日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java内部类总结

發布時間:2024/3/12 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java内部类总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

內部
本文主要參照網上的一些相關文章、以及thinking in java 第三版,對java里面的內部類進行了一個較為具體的總結 內部是指在一個外部的內部再定一個

內部

外部的一個成,而且依附于外部而存在的。內部,可用protectedprivate(而外部僅僅能使用public和缺省的包訪問權限)。

內部類主要有下面幾類:

內部、局部內部、靜內部、匿名內部 為什么須要內部類? 典型的情況是,內部類繼承自某個類或實現某個接口,內部類的代碼操作創建其的外圍類的對象。所以你能夠覺得內部類提供了某種進入其外圍類的窗體。使用內部類最吸引人的原因是: 每一個內部類都能獨立地繼承自一個(接口的)實現,所以不管外圍類是否已經繼承了某個(接口的)實現,對于內部類都沒有影響。假設沒有內部類提供的能夠繼承多個詳細的或抽象的類的能力。一些設計與編程問題就非常難解決。從這個角度看,內部類使得多重繼承的解決方式變得完整。接口攻克了部分問題,而內部類有效地實現了“多重繼承”。

A:成員內部類
外部的一個成存在,與外部的屬性、方法并列。 publicclass?Outer { ???????privatestaticinti?= 1; ???????privateintj?= 10; ???????privateintk?= 20; ???????publicstaticvoidouter_f1()?{ ?????? } ???????publicvoidouter_f2()?{ ?????? } ???????//?內部中,不能定 ???????//?內部中,能夠訪問外部的全部成 ???????class?Inner { ??????????????// static int inner_i = 100;//內部中不允態變 ??????????????intj?= 100;?//?內部和外部量能夠共存 ??????????????intinner_i?= 1; ??????????????void?inner_f1() { ???????????????????? System.out.println(i); ?????????????????????????//在內部訪問內部自己的量直接用量名 ?????????????????????System.out.println(j); ?????????????????????????//在內部訪問內部自己的量也能夠用this.量名 ?????????????????????System.out.println(this.j); ?????????????????????????//在內部訪問外部中與內部同名的量用外部.this.量名 ?????????????????????System.out.println(Outer.this.j); ?????????????????????????//假設內部中沒有與外部同名的量,能夠直接用量名訪問外部類變 ?????????????????????System.out.println(k); ????????????????????????????????????????? outer_f1(); ????????????????????????????????????????? outer_f2(); ????????????? } ?????? } ???????//外部的非靜方法訪問內部 ???????publicvoidouter_f3()?{ ????????????? Inner inner =?new?Inner(); ??????????????inner.inner_f1(); ?????? } ???????//?外部的靜方法訪問內部,與在外部外部訪問內部 ???????publicstaticvoidouter_f4() { ??????????????//step1?建立外部類對 ????????????? Outer out =?new?Outer(); ??????????????//step2?依據外部類對象建立內部類對 ????????????? Inner inner = out.new?Inner(); ??????????????//step3?訪問內部的方法 ????????????? inner.inner_f1(); ?????? } ???????publicstaticvoid?main(String[] args) { ??????????????//outer_f4();//該語句的果和以下三條句的果一 ??????????????//假設要直接建內部象,不能想當然地覺得僅僅需加上外圍類Outer的名字, ??????????????//就能夠依照通常的子生成內部象。而是必使用此外圍類的一個象來 ??????????????//建其內部的一個象: ??????????????//Outer.Inner outin = out.new Inner() ??????????????//因此,除非你已有了外圍類的一個象,否不可能生成內部象。

??????????????//內部象會悄悄地接到建它的外圍類象。假設你用的是靜的內部 ??????????????//那就不須要其外圍類對象的引用。 ??????????????Outer out =?new?Outer(); ??????????????Outer.Inner outin = out.new?Inner(); ??????????????outin.inner_f1(); ?????? } }
注意:內部是一個編譯時的概念,一旦編譯成功,就會成全然不同的兩于一個名outer的外部和其內部定的名inner的內部

編譯完畢后出outer.classouter$inner.class B:局部內部類
在方法中定的內部局部內部。與局部似。局部內部類不能有訪問說明符,由于它不是外圍類的一部分,可是它能夠訪問當前代碼塊內的常量,和此外圍類全部的成員。

publicclass?Outer { ???????privateints?= 100; ???????privateintout_i?= 1; ???????publicvoid?f(finalint?k) { ??????????????finalint?s = 200; ??????????????int?i = 1; ??????????????finalint?j = 10; ????????????? ?????????????????//在方法內部 ??????????????class?Inner { ?????????????????????ints?= 300;//?能夠定與外部同名的 ?????????????????????// static int m = 20;//不能夠定態變 ???????????????????? Inner(int?k) { ????????????????????????????inner_f(k); ???????????????????? } ?????????????????????intinner_i?= 100; ?????????????????????voidinner_f(int?k) { ?????????????????????????//假設內部沒有與外部同名的量,在內部中能夠直接訪問外部 ????????????????????????????System.out.println(out_i); ?????????????????????????//能夠訪問外部的局部(即方法內的),可是量必final ????????????????????????????System.out.println(j); ????????????????????????????//System.out.println(i); ?????????????????????????//假設內部中有與外部同名的量,直接用量名訪問的是內部 ????????????????????????????System.out.println(s); ?????????????????????????//this.量名訪問的也是內部類變 ????????????????????????????System.out.println(this.s); ?????????????????????????//用外部.this.內部類變量名訪問的是外部類變 ????????????????????????????System.out.println(Outer.this.s); ???????????????????? } ????????????? } ??????????????new?Inner(k); ?????? } ???????publicstaticvoid?main(String[] args) { ??????????????//?訪問局部內部先有外部類對 ??????????????Outer out =?new?Outer(); ????????????? out.f(3); ???????} } C:靜態內部類(嵌套類)(注意:前兩內部似,所以能夠照參考量)
假設你不須要內部類對象與其外圍類對象之間有聯系,那你能夠將內部類聲明為static。這通常稱為嵌套類(nested class)。

想要理解

static應用于內部類時的含義,你就必須記住,普通的內部類對象隱含地保存了一個引用,指向創建它的外圍類對象。

然而,當內部類是

static的時,就不是這樣了。嵌套類意味著: 1.?要創建嵌套類的對象,并不須要其外圍類的對象。

2.?不能從嵌套類的對象中訪問非靜態的外圍類對象。 publicclass?Outer { ???????privatestaticinti?= 1; ???????privateintj?= 10; ???????publicstaticvoidouter_f1() { ?????? } ???????publicvoidouter_f2() { ?????? } ???????//?內部能夠用public,protected,private ???????//?內部中能夠定或者非靜的成 ???????staticclass?Inner { ??????????????staticintinner_i?= 100; ??????????????intinner_j?= 200; ??????????????staticvoidinner_f1() { ???????? ?????????????//內部僅僅能訪問外部的靜(包含靜態變量和靜方法) ???????????????????? System.out.println("Outer.i"?+?i); ?????????????????????outer_f1(); ????????????? } ??????????????voidinner_f2()?{ ?????????????????????//?內部不能訪問外部的非靜(包含非靜態變量和非靜方法) ?????????????????????// System.out.println("Outer.i"+j); ?????????????????????// outer_f2(); ????????????? } ?????? } ???????publicvoidouter_f3()?{ ??????????????//?外部類訪問內部的靜:內部. ??????????????System.out.println(Inner.inner_i); ??????????????Inner.inner_f1(); ??????????????//?外部類訪問內部的非靜:例化內部就可以 ??????????????Inner inner =?new?Inner(); ??????????????inner.inner_f2(); ?????? } ???????publicstaticvoid?main(String[] args) { ??????????????newOuter().outer_f3(); ?????? } }
生成一個靜內部不須要外部是靜內部和成內部的區。靜內部象能夠直接生成:Outer.Inner in = new Outer.Inner();而不須要通生成外部類對象來生成。這樣實際上使靜內部了一個頂級類(正常情況下。你不能在接口內部放置不論什么代碼。但嵌套類能夠作為接口的一部分,由于它是static?的。僅僅是將嵌套類置于接口的命名空間內,這并不違反接口的規則) D:匿名內部類(from thinking in java 3th) 簡單地說:匿名內部類就是沒有名字的內部類。

什么情況下須要使用匿名內部類?假設滿足以下的一些條件,使用匿名內部類是比較合適的:

  ·僅僅用到類的一個實例。?
  ·類在定義后立即用到。

?
  ·類很小(SUN推薦是在4行代碼下面)?
  ·給類命名并不會導致你的代碼更easy被理解。

  在使用匿名內部類時。要記住下面幾個原則:   ·匿名內部類不能有構造方法。?
  ·匿名內部類不能定義不論什么靜態成員、方法和類。?
  ·匿名內部類不能是public,protected,private,static?
  ·僅僅能創建匿名內部類的一個實例。 ·一個匿名內部類一定是在new的后面,用其隱含實現一個接口或實現一個類。

?
  ·因匿名內部類為局部內部類,所以局部內部類的全部限制都對其生效。?

以下的樣例看起來有點奇怪: //在方法中返回一個匿名內部類 public class Parcel6 { ??????? public Contents cont() { ??????????????? return?new Contents() { ???????????????????? private int i = 11; ? ???????????????????? public int value() { ???????????????????? ?????? return i; ???????????????????? } ????????????? };?//?在這里須要一個分號 ??????? } ??????? public static void main(String[] args) { ??????????????? Parcel6 p = new Parcel6(); ??????????????? Contents c = p.cont(); ??????? } } cont()方法將以下兩個動作合并在一起:返回值的生成,與表示這個返回值的類的定義!進一步說,這個類是匿名的,它沒有名字。

更糟的是,看起來是你正要創建一個

Contents對象: return new Contents() 可是,在到達語句結束的分號之前,你卻說:“等一等,我想在這里插入一個類的定義”: return new Contents() { private int i = 11; public int value() { return i; } }; 這樣的奇怪的語法指的是:“創建一個繼承自Contents的匿名類的對象。

”通過

new?表達式返回的引用被自己主動向上轉型為對Contents的引用。匿名內部類的語法是以下樣例的簡略形式: class MyContents implements Contents { private int i = 11; public int value() { return i; } ??? } return new MyContents(); 在這個匿名內部類中,使用了缺省的構造器來生成Contents。以下的代碼展示的是,假設你的基類須要一個有參數的構造器,應該怎么辦: public class Parcel7 { public Wrapping wrap(int x) { // Base constructor call: return new Wrapping(x) { // Pass constructor argument. public int value() { return super.value() * 47; ??????????? } }; // Semicolon required ??? } public static void main(String[] args) { Parcel7 p = new Parcel7(); Wrapping w = p.wrap(10); ??? } } 僅僅需簡單地傳遞合適的參數給基類的構造器就可以,這里是將x?傳進new Wrapping(x)。在匿名內部類末尾的分號,并非用來標記此內部類結束(C++中是那樣)。

實際上,它標記的是表達式的結束。僅僅只是這個表達式正巧包括了內部類罷了。

因此,這與別的地方使用的分號是一致的。

假設在匿名類中定義成員變量,你相同可以對其運行初始化操作: public class Parcel8 { // Argument must be final to use inside // anonymous inner class: public Destination dest(final String dest) { return new Destination() { private String label = dest; public String readLabel() { return label; } }; ??? } public static void main(String[] args) { Parcel8 p = new Parcel8(); Destination d = p.dest("Tanzania"); ??? } } 假設你有一個匿名內部類。它要使用一個在它的外部定義的對象。編譯器會要求其參數引用是final?型的,就像dest()中的參數。

假設你忘記了,會得到一個編譯期錯誤信息。假設僅僅是簡單地給一個成員變量賦值。那么此例中的方法就行了。可是,假設你想做一些類似構造器的行為,該怎么辦呢?在匿名類中不可能有已命名的構造器(由于它根本沒名字!),但通過實例初始化,你就行達到為匿名內部類“制作”一個構造器的效果。

像這樣做:

abstract class Base?{ public Base(int i) { System.out.println("Base constructor, i = " + i); } public abstract void f(); } public class AnonymousConstructor?{ public static Base getBase(int i) { return?new Base(i) { ??????????? { System.out.println("Inside instance initializer"); ??????????? } public void f() { System.out.println("In anonymous f()"); ??????????? } }; } public static void main(String[] args) { Base base = getBase(47); base.f(); } } 在此例中,不要求變量i?一定是final?的。

由于

i?被傳遞給匿名類的基類的構造器,它并不會在匿名類內部被直接使用。下例是帶實例初始化的“parcel”形式。注意dest()的參數必須是final,由于它們是在匿名類內被使用的。

public class Parcel9 { public Destinationdest(final String dest, final float price) { return?new Destination() { private int cost; // Instance initialization for each object: ??????????? { cost = Math.round(price); if(cost > 100) System.out.println("Over budget!"); ??? ????????} private String label = dest; public String readLabel() { return label; } }; ??? } public static void main(String[] args) { Parcel9 p = new Parcel9(); Destination d = p.dest("Tanzania", 101.395F); ??? } } 在實例初始化的部分,你能夠看到有一段代碼,那原本是不能作為成員變量初始化的一部分而運行的(就是if?語句)。所以對于匿名類而言,實例初始化的實際效果就是構造器。當然它受到了限制:你不能重載實例初始化。所以你僅僅能有一個構造器。

從多層嵌套類中訪問外部 一個內部類被嵌套多少層并不重要。它能透明地訪問全部它所嵌入的外圍類的全部成員,例如以下所看到的: class MNA?{ private void f() {} class A?{ private void g() {} public class B?{ void h() { g(); f(); } } } } public class MultiNestingAccess { public static void main(String[] args) { MNA mna = new MNA(); MNA.A mnaa = mna.new A(); MNA.A.B mnaab = mnaa.new B(); mnaab.h(); } } 能夠看到在MNA.A.B中,調用方法g()f()不須要不論什么條件(即使它們被定義為private)。這個樣例同一時候展示了怎樣從不同的類里面創建多層嵌套的內部類對象的基本的語法。“.new”語法能產生正確的作用域,所以你不必在調用構造器時限定類名。 內部類的重載問題 假設你創建了一個內部類,然后繼承其外圍類并又一次定義此內部類時。會發生什么呢?也就是說,內部類能夠被重載嗎?這看起來似乎是個非常實用的點子,可是“重載”內部類就好像它是外圍類的一個方法。事實上并不起什么作用: class?Egg { ???????private?Yolk?y; ???????protectedclass?Yolk { ??????????????public?Yolk() { ???????????????????? System.out.println("Egg.Yolk()"); ????????????? } ?????? } ???????public?Egg() { ????????????? System.out.println("New Egg()"); ??????????????y?=?new?Yolk(); ?????? } } publicclass?BigEgg?extends?Egg { ???????publicclass?Yolk { ??????????????public?Yolk() { ???????????????????? System.out.println("BigEgg.Yolk()"); ????????????? } ?????? } ???????publicstaticvoid?main(String[] args) { ??????????????new?BigEgg(); ?????? } } 輸出結果為: New Egg() Egg.Yolk() 缺省的構造器是編譯器自己主動生成的,這里是調用基類的缺省構造器。

你可能覺得既然創建了

BigEgg的對象,那么所使用的應該是被“重載”過的Yolk,但你能夠從輸出中看到實際情況并非這種。

這個樣例說明。當你繼承了某個外圍類的時候。內部類并沒有發生什么特別奇妙的變化。這兩個內部類是全然獨立的兩個實體,各自在自己的命名空間內。當然,明白地繼承某個內部類也是能夠的: class Egg2 { ?????? protected class Yolk { ????????????? public Yolk() { ???????????????????? System.out.println("Egg2.Yolk()"); ????????????? } ????????????? public void f() { ???????????????????? System.out.println("Egg2.Yolk.f()"); ????????????? } ?????? } ?????? private Yolk y = new Yolk(); ?????? public Egg2() { ????????????? System.out.println("New Egg2()"); ?????? } ?????? public void insertYolk(Yolk yy) { ????????????? y = yy; ?????? } ?????? public void g() { ????????????? y.f(); ?????? } } public class BigEgg2 extends Egg2 { ?????? public class Yolk extends Egg2.Yolk { ????????????? public Yolk() { ???????????????????? System.out.println("BigEgg2.Yolk()"); ????????????? } ????????????? public void f() { ???????????????????? System.out.println("BigEgg2.Yolk.f()"); ????????????? } ?????? } ?????? public BigEgg2() { ????????????? insertYolk(new Yolk()); ?????? } ?????? public static void main(String[] args) { ????????????? Egg2 e2 = new BigEgg2(); ????????????? e2.g(); ?????? } } 輸出結果為: Egg2.Yolk() New Egg2() Egg2.Yolk() BigEgg2.Yolk() BigEgg2.Yolk.f() 如今BigEgg2.Yolk?通過extends Egg2.Yolk?明白地繼承了此內部類,而且重載了當中的方法。Egg2insertYolk()方法使得BigEgg2?將它自己的Yolk?對象向上轉型,然后傳遞給引用y。所以當g()調用y.f()時,重載后的新版的f()被運行。第二次調用Egg2.Yolk()BigEgg2.Yolk?的構造器調用了其基類的構造器。能夠看到在調用g()的時候,新版的f()被調用了。

內部類的繼承問題thinking in java 3th p294 由于內部類的構造器要用到其外圍類對象的引用,所以在你繼承一個內部類的時候,事情變得有點復雜。問題在于。那個“秘密的”外圍類對象的引用必須被初始化。而在被繼承的類中并不存在要聯接的缺省對象。

要解決問題,需使用專門的語法來明白說清它們之間的關聯:

class?WithInner { class?Inner?{ Inner(){ System.out.println("this is a?constructor in WithInner.Inner"); }; } } public class InheritInner extends?WithInner.Inner { // ! InheritInner() {} // Won't compile InheritInner(WithInner wi) { wi.super(); System.out.println("this is a?constructor in InheritInner"); } public static void main(String[] args) { WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); } } 輸出結果為: this is a?constructor?in WithInner.Inner this is a?constructor?in InheritInner 能夠看到,InheritInner?僅僅繼承自內部類,而不是外圍類。可是當要生成一個構造器時,缺省的構造器并不算好,并且你不能僅僅是傳遞一個指向外圍類對象的引用。此外。你必須在構造器內使用例如以下語法: enclosingClassReference.super(); 這樣才提供了必要的引用,然后程序才干編譯通過。

轉載于:https://www.cnblogs.com/yfceshi/p/6753660.html

總結

以上是生活随笔為你收集整理的java内部类总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。