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