匿名内部类的特征
1、匿名内部类的本质还是一个类
2、匿名内部类是一个内部类,嵌入在另一个类中
3、匿名内部类没有名字
4、匿名内部类同时也是一个对象
匿名内部类的引入
如果我们有一个IA接口,想使用接口中的方法,那么我们应该怎样做?
传统方法:
先实现IA接口 --->实现IA接口---> 创建实现IA接口对应类的对象---->调用方法
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer outer = new Outer();
outer.hi();
}
}
interface IA{
public void eat();
}
class Cat implements IA {
@Override
public void eat() {
System.out.println("小猫吃鱼~");
}
}
class Outer{
public void hi() {
Cat cat = new Cat();
cat.eat();
}
}
----------------------
小猫吃鱼~
传统方法可以实现需求,但是会显得冗余麻烦。如果进一步提出需求:接口中的方法只使用一次,以后再也不使用了,那么就可以使用匿名内部类精炼的来解决这个问题,不用创建类来实现接口也可以
匿名内部类方法
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer outer = new Outer();
outer.hi();
}
}
interface IA {
public abstract void eat();
}
class Outer {
public void hi() {//方法
IA cat = new IA() {
@Override
public void eat() {
System.out.println("小猫吃鱼~");
}
};
cat.eat();
}
}
-------------------
小猫吃鱼~
而此时我们并没有实例化这个接口的类,便实现了里面的方法,所以称之为匿名内部类
其实这个类是被临时创建的,在JDK中有类的名字
以上面为例,在JDK底层上会创建一个实现了IA接口的类Outer$1,该类被创建的瞬间就会实例一个Outer$1对象,然后把对象地址传递给 cat
匿名内部类只能使用一次,使用完就不能再用了。
JDK底层匿名内部类创建过程
JDK底层创建Outer$1类的过程大概如下(以上面代码为例)
class Outer$1 implements IA {
@Override
public void eat() {
System.out.println("小猫吃鱼~");
}
}
然后 new Outer$1() , 把对象返回给cat
我们可以验证一下 cat 的运行类型是不是Outer$1
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer outer = new Outer();
outer.hi();
}
}
interface IA {
public abstract void eat();
}
class Outer {
public void hi() {//方法
IA cat = new IA() {
@Override
public void eat() {
System.out.println("小猫吃鱼~");
}
};
cat.eat();
System.out.println("cat对象的运行类型=" + cat.getClass);
}
}
-------------------
小猫吃鱼~
cat对象的运行类型=class com.zkyedu.innerclass.Outer$1
可以看到结尾运行类型正是Outerus$1
如果创建想创建不同的对象,那么匿名内部类的类名后面的数字会逐渐增加Outerus$1 ,Outerus$2 ..........
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer outer = new Outer();
outer.hi();
}
}
interface IA {
public abstract void eat();
}
class Outer {
public void hi() {//方法
IA cat = new IA() {
@Override
public void eat() {
System.out.println("小猫吃鱼~");
}
};
IA dog = new IA() {
@Override
public void eat() {
System.out.println("小狗吃骨头~");
}
};
cat.eat();
System.out.println("cat对象的运行类型=" + cat.getClass);
System.out.println("dog对象的运行类型=" + dog.getClass);
}
}
-------------------
小猫吃鱼~
cat对象的运行类型=class com.zkyedu.innerclass.Outer$1
dog对象的运行类型=class com.zkyedu.innerclass.Outer$2
!!!注意匿名内部类的作用域是在定义它的方法或者代码块中,外部其他类不能访问匿名内部类,如果想访问可以创建外部类对象,然后调用方法。
匿名内部类的使用细节
1、可以直接访问外部类的所有成员,包含私有的
2、不能添加访问修饰符,因为它的地位就是一个局部变量
3、.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)
4、作用域 : 仅仅在定义它的方法或代码块中