首页 > 代码库 > 匿名内部类
匿名内部类
为什么有内部类
每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多重继承的解决方案变得更加完整。
如何定义一个匿名内部类
以学校和老师的关系为例
//学校类class School{ public static Teacher getTeacher(){ //匿名内部类 return new Teacher(){ public void teaching(){ System.out.println("张三老师在讲课"); } }; }}//老师类abstract class Teacher{ public abstract void teaching();}//测试类public class Annoymous { public static void main(String[] args) { Teacher t = School.getTeacher(); t.teaching(); }}
----------------------
Output: 张三老师在讲课
Teacher类是一个抽象类,都知道抽象类是无法直接new的, 所以必须先继承Teacher才能new, 上述代码可以通过编译,说明 创建一个匿名内部类它包含了以下步骤:定义本类 , 继承父类 ,实现类 , 创建实例
缺点
它仅能被使用一次,创建匿名内部类时它会立即创建一个该类的实例,该类的定义会立即消失,所以匿名内部类是不能够被重复使用,如果多次调用匿名内部类,建议重新定义类。
注意事项
1.匿名内部类中是不能定义构造函数的。
2.匿名内部类中不能存在任何的静态成员变量和静态方法。
3.使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口
4.匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法
使用的形参必须为final
我们给匿名内部类传递参数的时候,若该形参在内部类中需要被使用,那么该形参必须要为final
为什么呢?
内部类和外围类,编译后是两个class文件, 内部类仅仅保存了对外围类的引用
public class OuterClass { public void display(final String name){ //内部类 class InnerClass{ void display(){ System.out.println(name); } } }
内部类InnerClass获取形参的过程如下:
第一步: 把形参进行值拷贝
public class OuterClass$InnerClass { public InnerClass(String name){ this.InnerClass$name = name; }
第二步:使用内部类的属性
public void display(){ System.out.println(this.InnerClass$name + "----" + this.InnerClass$age ); }
内部类并不是直接调用方法传递的参数,而是利用自身的构造器对传入的参数进行备份,调用的实际上时自己的属性而不是外部方法传递进来的参数。
进一步的分析:
从作用域的角度: 外部方法的参数name, 作用域是整个外围类,当然也包括内部类, 内部类中使用的name, 作用域是整个内部类 , 如果在内部类中,对name值进行了修改,
此时外围类中name的值是不会发生改变的, 这就产生了矛盾, 程序自然是不会接受的
所以为了保持参数的一致性,就规定使用final来避免形参的不改变。
匿名类的初始化
匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用代码块达到构造器的效果
public class OutClass { public InnerClass getInnerClass(final int age,final String name){ return new InnerClass() { int age_ ; String name_; //构造代码块完成初始化工作 { age_ = age; name_ = name; } } public String getName() { return name_; } public int getAge() { return age_; } }; }
匿名内部类