一. 接口
a.接口:当一些具体的事物具有特殊的功能,而这些特殊的功能又不能写在类中,JAVA提供了接口实现,关键字是interface
b.接口定义的格式:
interface接口名{
}
c.接口的特点:
成员变量:接口的成员变量只能是常量,默认修饰符是public static final
成员方法:接口中的成员方法只能是抽象方法,默认修饰符为:public abstract
构造方法:接口中的无构造方法
d.注意:接口不能实例化,只能间接的通过非抽象的接口的子实现类实例化
接口的子类和接口是实现关系
e.接口子实现类格式:
class 接口子实现类名 implements 接口名{
}
f.接口子实现类可以是抽象类也可以是非抽象类:
如果接口的子实现类是抽象类,那么接口就没有办法实例化,所以就没有意义.
而非抽象的子实现类是可以实例化的
例如:
动物类中有具体的动物:猫;
有些猫具有跳高的额外功能
所以:需要将跳高功能定义为一个接口中的抽象方法
接口实例化的时候可以利用接口多态的方法实现:
代码如下:
输出结果:
g.重点:接口的抽象类的区别:
成员变量:
接口中的成员变量只能是常量,默认修饰符为:public staticfinal
抽象类中的成员变量既可以是常量,也可以是变量;
成员方法:
接口中的成员方法只能是抽象方法,默认修饰符为:public abstract
抽象类中的成员方法既可以是抽象方法又可以是非抽象方法
构造方法;
接口中的没有构造方法;
抽象类中可以有构造方法;
h.类与类,类与接口,接口与接口的关系:
1)类与类的关系:
继承关系,支持单继承和多层继承,不支持多继承;
2)接口与接口之间的关系:
继承关系,支持单继承和多继承;
3)类与接口之间的关系:
实现关系,可以单实现也可以多实现,并且类可以继承另一个类的同时去实现多个接口
例如:
有两个接口:Monther和Father
接口sisiter可以多继承Monther和Father
类son可以继承object类的同时去实现Monther和Father接口
代码实现如下:
输出结果:
二.内部类
a. 内部类:在类中定义了另一个类(A类中定义了B类,B类就是A类的内部类)
b. 内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有;
外部类可以直接访问内部类的成员吗?
外部类不能直接访问内部类的成员,需要创建内部类的对象,通过内部类对象调用方法;
c. 内部类的分类:
成员内部类:在外部类的成员位置(在方法外外部类中)
局部内部类:在外部成员的局部位置(在方法中)
(一)成员内部类:
1)如何访问内部类的成员:
不能直接创建对象;
访问格式:
外部类名.内部类名 对象名=外部对象.内部对象;
分析:外部类中有私有变量num;用内部类中的show()方法可以访问,而内部类中的show()方法只能通过内部类的对象来调用,而创建内部类对象时就是以上格式;
代码如下:
运行结果:
2)成员内部类有关的修饰符:
private:可以是是一个私有的内部类,目的是保护数据的安全性;
成员内部类如果是私有的,那么就不能直接创建对象,就要通过创建外部类的对象,然后外部类对象调用外部类中的方法,外部类的方法中可以创建成员内部类的对象,然后访问成员内部类中的数据成员;
例如:
static:成员内部类可以是一个静态的内部类:
静态成员内部类访问外部类数据,外部类数据必须也是静态的;
成员静态内部类访问自己内部成员格式:
注意:此时静态成员内部类不能通过以下的方式来访问本类中的成员
外部类名.内部类名 对象名=外部对象.内部对象;
静态成员内部类访问自己本类数据成员的正确格式:
外部类名.内部类名 对象名=new 外部类名.内部类名();
例如:
(二)局部内部类
1)局部内部类的访问:
局部内部类的访问是在局部内部类所在的方法中创建一个局部内部类对象,然后通过局部内部类对象调用局部内部类中的数据成员.
面试题:
2)局部内部类访问局部变量,有什么要求:
要求:局部内部类访问局部变量,需要让局部使用final修饰.因为局部变量是随着方法的调用而存在,随着方法调用完毕而消失;消失的时候不会立即消失,而是等待GC空闲时刻进行垃圾回收,此时method()调用完毕,可是局部内部类还在访问着,所以此时就需要将局部变量用final修饰
分析: 有外部类Outer6
外部类中有私有成员变量num,
局部内部类在外部类中的method()方法中,
method()中有局部变量num2,
局部内部类要访问num2,就必须将num2设置为final,
访问局部内部类时应该在method()方法中创建局部内部类对象,
通过局部内部类对象调用局部内部类中的数据成员.
测试类:
测试类中只需要创建一个外部类对象,
通过外部类对象调用method()方法.
代码如下:
运行结果:
d. 匿名内部类:
1.匿名内部类的前提条件:
有一个类或者接口存在:
这个类可以是具体类也可以是抽象类.
2.匿名内部类的格式:
new 类名/接口名(){
方法重写;
};
当想调用匿名内部类重写的成员方法时,如何调用?
new 类名/接口名(){
method(){
}
}.medthod();
3.匿名内部类的本质:
需要继承该类或实现该接口的子类对象;
注意: 内部类与外部类之没有直接继承关系.
面试题:
分析:
外部类Outer8:有成员变量num=10;
成员内部类Inner8:Inner8中有变量num=20;
成员内部类中有method()方法:method()有局部变量num=30;
测试类:
创建了一个成员内部类对象oi;
用对象oi去调用method();
补充method()方法,使其在控制台输出:30,20,10
System.out.println(num);//就近原则,输出method()方法中的num;
System.out.println(this.num);//代表当前类的对象:Inner8类中
System.out.println(newOuter().num);//使用匿名对象去调用成员变量num;
或者System.out.println(Outer.this.num);//使用外部类名.this去调用成员变量(外部类限定this)
代码如下:
运行结果:
一.形式参数与返回值是引用类型时:
1)返回值是引用类型时:
类:返回的是该类的对象;
抽象类:返回的是该抽象类的子类对象;
接口:返回的是该接口的子实现类对象;
2)形式参数是引用类型时:
类:传的是该类的对象;
抽象类;传的是该抽象类的子类对象;
接口:传的是该接口的子实现类对象;
分析:
有接口Love2,里面有抽象方法love();
接口Love2的子实现类Student,重写love()方法;
类PersonDemo2里面有返回类型为Love2的getLove2()方法
getLove2()里面返回一个Student3类型的对象;
要求:
实现Students3里面重写的love()方法;
测试类:
使用链式编程调用
new PersonDemo2().getLove2().love();
代码如下:
运行结果: