重点掌握匿名内部类的使用!
1、内部类可以随意访问外部类的成员,包括私有的属性,而外部类不可以。
2、内外部类有重名属性时,内部类的访问采用就近原则,如想访问外部的成员,则用外部类名.this.属性名。
内部类分类,四种
局部内部类
第七条解释:Outer02.this本质是一个外部类的对象。
匿名内部类
应用场景:一个函数中需要使用接口,但接口实现的类全程序中只会用一次,如果单独创建类会累赘,为了简化开发实现了匿名内部类。
1、本质仍然是类
2、内部类(如方法体、代码块内)
3、该类没有名字(系统给了但我们看不见不可用)
4、同时还是一个对象
5、相当于JDK底层立即创建了匿名内部类,并将地址返回给了tiger
6、匿名内部类使用一次,这个类就不能再使用,但给对象返回了实例,我们的对象是可以反复用的。
//tiger编译类型:IA
//tiger运行类型:匿名内部类
class A{
public void f1(){
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("tigercry");
}
};
tiger.cry();
System.out.println(tiger.getClass());
}
}
interface IA{
void cry();
}
输出结果(匿名内部类底层分配的类名):
tigercry
class com.innerclass.A$1
匿名内部类使用细节
1、语法奇特,既有类的定义,又本身是一个对象,故可以直接调用匿名内部类方法。如下:
new IA(){
@Override
public void cry() {
System.out.println("ok");
}
}.cry();
2、可以随意访问外部类所有成员,包括私有
3、不能添加访问修饰符,因为其地位是一个局部变量。
4、内外互相访问的规则同局部内部类。
匿名内部类最佳实践案例
public class AnonymousInnerClassDetial {
public static void main(String[] args) {
f1(new AA() {
@Override
public void show() {
System.out.println("aaShow");
}
});
}
public static void f1(AA aa){
aa.show();
}
}
interface AA{
void show();
}
其中,实际上是向f1函数传递了如下实参:
new AA() {
@Override
public void show() {
System.out.println("aaShow");
}
}
类似上述使用方法,课堂上的练习题:
public class InnerClassExercise02 {
public static void main(String[] args) {
Cellphone cellphone = new Cellphone();
cellphone.alarmclock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
cellphone.alarmclock(new Bell() {
@Override
public void ring() {
System.out.println("小伙伴上课啦");
}
});
}
}
interface Bell{
void ring();
}
class Cellphone{
public void alarmclock(Bell bell){
bell.ring();
}
}
匿名内部类涉及到的知识点
继承、多态、动态绑定、内部类等...
成员内部类
没有写在方法或代码块,而是直接写在外部类中成员的位置。 ”成员内部类“
和外部类的其他成员一样,为整个类体,比如前面案例,在外部类的成员方法中创建成员内部类对象,再调用方法。
外部其他类访问成员内部类的三种方法
1、outer.new Inner();
2、new Outer().new Inner();
3、在外部类中编写一个可以返回Inner类对象的方法。
静态内部类
静态类在地位上是一个静态成员,只能访问外部类的静态属性。
外部其他类访问静态内部类的方法
有三种:
1、outer.new Inner.f1();
2、new Outer().new Inner.f1();
3、通过一个方法来获取一个静态内部类的对象实例。
内外属性重名时
由于是静态的,所以直接外部类名.属性名就可以了,不必再加this