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變量脫離了類實例化這個條件,編譯期間便可確定。
