以下均來源於網絡整理
一、內部類
https://www.cnblogs.com/wfq9330/p/8760031.html
定義:根據創建位置的不同,分爲成員的、方法的、匿名的。接口中的內部類叫做接口內部類。
理解:在類的內部創建,那就是類的一部分,跟屬性、方法同級。這也就解釋了爲何能訪問外部私有成員,我是你的一部分,我當然可以訪問了。
1、成員內部類
class Outer { private int i = 1; class Inner { public void fun() {System.out.println("Outer I=" + i)} } }
2、方法內部類
class Outer{ private String test; public void fun() { final int i = 1; // 被方法內部類訪問的局部變量必須被final修飾 class Inner { // 方法內部類 不能有訪問修飾符,比如public public void print() { System.out.println("Method I=" + i + test); } } } }
3、匿名內部類
interface USB { public abstract void start() } class Outer{ public void fun() { final int i = 1; // 被匿名內部類訪問的局部變量必須被final修飾 new USB(){ @Override public void start(){ System.out.println("local_var_i=" + i); } }.start(); } }
4、靜態內部類
class Outer{ private int i = 1; static class Inner{ // 不能訪問外部類的非靜態成員 public void fun() { } } }
5、接口內部類
interface USB { class Inner { // 默認是public static,即可以直接new USB.Inner(); } }
二、匿名內部類
https://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html
匿名內部類也就是沒有名字的內部類
正因爲沒有名字,所以匿名內部類只能使用一次,當然也就不能有構造器
但使用匿名內部類:必須繼承一個父類或實現一個接口
使用匿名內部類課使代碼更加簡潔、緊湊,模塊化程度更高。
內部類能夠訪問外部內的一切成員變量和方法,包括私有的,而實現接口或繼承類做不到,所以匿名內部類作用大
1、匿名內部類的基本實現
abstract class Person { public abstract void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
運行結果:eat something
紅色加粗的代碼,就是匿名內部類,繼承了 Person 類,卻沒有給出這個類的名字,直接實例化它並賦值給 p
如果不用匿名內部類,我們會這樣寫
abstract class Person { public abstract void eat(); } class Child extends Person { public void eat() { System.out.println("eat something"); } } public class Demo { public static void main(String[] args) { Person p = new Child(); p.eat(); } } 運行結果:eat something
先定義一個類,名字叫Child,用到的時候,Person p = new Child(); 用它的名字實例化它,然後賦值給 p,對比發現,定義匿名內部類,後面有大括號接類的方法,普通的實例化,沒有大括號的內容
2、在接口上使用匿名內部類
interface Person { public void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
運行結果:eat something
3、Thread類的匿名內部類實現
public class Demo { public static void main(String[] args) { Thread t = new Thread() { public void run() { for (int i = 1; i <= 5; i++) { System.out.print(i + " "); } } }; t.start(); } } 運行結果:1 2 3 4 5
4、Runnable接口的匿名內部類實現
public class Demo { public static void main(String[] args) { Runnable r = new Runnable() { public void run() { for (int i = 1; i <= 5; i++) { System.out.print(i + " "); } } }; Thread t = new Thread(r); t.start(); } } 運行結果:1 2 3 4 5
三、匿名類
我個人理解,一個沒有名字的類--匿名類,必須依賴於一個現有的類中,才能存在,你在類外部定義一個匿名類,語法是通不過的,所以匿名類就是匿名內部類
鏈接:https://www.zhihu.com/question/49330534/answer/115478102
當你想使用一個類的protected 方法時,但是又不和這個類在同一個包下,你是沒辦法調用的。
這時候匿名類就派上用場了,你可以聲明一個匿名類繼承該類,並定義一個方法,在這個方法內使用super調用你想調用的那個方法(其實你也可以寫個類繼承這個類,就能調用父類的protected方法了,但是匿名類更簡潔,因爲你只想調用這個方法而已)
五、匿名對象與匿名內部類
匿名對象:沒有名字的對象。
非匿名對象:
ClassName c=new ClassName();
c.run();
匿名對象:
new ClassName().run();
注意事項:
1、當對象對方法僅進行一次調用的時候,就可以簡化成匿名對象。
2、兩個匿名對象不可能是同一個對象。
3、一般不給匿名對象賦予屬性值,因爲永遠無法獲取到。
4、運行一次,直接就被回收掉了,節省內存空間。