首页 > 技术文章 > 匿名内部类常见用法

hetaoyuan 2020-02-18 16:23 原文


class
Main { public static void main(String[] args) { for (int i = 0; i < 3; i++) { Thread thread = new Thread(){ @Override public void run(){ for (int i = 0; i < 3; i++) { System.out.print(i+" "); } System.out.println(); } }; System.out.println(thread.getName()); thread.start(); } } }
Thread-0
Thread-1
Thread-2
0 1 2 0 1 2 0 1 2 

Thread匿名内部类

 

 

 

Runnable的匿名内部类

class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            Runnable runnable = new Runnable(){
                @Override
                public void run() {
                    for (int i = 0; i < 3; i++) {
                        System.out.print(i+" ");
                    }
                    System.out.println();
                }
            };
            Thread thread = new Thread(runnable);
            System.out.println(thread.getName()+" "+thread.getId());
            thread.start();
        }

    }
}
Thread-0 11
Thread-1 12
Thread-2 13
0 1 2 
0 1 2 
0 1 2 

 

接口匿名内部类

interface icomputer{
    void buyPC();
}
class Demo{
    public static void main(String[] args) {
        icomputer icomputer = new icomputer() {
            @Override
            public void buyPC() {
                System.out.println("买一台MAC");
            }
        };
        icomputer.buyPC();
    }
}
买一台MAC

 

抽象类匿名内部类

abstract  class animals{
    abstract void eat();
}
class People{
    public static void main(String[] args) {
        animals animals = new animals() {
            @Override
            void eat() {
                System.out.println("吃面条");
            }
        };
        animals.eat();
    }
}
吃面条

 

 

为什么要有匿名内部类?

eg:

abstract  class animals{
    abstract void eat();
}
class People extends animals{

    @Override
    void eat() {
        System.out.println("吃面条");
    }
}

class Demo{
    public static void main(String[] args) {
        animals animals = new People();
        animals.eat();
    }
}



class Demo1{
    public static void main(String[] args) {
        animals animals = new animals(){
            @Override
            void  eat(){
                System.out.println("吃面条");
            }
        };
        animals.eat();
    }
}

因为如果抽象类或接口的实现类我们只实现一次,那么重新写一个实现类会比较麻烦,用来简化代码,所以引出了匿名内部类。匿名内部类必须重写接口或者抽象类中的全部抽象方法,可以调用抽象类中的静态常量或者抽象类中非private修饰的变量

 

abstract class animals{
  int age = 6;
  private int tall;
    abstract void eat();
    abstract void sleep();
}



class Demo1{

    public static void main(String[] args) {
       animals animal = new animals() {
           @Override
           public void eat() {
               System.out.println("吃面条");
           }

           @Override
           public void sleep() {
               System.out.println("年龄为"+age);
               System.out.println("上床睡觉");
           }
           public void print(){
               System.out.println(age);
           }

       };
        animal.eat();
        animal.sleep();
//        ((animals) animal).print();  该条语句无法被执行,因为抽象类中不含该方法
       
    }
}
吃面条
年龄为6
上床睡觉

 

1、匿名内部类不能定义任何静态成员、方法。

2、匿名内部类中的方法不能是抽象的;

3、匿名内部类必须实现接口或抽象父类的所有抽象方法。

4、匿名内部类不能定义构造器;

5、匿名内部类访问的外部类成员变量或成员方法必须用static修饰;

6、内部类可以访问外部类私有变量和方法。

1、匿名内部类因为没有类名,可知匿名内部类不能定义构造器

2、因为在创建匿名内部类的时候,会立即创建它的实例,可知匿名内部类不能是抽象类,必须实现接口或抽象父类的所有抽象方法

3、匿名内部类会继承一个父类(有且只有一个)或实现一个接口(有且只有一个),实现父类或接口中所有抽象方法,可以改写父类中的方法,添加自定义方法。

5、当匿名内部类和外部类有同名变量(方法)时,默认访问的是匿名内部类的变量(方法),要访问外部类的变量(方法)则需要加上外部类的类名。

6、从Outer.class反编译代码中可看出自动生成了两个静态方法:access$0()和access$1(),并在测试3和测试4中通过Outer类名直接调用,这样实现了内部类对外部类私有成员变量和方法的访问。可知内部类可以访问外部类私有变量和方法


疑问

匿名内部类不能含有static的变量和方法。但是测试发现变量可以被static final修饰,为什么?

主要是因为final类型在编译期间jvm有优化,常量池会维护这些变量。虽然非静态内部类不能脱离外部类这个上下文实例化,但是常量池使得final变量脱离了类实例化这个条件,编译期间便可确定。

推荐阅读