一、抽象类的定义格式
1、概念:包含抽象方法的类叫做抽象类。
2、定义抽象类的关键字:abstract class
格式:
public abstract class抽象类名 extends 抽象类或类{
访问修饰符(public,protected,private)数据类型属性名;
访问修饰符抽象类名(数据类型参数名,…){
//方法体
}
访问修饰符返回值数据类型方法名(数据类型参数名,…){
//方法体
}
访问修饰符 abstract 返回值数据类型方法名(数据类型参数名,…);
//注意:抽象方法没有方法体
}
2、抽象类和类的区别:
1)抽象类可以比类多定义一种抽象方法,而一般的类不能定义抽象方法。
2)抽象类不能实例化对象,而类可以实例化对象。(因为抽象类中可能含有抽象方法,抽象方法是不能被调用的,故实例化抽象类对象也没有意义,故抽象类不能实例化对象。)
3、一般类继承抽象类与抽象类继承抽象类的区别:
一般的类继承抽象类后,必须实现抽象类中所有的抽象方法;
抽象类继承抽象类后,可以不用实现抽象类中所有的抽象方法,只要实现需要的方法即可。
Eg:
public abstract class Student {
private String name;
//定义构造方法
public Student(String name) {
this.name = name;
}
//定义一般方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//定义抽象方法
public abstract void study();//定义了一个学习的抽象方法study()
public abstract void exam();//定义了一个考试的抽象方法exam()
}
//定义一个一般的类UNStudent继承抽象类Student
public class UNStudent extends Student{
public UNStudent(String name) {
super(name);
}
//实现抽象类中所有的抽象方法
@Override
public void exam() {
setName("张三");
System.out.println(getName()+"在考试。");
}
public void study(){
setName("张三");
System.out.println(getName()+"在学习。");
}
}
//定义一个抽象类ComStudent继承抽象类Student
public abstract class ComStudent extends Student{
public ComStudent(String name) {
super(name);
}
//可以选择性的去实现抽象类中的抽象方法
public void study(){
setName("张三");
System.out.println(getName()+"在学习。");
}
}
二、接口的定义格式
1、 定义接口的关键字是:interface
格式:
public interface 接口名{
//常量
public static final 常量名 = 值;
//抽象方法
public abstract 返回值数据类型方法名(数据类型参数名,…);
}
接口中默认的访问修饰符是public
2、 接口的实现
关键字:implements
格式:
public class 类名 implements 接口名,…{
}
注意:当类实现接口后,类必须实现接口中的所有抽象方法。接口不能实例化对象。
当继承和实现接口同时存在时,要先继承,再实现接口。
public class 类名 extends 父类名 implement 接口名,...{
//实现接口的抽象方法
}
接口是告诉我们要做什么事情,接口的实现则是告诉我们怎么做这些事情。
接口的实现相当于类中的继承,所以接口的实现中也存在自动转型。
3、 接口和类的区别:
|
接口 |
类 |
1 |
关键字:interface |
关键字:class |
2 |
接口只能定义常量和抽象方法 |
类可以定义任意访问修饰符的方法、属性、常量 |
3 |
接口的默认访问修饰符是public |
类的默认访问修饰符就是默认的(public,protected,private和默认的)。 |
4 |
接口可以实现多重继承 |
类只能实现单继承 |
5 |
接口不能用来实例化对象 |
类可以用来实例化对象 |
Eg:
//定义一个父类Sport:运动类
public class Sport {
//定义普通方法jump(),run()
public void jump(){
System.out.println("动作:跳跃");
}
}
//定义了一个接口Dance()
public interface Dance {
//定义抽象方法gyrate():旋转
public void gyrate();
}
//定义一个接口Music(音乐)
public interface Music {
//定义一个抽象方法play()
public void play();
}
//定义一个子类Eurythmics(艺术体操类)继承父类Sport,并实现了两个接口Dance,Music,当继承和实现接口同时存在时,要先继承,再实现接口
public class Eurythmics extends Sport implements Dance,Music{
//实现Dance接口中的抽象方法
public void gyrate() {
System.out.println("舞蹈动作:旋转");
}
//实现Music接口中的抽象方法
public void play() {
System.out.println("配乐:天空之城");
}
}
//定义一个比赛类Match
public class Match {
public static void main(String[] args) {
Eurythmics e=new Eurythmics();//实例化一个艺术体操对象
e.gyrate();//子类实现了Dance接口,子类的对象调用Dance接口中的gyrate()方法
e.play();//子类实现了Music接口,子类的对象调用Music接口中的play()方法
e.jump();//子类继承了父类中的jump()方法,子类的对象调用了jump()方法
System.out.println();
dancePart(e);//e被看作一个Dance对象,相当于e自动转型,作为参数传入dancePart()
musicPart(e);//e被看作一个Music对象,相当于e自动转型,作为参数传入musicPart()
sportPart(e);//e被看作一个Sport对象,相当于e自动转型,作为参数传入sportPart()
}
//定义舞蹈部分的方法
public static void dancePart(Dance dance){
dance.gyrate();
}
//定义音乐部分的方法
public static void musicPart(Music music){
music.play();
}
//定义运动部分的方法
public static void sportPart(Sport sport){
sport.jump();
}
}
结果:
舞蹈动作:旋转
配乐:天空之城
动作:跳跃
舞蹈动作:旋转
配乐:天空之城
动作:跳跃
4、使用接口的原因:
1)核心原因:为了能够自动转型为多个基类,这样给程序带来了灵活性。(如上例)
2)将代码完全与接口的实现分离,不同的子类可以对接口中定义的抽象方法有不同的实现,这也是一种规范,在团队合作中,接口可以是分工变得明确,接口确定下来后,就可以同时进行开发,提高开发效率。
3)使用接口还有使用方便,可读性强,结构清晰等优点。
三、 事件原理
1、 事件处理源:
1) 概念Java中所有的组件对象都是可以作为事件源。包括容器和元素组件。
容器布局不是事件源。
2) 如何判断哪个对象是事件源对象?
根据所操作的方法,看操作时反应在哪个组件上,那么该组件就是事件源。
如图:
当用鼠标点击登录按钮的时候,按钮是事件源;当在输入框输入一个账号,按回车时,输入框是事件源;当用鼠标点击“账号”这个标签的时候,标签是事件源;当鼠标点击窗体是,窗体是事件源……
2、 事件类型(监听器方法)
监听器方法:在组件上发生动作后,要捕获动作的方法。
分局发生的动作以及所要使用的值来决定使用不同的事件类型。
常用的事件接口 |
事件类型(监听器方法) |
ActionListener 动作监听器接口 |
AddActionListener(对象名); |
MouseListener 鼠标监听器接口 |
addMouseListener(对象名); |
MouseMotionListener 鼠标移动监听器接口 |
addMouseMotionListener(对象名); |
KeyListener 按键处理监听器接口 |
addKeyListener(对象名); |
3、 事件处理对象
事件处理对象的作用:当监听器方法捕获到动作后,那么就要交给事件处理对象来处理;事件处理对象会实现对应的监听器接口,来完成最后的处理。
4、 事件的执行流程
1) 确定事件源对象
2) 确定要发生的是什么类型的事件
3) 给事件源添加监听器方法
4) 实例化事件处理类的对象(定义类实现事件接口,并且实现接口中的方法)
5) 给监听器方法绑定事件处理类对象
只要事件源发生监听器方法能捕获到的动作,那么方法就会捕获动作信息以及事件源的相关信息,然后激活事件处理对象,将收集的信息和动作一并交给事件处理对象,事件处理对象会根据信息自动调用事件处理方法。
Eg1:实现QQ登录界面登录的过程,做账号和密码验证。
QQ界面上的关键代码如下:
JButton jb=new JButton("登 录");
jp2.add(jb);
//jcb为下拉框对象,jpf为密码输入框对象,jf为登录窗口对象
LoginListener ll=new LoginListener(jcb,jpf,jf);
jb.addActionListener(ll);
定义事件处理类:
//定义LoginListener类实现了事件接口ActionListener
public class LoginListener implements ActionListener {
private JComboBox jcb;
private JPasswordField jpf;
private JFrame jf1;
//定义构造方法,便于在实例化事件处理类对象时,将qq界面上将下拉框、密码输入框、登录窗口的对象的地址传过来,进行事件处理
public LoginListener(JComboBox jcb,JPasswordField jpf,JFrame jf1){
this.jcb=jcb;
this.jpf=jpf;
this.jf1=jf1;
}
/**
* 事件处理方法
*/
public void actionPerformed(ActionEvent arg0) {
String jcbStr=(String)jcb.getSelectedItem();//获取下拉列表中选中项,并把其转成String类型
String jpfStr=new String(jpf.getPassword());
//当账号和密码匹配时,出现新的QQ界面(窗口),同时登录窗口关闭
if(jcbStr.equals("12345678")&&jpfStr.equals("123")){
JFrame jf=new JFrame("QQ2013");
jf.setSize(260,600);
jf.setResizable(true);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
jf.setVisible(true);
jf1.setVisible(false);//将登录窗口隐藏起来
}else{
//当账号和密码不匹配时,弹出提示信息
JOptionPane.showMessageDialog(null, "请输入正确的账号和密码!");
}
}
}
1、点击“登录”按钮后,事件发生,事件源为“登录”按钮。
2、即将发生的事件为:当账号和密码匹配时,出现新的QQ界面(窗口),同时登录窗口关闭;当账号和密码不匹配时,弹出提示信息。
3、添加监听器方法addActionListener()
4、定义LoginListener类实现了事件接口ActionListener,实例化事件处理类的对象ll。
5、给监听器绑定事件处理对象ll。