摘要:內部類中也可以取得這個外部類對象引用。創建成員內部類對象的時候需要外部類對象。另外在方法中的內部類不能加等權限修飾符,只能加和修飾符。可以在接口內部定義內部類,而且他們即使沒有修飾,也會自動變成的。
Thinking in Java撈干貨,寫筆記 一、成員內部類 1.最基本使用
public class Demo { class Contents{ private int i=11; public int value(){ return i; } } class Destination{ private String label; Destination(String whereTo){ label=whereTo; } String readLabel(){ return label; } } public void ship(String dest){ Contents c=new Contents(); Destination d=new Destination(dest); System.out.println(d.readLabel()); } public static void main(String[] args) { Demo d=new Demo(); d.ship("Tasmania"); } }2.內部類可以訪問外部類的成員
內部類可以訪問外部類的成員變量。如下:
public class Demo { private Object[] items; private int next = 0; public Demo(int size) { items = new Object[size]; } public void add(Object x) { if (next < items.length) { items[next++] = x; } } private class SequenceSelector implements Selector { private int i = 0; public boolean end() { return i == items.length; } public Object current() { return items[i]; } public void next() { if (i < items.length) { i++; } } } public Selector selector() { return new SequenceSelector(); } public static void main(String[] args) { Demo d = new Demo(10); for (int i = 0; i < 10; i++) { d.add(Integer.toString(i)); } Selector selector = d.selector(); while (!selector.end()) { System.out.print(selector.current() + " "); selector.next(); } } } interface Selector { boolean end(); Object current(); void next(); }
因為在創建內部類對象的時候,內部類對象會捕獲一個指向外部類對象的引用。訪問外部類成員的時候,就是用這個引用來獲取外部類成員的。內部類中也可以取得這個外部類對象引用。舉例如下:
public class DotThis{ void f(){ System.out.println("DotThis.f()"); } class Inner{ public DotThis outer(){ return DotThis.this; //A plain "this" would be Inner"s this } } public Inner inner(){ return new Inner(); } public static void main(String[] args) { DotThis dt=new DotThis(); DotThis.Inner dti=dt.inner(); dti.outer().f(); } }
當要在其他類中創建一個內部類對象的時候,可以使用.new語法。
public class DotNew{ public class Inner{ } public static void main(String[] args){ Inner dni=new DotNew().new Inner(); } }
當創造內部類對象的時候,如果這個內部類不是嵌套類(靜態內部類),那么就必須要通過外部類對象,才能創建這個內部類對象,為什么呢,之前說過,因為這個內部類對象要獲取外部類的引用啊。
并且在存在多個內部類的時候,多個內部類之間可以互相創建對象。例子就不舉了。
小結:現在所說的都是成員內部類,其實內部類沒那么復雜,既然叫做成員內部類了,他就只是類的成員罷了。他也可以帶修飾符,他的修飾符和其他普通的成員變量的修飾符的意義也沒有什么不同。
3.內部類權限修飾符當內部類被private修飾的時候,該類只能被外部類內的方法使用,其他類不能獲取該內部類的引用,因為是private的,所以其他類根本不知道存在一個這樣的類。當然也可以作為一個成員變量使用,但是如果作為成員變量,則其他類并不能直接創建內部類的引用,需要用其他手段獲取該引用,如下:
class Outer{ Inner in; private class Inner implements a_interface{ void show(){ System.out.println("123"); } } } interface a_interface{ void show(); } class test{ //Inner in=new Outer().in;這是錯誤的,因為test并不知道Outer類有一個Inner內部類,因為是私有的 a_interface in=new Outer().in;//可以運用向上轉型的方法獲取private修飾的內部類。 }
小結:其實這也很好記,無論是public還是private,修飾到內部類上的時候,和他們修飾普通的成員變量(如string,int之類)的時候沒什么不同,規則都一樣,public就都能使用,private就類內可以用。所以規則就記住三條就好:1.先考慮外部類的權限,是否可以獲取一個外部類對象。2.創建成員內部類對象的時候需要外部類對象。3.考慮內部類的權限,是否可以獲取這樣的一個內部類對象(或者說,在外部知不知道有這樣一個內部類)。
二、方法和作用域內的內部類當我們需要解決一個復雜的問題,想創建一個類來輔助解決問題,但是不希望這個類是公共可用的,甚至不希望在外部類之內的其他地方可以訪問到這個輔助類。我們可以運用方法內的內部類
public class Outer { public InterfaceDemo get_InterfaceDemo(String s) { class InterfaceDemoTool implements InterfaceDemo { private String label; private InterfaceDemoTool(String label) { this.label = label; } public String readLabel() { return label; } } return new InterfaceDemoTool(s); } public static void main(String[] args) { Outer o = new Outer(); InterfaceDemo i = o.get_InterfaceDemo("123"); } } interface InterfaceDemo { String readLabel(); }
當然在方法中還可以定義多個內部類,并且這些內部類之間的關系和普通一個Java文件中多個類之間的關系好像沒什么不同。也可以相互繼承和創建對象。另外在方法中的內部類不能加private等權限修飾符,只能加abstract和final修飾符。
另外也可以在某個作用域內創建內部類對象
if(a==b){ class inner{ } new inner(); }三、匿名內部類
下面這塊代碼中get_inner()的意思是,創建一個繼承自InnerFather的匿名類對象,并且自動向上轉型為InnerFather后返回。
public class Outer { public InnerFather get_inner() { return new InnerFather() { void print(){ System.out.println("Inner_Override"); } }; } class InnerFather { InnerFather() { } void print(){ System.out.println("InnerFather"); } } public static void main(String[] args) { Outer o = new Outer(); InnerFather i = o.get_inner(); i.print(); } }
當然這只是有無參構造函數,當父類只有一個含參構造函數的時候,我們可以這樣向匿名內部類傳入一個構造函數參數。
public class Outer { public InnerFather get_inner(int i) { return new InnerFather(i) { void print(){ System.out.println("Inner_Override"); } }; } class InnerFather { InnerFather(int i) { } void print(){ System.out.println("InnerFather"); } } public static void main(String[] args) { Outer o = new Outer(); InnerFather i = o.get_inner(10); i.print(); } }
可以通過構造代碼塊來實現匿名內部類的自定義的構造函數
abstract class Base { public Base(int i) { System.out.println("Base constructor"); } public abstract void f(); } public class AnonymousConstructor { public static Base getBase(int i){ return new Base(i){ {System.out.println("AnonymousConstructor constructor");} public void f(){ } }; } public static void main(String[] args) { Base base = getBase(47); } }
(書上說,如果傳入了新的對象,就比如下面例子中的s_in,這個s_in就必須是final的,但是我實驗了一下發現并不用啊,我也沒太搞懂。)
abstract class Base { public Base(int i) { System.out.println("Base constructor"); } public abstract void f(); } public class AnonymousConstructor { public static Base getBase(int i,String s_in){ return new Base(i){ {System.out.println("AnonymousConstructor constructor");}//構造代碼塊4.嵌套類 String s=s_in; public void f(){ } }; } public static void main(String[] args) { Base base = getBase(47,"hello"); } }四、嵌套類
嵌套類指的是被static修飾的內部類。這意味著:1.創建嵌套類對象不需要外部類對象。2.不能再嵌套類對象之中訪問非靜態的外圍類對象。普通內部類的成員和方法只能放在類的外部層次上(這句話我沒搞懂= =),所以普通內部類不能有static的成員和方法。但是嵌套類可以有。
public class Outer { static class Inner{ static int i=5; } public static void main(String[] args) { Inner i=new Outer.Inner(); } }
可以從上面的例子看到,在創建這個嵌套類對象的時候,并沒有像最開始那樣,用一個外部類對象來創建這個內部類對象。其實這和靜態方法差不多。
可以在接口內部定義內部類,而且他們即使沒有static修飾,也會自動變成public static的。
public interface ClassInInterface { void howdy(); class Test implements ClassInInterface{ public void howdy(){ System.out.println("howdy!"); } public static void main(String[] args) { new Test().howdy(); } } }
書上有句話說的很好,在開發的時候建議在每個類中都寫一個main方法測試,但是這又必須帶著那些已經編譯過的額外代碼,所以我們可以用嵌套類放置測試代碼。
public class Outer { public void f(){ System.out.println("I need to be tested"); } public static class Tester{ public static void main(String[] args) { Outer o=new Outer(); o.f(); } } }
當然以上兩段代碼如果是在eclipse上運行的話,需要設置一下運行的main函數在哪,否則會報錯
紙老虎,愛有幾層有幾層,反正只要是外部類的東西,不管哪層外部類,都能訪問到。
public class Outer { void f(){ System.out.println("hello"); } class Inner1{ void g(){ System.out.println("java"); } class Inner2{ void h(){ f(); g(); } } } public static void main(String[] args) { Outer.Inner1.Inner2 in2=new Outer().new Inner1().new Inner2(); in2.h(); } }
下面是個好玩的
public class Outer { void f(){ System.out.println("hello"); } class Inner1{ void f(){ System.out.println("java"); } class Inner2{ void h(){ f(); } } } public static void main(String[] args) { Outer.Inner1.Inner2 in2=new Outer().new Inner1().new Inner2(); in2.h(); } }
最后打印結果是java。
大概就這么多吧,以后如果還有新東西再補。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67513.html
摘要:四上的操作看五格式化輸出運用和語言很相似和是等價的喲類格式化說明符轉換六正則表達式網上教程學七掃描輸入新增了類。 一、不可變String String類型的對象是不可變的,所有的改變實際上都是創建了一個新的String對象,另外當String作為傳入參數的時候,其實實際上傳入的是這個引用的一個拷貝,這個方法結束了之后這個傳入的引用也就消失了,原來的那個String不會受到方法內的影響而...
摘要:但如果導出類還有抽象方法,那這個類還應該加上聲明為抽象類。并且接口具有繼承的一系列特點,如向上轉型等等。接口中的方法是自動是的。 Thinking in Java 好書全是干貨 一、抽象類和抽象方法 抽象方法:這種方法只有聲明而沒有方法體,下面是抽象方法生命所采用的語法 abstract void f(); 包含抽象方法的類叫做抽象類,如果一個類包含一個或多個抽象方法,該類必須被限定為...
摘要:通過運行時類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型。編程應該盡量面向接口編程,應該對類型信息盡量的少了解二對象看書,書上寫得好靜態語句塊在這個類被加載的時候運行。 一、為什么需要RTTI Run-Time Type Information。通過運行時類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型。編程應該盡量...
摘要:異常處理程序拋出的異常必須在異常處理程序中得到處理。終止與恢復異常處理有兩種模型,支持終止模型,一旦異常被拋出,表明錯誤無法挽回,無法退回來繼續執行之前出錯的代碼。對于異常來說,最重要的部分就是類名。 一、概念 使用異常能降低處理錯誤代碼的復雜程度,并且將錯誤在一個地方進行處理,于是將描述在正常行為過程中做過什么事的代碼和出了問題怎么辦的代碼相分離 二、基本異常 異常情形指的是當前環境...
摘要:迭代器解決了這個問題。刪除后于是我們可以寫一個方法,接受一個類型,然后讓他調用方法,這就不需要考慮這個是個還是了,也就是說,可以將遍歷容器的操作與序列底層的結構分離,迭代器統一了對容器類的訪問方式。十二和兩種遍歷的方法,與迭代器方法。 一、泛型和類型安全的容器 package tij.hoding; import java.util.ArrayList; public class ...
閱讀 2351·2021-11-25 09:43
閱讀 2864·2021-11-24 09:39
閱讀 2925·2019-08-30 11:10
閱讀 1130·2019-08-29 16:34
閱讀 595·2019-08-29 13:25
閱讀 3358·2019-08-29 11:21
閱讀 2861·2019-08-26 11:39
閱讀 2394·2019-08-26 11:34