您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java內部類示例分析”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Java內部類示例分析”文章能幫助大家解決問題。
將一個類定義在另一個類的內部或者接口內部或者方法體內部,這個類就被稱為內部類,我們不妨將內部類所在的類稱為外圍類,除了定義在類,接口,方法中的內部類,還有一種特殊的內部類,那就是使用關鍵字new創建一個匿名類的對象,而這個匿名類其實就是一個內部類,具體說是一個匿名內部類,經常用于傳入構造器實參構造對象,例如PriorityQueue對象的創建。
一個類定義在另一個類的內部或者接口內部,并且沒有static修飾時,這個內部類就稱為實例內部類,使用static修飾時,這個內部類被稱為靜態內部類(嵌套類),將一個類定義在代碼塊內部,特別是方法體內部,這個內部類被稱為本地內部類或者局部內部類,還有一種就是上面所說的匿名內部類。
實例內部類的定義很簡單,就直接定義在外圍類的里面就可以了。問題是如何創建一個內部類對象,首先,需要明白內部類與外圍類中的成員變量與方法是平起平坐的,都是屬于外圍類對象的(無static修飾),所以想要內部類對象先得有外圍類對象,第一種創建內部類對象的方式就是使用一個方法返回一個內部類對象,并且這個內部類對象的類型為OutClassName.InnerClassName,即外圍類名.內部類名。
public class Outer { class Inner1 { private String str; public Inner1(String s) { this.str = s; } public String readStr() { return this.str; } } class Inner2 { private int val; public Inner2(int i) { this.val = i; } public int readVal() { return this.val; } } //創建內部類 public Inner1 creatInner1(String s) { return new Inner1(s); } public Inner2 creatInner2(int i) { return new Inner2(i); } public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner1 inner1 = outer.creatInner1("Inner1"); Outer.Inner2 inner2 = outer.creatInner2(2); System.out.println(inner1.readStr()); System.out.println(inner2.readVal()); } }
//output: Inner1 2 Process finished with exit code 0
當然,創建一個內部類還有其他的方法,就是使用外圍類的對象.new來創建一個內部類對象,語法為:
外部類對象.new 內部類構造方法;
public class Outer { class Inner1 { private String str; public Inner1(String s) { this.str = s; } public String readStr() { return this.str; } } class Inner2 { private int val; public Inner2(int i) { this.val = i; } public int readVal() { return this.val; } } public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner1 inner1 = outer.new Inner1("Inner1"); Outer.Inner2 inner2 = outer.new Inner2(2); System.out.println(inner1.readStr()); System.out.println(inner2.readVal()); } }
//output: Inner1 2 Process finished with exit code 0
內部類的特性不止如此,內部類還能與外圍類鏈接,首先實例內部類對象的創建是依賴外圍類對象的引用,實例內部類與外圍類的成員變量地位一樣,如果想要通過內部類對象訪問外圍類的成員變量與方法(特別是同名變量)。在內部類中,可以使用外圍類名.this獲取外圍類對象,然后使用獲得的這個外圍類對象來使用外圍類的變量與方法。
public class Outer { private String outStr; public Outer(String str) { this.outStr = str; } public void printOuter() { System.out.println(this.outStr); } class Inner { private String str; public Inner(String s) { this.str = s; } public String readStr() { return this.str; } //使用.this獲取父類對象引用 public Outer outer() { return Outer.this; } } public static void main(String[] args) { Outer outer = new Outer("outerString"); Outer.Inner inner = outer.new Inner("innerString"); Outer out = inner.outer(); out.printOuter(); } }
//output: outerString Process finished with exit code 0
其實內部類對象中有兩個this,直接使用this.成員獲取的是內部類對象自己的成員,而像上面使用外圍類名.this.成員獲取的是外圍類的成員,也就是說在內部類中this指向內部類對象自己的引用,外部類名.this指向外圍類對象的引用。
當出現內部類與外圍類變量名相同時,這兩個this就有很大的用處了。
public class Outer { public int a = 12; public int b = 16; public int c = 20; class Inner{ public int a = 8; public int c = 48; public int d = 2; public void printVal() { System.out.println("外圍類變量a=" + Outer.this.a); System.out.println("外圍類變量b=" + Outer.this.b); System.out.println("外圍類變量c=" + Outer.this.c); System.out.println("內部類變量a=" + this.a); System.out.println("內部類變量c=" + this.c); System.out.println("內部類變量d=" + this.d); } } public Inner creatInner() { return new Inner(); } public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.creatInner(); inner.printVal(); } }
//output: 外圍類變量a=12 外圍類變量b=16 外圍類變量c=20 內部類變量a=8 內部類變量c=48 內部類變量d=2 Process finished with exit code 0
如果沒有出現同名,直接獲取的成員即可,可以不用使用上面所說的this,出現同名,直接訪問的成員默認是內部類對象的。
內部類可以與外圍類的所有元素的訪問權限,所以我們可以嘗試使用內部類來遍歷輸出外圍類中的元素,雖然內部類與外圍類的成員地位是平等,但內部類畢竟也是類,它也可以像外圍類一樣繼承類和實現接口。
import java.util.Arrays; interface Selector{ //判斷是否迭代完全部元素 public boolean end(); //獲取當前元素 public Object current(); //迭代下一個元素 public void next(); } public class SequeArray { private Object[] items; private int usedSize; public SequeArray(int capacity) { items = new Object[capacity]; } public void add(Object val) { if (usedSize == items.length) items = Arrays.copyOf(items, 2 * usedSize); items[usedSize++] = val; } private class SequeSelector implements Selector{ private int index; public boolean end() { return index == usedSize; } public Object current() { return items[index]; } public void next() { if (index < usedSize) index++; } } public SequeSelector sequeSelector() { return new SequeSelector(); } public static void main(String[] args) { SequeArray array = new SequeArray(10); for (int i = 0; i < 10; i++) { array.add(i+1); } //發生了向上轉型 Selector selector = array.sequeSelector(); while (!selector.end()) { System.out.print(selector.current() + " "); selector.next(); } } }
//output: 1 2 3 4 5 6 7 8 9 10 Process finished with exit code 0
內部類的繼承有一點麻煩,因為內部類的構造器必須依賴外圍類的引用,所以需要一段特殊的語法來說明內部類與外圍類的關聯:
外圍類引用.super();
具體怎么使用看如下一段代碼:
public class Outer { class Inner{ } } class Person extends Outer.Inner { private String str; private int id; public Person(Outer out, String str, int id) { out.super(); this.str = str; this.id = id; } public void readVal() { System.out.println(this.str + this.id); } }
當內部類被繼承的時候,需要通過外圍類的引用傳入父類的構造方法中并調用super()才能通過編譯。
如果內部類繼承外部類,直接繼承即可,不需要這么麻煩。
程序生成一個java文件的字節碼文件時,命名為公共外部類$內部類。
內部類可以無限嵌套,一般沒人這么干。
靜態內部類也稱嵌套類,它就是在實例內部類的定義前加入一個static關鍵字,像下面這樣:
public class Outer { static class Inner{ } }
與實例內部類的區別是靜態內部類是屬于類的而不是屬于對象的,因此靜態內部類的創建不依賴與外部類對象,這是和實例內部類最大的區別之一。
public class Outer { static class Inner{ private String str; public Inner(String s) { str = s; } } public static void main(String[] args) { Outer.Inner inner = new Outer.Inner("我是靜態內部類!"); System.out.println(inner.str); } }
//output: 我是靜態內部類! Process finished with exit code 0
匿名內部類的用法我們已經見過了,就是創建PriorityQueue對象時,默認創建的是小堆,需要傳入比較器來創建大堆。
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; } });
像上面這種在方法中使用new關鍵字創建一個匿名類的對象作為實參,里面這個匿名類就是匿名內部類,創建過程中的Comparator匿名類對象是繼承所需傳參類型的,在這里也就是Comparator類。
如果使用自定義類型傳入優先隊列,是一定要實現比較器的,實現比較器最常見的方式就是匿名內部類與Lambda表達式。
假設我有一個Person類數組,需要對他們的name排序,如果不使用內部類,就需要在Person類中實現比較器。
import java.util.Arrays; import java.util.Comparator; class Preson { public String name; public Integer id; public Preson(String name, Integer id) { this.name = name; this.id = id; } @Override public String toString() { return "Preson{" + "name='" + name + '\'' + ", id=" + id + '}'; } } class PersonComparator implements Comparator<Preson> { @Override public int compare(Preson o1, Preson o2) { return o1.name.compareTo(o2.name); } } public class Main { public static void main(String[] args) { Preson preson1 = new Preson("aboluo", 24); Preson preson2 = new Preson("zhousi", 25); Preson preson3 = new Preson("syyfjy", 2); Preson[] presons = {preson1, preson2, preson3}; Arrays.parallelSort(presons, new PersonComparator()); System.out.println(Arrays.toString(presons)); } }
//output: [Preson{name='aboluo', id=24}, Preson{name='syyfjy', id=2}, Preson{name='zhousi', id=25}] Process finished with exit code 0
使用內部類上述代碼就變為:
import java.util.Arrays; import java.util.Comparator; class Preson { public String name; public Integer id; public Preson(String name, Integer id) { this.name = name; this.id = id; } @Override public String toString() { return "Preson{" + "name='" + name + '\'' + ", id=" + id + '}'; } } public class Main { public static void main(String[] args) { Preson preson1 = new Preson("aboluo", 24); Preson preson2 = new Preson("zhousi", 25); Preson preson3 = new Preson("syyfjy", 2); Preson[] presons = {preson1, preson2, preson3}; Arrays.parallelSort(presons, new Comparator<Preson>() { @Override public int compare(Preson o1, Preson o2) { return o1.name.compareTo(o2.name); } }); System.out.println(Arrays.toString(presons)); } }
//output: [Preson{name='aboluo', id=24}, Preson{name='syyfjy', id=2}, Preson{name='zhousi', id=25}] Process finished with exit code 0
還有一個本地內部類,就是類定義在方法中,就不多說了,基本上不用,用法如下:
public class Outer { public void func() { class Inner{ // } } }
關于“Java內部類示例分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。