摘要:內(nèi)部類(lèi)中也可以取得這個(gè)外部類(lèi)對(duì)象引用。創(chuàng)建成員內(nèi)部類(lèi)對(duì)象的時(shí)候需要外部類(lèi)對(duì)象。另外在方法中的內(nèi)部類(lèi)不能加等權(quán)限修飾符,只能加和修飾符。可以在接口內(nèi)部定義內(nèi)部類(lèi),而且他們即使沒(méi)有修飾,也會(huì)自動(dòng)變成的。
Thinking in Java撈干貨,寫(xiě)筆記 一、成員內(nèi)部類(lèi) 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.內(nèi)部類(lèi)可以訪(fǎng)問(wèn)外部類(lèi)的成員
內(nèi)部類(lèi)可以訪(fǎng)問(wèn)外部類(lèi)的成員變量。如下:
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(); }
因?yàn)樵趧?chuàng)建內(nèi)部類(lèi)對(duì)象的時(shí)候,內(nèi)部類(lèi)對(duì)象會(huì)捕獲一個(gè)指向外部類(lèi)對(duì)象的引用。訪(fǎng)問(wèn)外部類(lèi)成員的時(shí)候,就是用這個(gè)引用來(lái)獲取外部類(lèi)成員的。內(nèi)部類(lèi)中也可以取得這個(gè)外部類(lèi)對(duì)象引用。舉例如下:
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(); } }
當(dāng)要在其他類(lèi)中創(chuàng)建一個(gè)內(nèi)部類(lèi)對(duì)象的時(shí)候,可以使用.new語(yǔ)法。
public class DotNew{ public class Inner{ } public static void main(String[] args){ Inner dni=new DotNew().new Inner(); } }
當(dāng)創(chuàng)造內(nèi)部類(lèi)對(duì)象的時(shí)候,如果這個(gè)內(nèi)部類(lèi)不是嵌套類(lèi)(靜態(tài)內(nèi)部類(lèi)),那么就必須要通過(guò)外部類(lèi)對(duì)象,才能創(chuàng)建這個(gè)內(nèi)部類(lèi)對(duì)象,為什么呢,之前說(shuō)過(guò),因?yàn)檫@個(gè)內(nèi)部類(lèi)對(duì)象要獲取外部類(lèi)的引用啊。
并且在存在多個(gè)內(nèi)部類(lèi)的時(shí)候,多個(gè)內(nèi)部類(lèi)之間可以互相創(chuàng)建對(duì)象。例子就不舉了。
小結(jié):現(xiàn)在所說(shuō)的都是成員內(nèi)部類(lèi),其實(shí)內(nèi)部類(lèi)沒(méi)那么復(fù)雜,既然叫做成員內(nèi)部類(lèi)了,他就只是類(lèi)的成員罷了。他也可以帶修飾符,他的修飾符和其他普通的成員變量的修飾符的意義也沒(méi)有什么不同。
3.內(nèi)部類(lèi)權(quán)限修飾符當(dāng)內(nèi)部類(lèi)被private修飾的時(shí)候,該類(lèi)只能被外部類(lèi)內(nèi)的方法使用,其他類(lèi)不能獲取該內(nèi)部類(lèi)的引用,因?yàn)槭莗rivate的,所以其他類(lèi)根本不知道存在一個(gè)這樣的類(lèi)。當(dāng)然也可以作為一個(gè)成員變量使用,但是如果作為成員變量,則其他類(lèi)并不能直接創(chuàng)建內(nèi)部類(lèi)的引用,需要用其他手段獲取該引用,如下:
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;這是錯(cuò)誤的,因?yàn)閠est并不知道Outer類(lèi)有一個(gè)Inner內(nèi)部類(lèi),因?yàn)槭撬接械? a_interface in=new Outer().in;//可以運(yùn)用向上轉(zhuǎn)型的方法獲取private修飾的內(nèi)部類(lèi)。 }
小結(jié):其實(shí)這也很好記,無(wú)論是public還是private,修飾到內(nèi)部類(lèi)上的時(shí)候,和他們修飾普通的成員變量(如string,int之類(lèi))的時(shí)候沒(méi)什么不同,規(guī)則都一樣,public就都能使用,private就類(lèi)內(nèi)可以用。所以規(guī)則就記住三條就好:1.先考慮外部類(lèi)的權(quán)限,是否可以獲取一個(gè)外部類(lèi)對(duì)象。2.創(chuàng)建成員內(nèi)部類(lèi)對(duì)象的時(shí)候需要外部類(lèi)對(duì)象。3.考慮內(nèi)部類(lèi)的權(quán)限,是否可以獲取這樣的一個(gè)內(nèi)部類(lèi)對(duì)象(或者說(shuō),在外部知不知道有這樣一個(gè)內(nèi)部類(lèi))。
二、方法和作用域內(nèi)的內(nèi)部類(lèi)當(dāng)我們需要解決一個(gè)復(fù)雜的問(wèn)題,想創(chuàng)建一個(gè)類(lèi)來(lái)輔助解決問(wèn)題,但是不希望這個(gè)類(lèi)是公共可用的,甚至不希望在外部類(lèi)之內(nèi)的其他地方可以訪(fǎng)問(wèn)到這個(gè)輔助類(lèi)。我們可以運(yùn)用方法內(nèi)的內(nèi)部類(lèi)
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(); }
當(dāng)然在方法中還可以定義多個(gè)內(nèi)部類(lèi),并且這些內(nèi)部類(lèi)之間的關(guān)系和普通一個(gè)Java文件中多個(gè)類(lèi)之間的關(guān)系好像沒(méi)什么不同。也可以相互繼承和創(chuàng)建對(duì)象。另外在方法中的內(nèi)部類(lèi)不能加private等權(quán)限修飾符,只能加abstract和final修飾符。
另外也可以在某個(gè)作用域內(nèi)創(chuàng)建內(nèi)部類(lèi)對(duì)象
if(a==b){ class inner{ } new inner(); }三、匿名內(nèi)部類(lèi)
下面這塊代碼中g(shù)et_inner()的意思是,創(chuàng)建一個(gè)繼承自InnerFather的匿名類(lèi)對(duì)象,并且自動(dòng)向上轉(zhuǎn)型為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(); } }
當(dāng)然這只是有無(wú)參構(gòu)造函數(shù),當(dāng)父類(lèi)只有一個(gè)含參構(gòu)造函數(shù)的時(shí)候,我們可以這樣向匿名內(nèi)部類(lèi)傳入一個(gè)構(gòu)造函數(shù)參數(shù)。
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(); } }
可以通過(guò)構(gòu)造代碼塊來(lái)實(shí)現(xiàn)匿名內(nèi)部類(lèi)的自定義的構(gòu)造函數(shù)
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); } }
(書(shū)上說(shuō),如果傳入了新的對(duì)象,就比如下面例子中的s_in,這個(gè)s_in就必須是final的,但是我實(shí)驗(yàn)了一下發(fā)現(xiàn)并不用啊,我也沒(méi)太搞懂。)
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");}//構(gòu)造代碼塊4.嵌套類(lèi) String s=s_in; public void f(){ } }; } public static void main(String[] args) { Base base = getBase(47,"hello"); } }四、嵌套類(lèi)
嵌套類(lèi)指的是被static修飾的內(nèi)部類(lèi)。這意味著:1.創(chuàng)建嵌套類(lèi)對(duì)象不需要外部類(lèi)對(duì)象。2.不能再嵌套類(lèi)對(duì)象之中訪(fǎng)問(wèn)非靜態(tài)的外圍類(lèi)對(duì)象。普通內(nèi)部類(lèi)的成員和方法只能放在類(lèi)的外部層次上(這句話(huà)我沒(méi)搞懂= =),所以普通內(nèi)部類(lèi)不能有static的成員和方法。但是嵌套類(lèi)可以有。
public class Outer { static class Inner{ static int i=5; } public static void main(String[] args) { Inner i=new Outer.Inner(); } }
可以從上面的例子看到,在創(chuàng)建這個(gè)嵌套類(lèi)對(duì)象的時(shí)候,并沒(méi)有像最開(kāi)始那樣,用一個(gè)外部類(lèi)對(duì)象來(lái)創(chuàng)建這個(gè)內(nèi)部類(lèi)對(duì)象。其實(shí)這和靜態(tài)方法差不多。
可以在接口內(nèi)部定義內(nèi)部類(lèi),而且他們即使沒(méi)有static修飾,也會(huì)自動(dòng)變成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(); } } }
書(shū)上有句話(huà)說(shuō)的很好,在開(kāi)發(fā)的時(shí)候建議在每個(gè)類(lèi)中都寫(xiě)一個(gè)main方法測(cè)試,但是這又必須帶著那些已經(jīng)編譯過(guò)的額外代碼,所以我們可以用嵌套類(lèi)放置測(cè)試代碼。
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(); } } }
當(dāng)然以上兩段代碼如果是在eclipse上運(yùn)行的話(huà),需要設(shè)置一下運(yùn)行的main函數(shù)在哪,否則會(huì)報(bào)錯(cuò)
紙老虎,愛(ài)有幾層有幾層,反正只要是外部類(lèi)的東西,不管哪層外部類(lèi),都能訪(fǎng)問(wèn)到。
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(); } }
下面是個(gè)好玩的
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(); } }
最后打印結(jié)果是java。
大概就這么多吧,以后如果還有新東西再補(bǔ)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67513.html
摘要:四上的操作看五格式化輸出運(yùn)用和語(yǔ)言很相似和是等價(jià)的喲類(lèi)格式化說(shuō)明符轉(zhuǎn)換六正則表達(dá)式網(wǎng)上教程學(xué)七掃描輸入新增了類(lèi)。 一、不可變String String類(lèi)型的對(duì)象是不可變的,所有的改變實(shí)際上都是創(chuàng)建了一個(gè)新的String對(duì)象,另外當(dāng)String作為傳入?yún)?shù)的時(shí)候,其實(shí)實(shí)際上傳入的是這個(gè)引用的一個(gè)拷貝,這個(gè)方法結(jié)束了之后這個(gè)傳入的引用也就消失了,原來(lái)的那個(gè)String不會(huì)受到方法內(nèi)的影響而...
摘要:但如果導(dǎo)出類(lèi)還有抽象方法,那這個(gè)類(lèi)還應(yīng)該加上聲明為抽象類(lèi)。并且接口具有繼承的一系列特點(diǎn),如向上轉(zhuǎn)型等等。接口中的方法是自動(dòng)是的。 Thinking in Java 好書(shū)全是干貨 一、抽象類(lèi)和抽象方法 抽象方法:這種方法只有聲明而沒(méi)有方法體,下面是抽象方法生命所采用的語(yǔ)法 abstract void f(); 包含抽象方法的類(lèi)叫做抽象類(lèi),如果一個(gè)類(lèi)包含一個(gè)或多個(gè)抽象方法,該類(lèi)必須被限定為...
摘要:通過(guò)運(yùn)行時(shí)類(lèi)型信息,程序能夠使用基類(lèi)的指針或引用來(lái)檢查這些指針或引用所指的對(duì)象的實(shí)際派生類(lèi)型。編程應(yīng)該盡量面向接口編程,應(yīng)該對(duì)類(lèi)型信息盡量的少了解二對(duì)象看書(shū),書(shū)上寫(xiě)得好靜態(tài)語(yǔ)句塊在這個(gè)類(lèi)被加載的時(shí)候運(yùn)行。 一、為什么需要RTTI Run-Time Type Information。通過(guò)運(yùn)行時(shí)類(lèi)型信息,程序能夠使用基類(lèi)的指針或引用來(lái)檢查這些指針或引用所指的對(duì)象的實(shí)際派生類(lèi)型。編程應(yīng)該盡量...
摘要:異常處理程序拋出的異常必須在異常處理程序中得到處理。終止與恢復(fù)異常處理有兩種模型,支持終止模型,一旦異常被拋出,表明錯(cuò)誤無(wú)法挽回,無(wú)法退回來(lái)繼續(xù)執(zhí)行之前出錯(cuò)的代碼。對(duì)于異常來(lái)說(shuō),最重要的部分就是類(lèi)名。 一、概念 使用異常能降低處理錯(cuò)誤代碼的復(fù)雜程度,并且將錯(cuò)誤在一個(gè)地方進(jìn)行處理,于是將描述在正常行為過(guò)程中做過(guò)什么事的代碼和出了問(wèn)題怎么辦的代碼相分離 二、基本異常 異常情形指的是當(dāng)前環(huán)境...
摘要:迭代器解決了這個(gè)問(wèn)題。刪除后于是我們可以寫(xiě)一個(gè)方法,接受一個(gè)類(lèi)型,然后讓他調(diào)用方法,這就不需要考慮這個(gè)是個(gè)還是了,也就是說(shuō),可以將遍歷容器的操作與序列底層的結(jié)構(gòu)分離,迭代器統(tǒng)一了對(duì)容器類(lèi)的訪(fǎng)問(wèn)方式。十二和兩種遍歷的方法,與迭代器方法。 一、泛型和類(lèi)型安全的容器 package tij.hoding; import java.util.ArrayList; public class ...
閱讀 2366·2021-11-25 09:43
閱讀 2874·2021-11-24 09:39
閱讀 2937·2019-08-30 11:10
閱讀 1146·2019-08-29 16:34
閱讀 610·2019-08-29 13:25
閱讀 3369·2019-08-29 11:21
閱讀 2872·2019-08-26 11:39
閱讀 2404·2019-08-26 11:34