1. 匿名内部类

  • 没有(或者不需要)命名来初始化类,就称为匿名内部类。
  • 在这四种内部类中,以后的工作可能遇到最多的是匿名内部类,所以说匿名内部类是最常用的一种内部类。

什么是匿名对象?

  • 如果一个对象只要使用一次,那么我们就是需要new Object().method()。 就可以了,而不需要给这个实例保存到该类型变量中去。这就是匿名对象。

匿名内部类跟匿名对象是一个道理:

  • 匿名对象:我只需要用一次,那么我就不用声明一个该类型变量来保存对象了。
  • 匿名内部类:我也只需要用一次,那我就不需要在类中先定义一个内部类,而是等待需要用的时候,我就在临时实现这个内部类,因为用次数少,可能就这一次,那么这样写内部类,更方便。不然先写出一个内部类的全部实现来,然后就调用它一次,岂不是用完之后就一直将其放在那,那就没必要那样。

如何使用匿名内部类:

  • 1.匿名内部类需要依托于其他类或者接口来创建
  • 如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类
  • 如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。
  • 2.匿名内部类的声明必须是在使用new关键字的时候
  • 匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。

【示例】:

  • A是一个类(普通类、抽象类都可以),依托于A类创建一个匿名内部类对象
  • 总结: { }里面是类的具体声明,new B{ } 会返回一个这个匿名内部类的实例对象。

匿名内部类特点:

  1. 匿名内部类除了依托的类或接口之外,不能指定继承或者实现其他类或接口,同时也不能被其他类所继承,因为没有名字。
  2. 匿名内部中,我们不能写出其构造器,因为没有名字。
  3. 匿名内部中,除了重写上面的方法外,一般不会再写其他独有的方法,因为从外部不能直接调用到。(间接是调用到的)

示例1:

interface Work {
    void doWork();
}

public class AnonymousOuterClass {
    private String name = "AnonymousOuterClass";
    private static int age = 21;

    public void say() {
        System.out.println("Say...");
    }

    public static void go() {
        System.out.println("Go...");
    }

    public void test() {
        final int i = 90;
        Work w = new Work() {
            @Override
            public void doWork() {
                //             打印外部类的属性
                System.out.println(AnonymousOuterClass.this.name);
                System.out.println(AnonymousOuterClass.age);
                //              调用外部类的方法实例方法
                AnonymousOuterClass.this.say();
                //              调用外部类的方法静态方法
                AnonymousOuterClass.go();
                //              打印方法里面定义的常量
                System.out.println(i);
            }
        };
        w.doWork();
    }
}

class Test {
    public static void main(String[] args) {
        new AnonymousOuterClass().test();
    }
}

Android匿名类导致内存泄漏_内部类

示例2:

public class AnonymousOuterClass {
    public void say() {
        System.out.println("Say...");
    }

    public void test() {
        new AnonymousOuterClass() {
            public void say() {
                System.out.println("Say No...");
            }
        }.say();
    }
}

class Test {
    public static void main(String[] args) {
        new AnonymousOuterClass().test();
    }
}

Android匿名类导致内存泄漏_匿名内部类_02

我们可以试一下不用匿名内部类和用匿名内部类实现一个接口中的方法的区别

1.【不用匿名内部类】:

Android匿名类导致内存泄漏_内部类_03

2.【用匿名内部类】:

interface Test1 {
    public void method();
}

public class Test {
    public static void main(String[] args) {
        //如果我们需要使用接口中的方法,我们只需要走一步,就是使用匿名内部类,直接将其 类的对象创建出来。
        new Test1() {
            public void method() {
                System.out.println("实现了Test接口的方法");
            }
        }.method();
    }
}

Android匿名类导致内存泄漏_java_04


小结:

  • 解析:其实只要明白一点,new Test1(){实现接口中方法的代码}; Test1(){…}这个的作用就是将接口给实现了,只不过这里实现该接口的是一个匿名类,也就是说这个类没名字,只能使用这一次,我们知道了这是一个类, 将其new出来,就能获得一个实现了Test1接口的类的实例对象,通过该实例对象,就能调用该类中的方法了,因为其匿名类是在一个类中实现的,所以叫其匿名内部类,不要纠结为什么Test1(){…}就相当于实现了Test1接口,这其中的原理等足够强大了,在去学习,不要钻牛角尖,这里就仅仅是需要知道他的作用是什么,做了些什么东西就行。