匿名内部类常见用法
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变量脱离了类实例化这个条件,编译期间便可确定。