首页 > 代码库 > 匿名内部类

匿名内部类

为什么有内部类

每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多重继承的解决方案变得更加完整。

如何定义一个匿名内部类

以学校和老师的关系为例

//学校类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_;            }        };    }

 

匿名内部类