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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java Inner Class 内部类

發(fā)布時間:2023/12/13 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Inner Class 内部类 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

內(nèi)部類 ?Inner Class

一個內(nèi)部類可以定義在另一個類里,可以定義在函數(shù)里,甚至可以作為一個表達式的一部分。

Java中的內(nèi)部類共分為四種

  靜態(tài)內(nèi)部類static inner class (also called nested class)

  成員內(nèi)部類member inner class

  局部內(nèi)部類local inner class

  匿名內(nèi)部類anonymous inner class

?

1?成員內(nèi)部類 ?member inner class

?

1.1 形式

成員內(nèi)部類也是定義在另一個類中,但是定義時不用static修飾。形如:

1 class Outer { 2 class Inner{ 3 4 } 5 }

編譯之后會產(chǎn)生如下2個class文件:

?

---->這可以將相關(guān)的類組織在一起,從而降低了命名空間的混亂。

?

成員內(nèi)部類的修飾符:
對于普通的類,可用的修飾符有final、abstract、strictfp、public和默認的包訪問。
但是成員內(nèi)部類更像一個成員變量和方法。
可用的修飾符有:final、abstract、public、private、protected、strictfp和static。
一旦用static修飾內(nèi)部類,它就變成靜態(tài)內(nèi)部類了。

?

1.2 創(chuàng)建內(nèi)部類實例

成員內(nèi)部類就像一個實例變量,他依賴于外部類的實例存在 --> 必須先有外部類的實例 ?才能創(chuàng)建成員內(nèi)部類對象

在外部類里面創(chuàng)建成員內(nèi)部類的實例:this.new Innerclass(); 或可以用 Inner inner = new Inner(); 方法直接創(chuàng)建

在外部類之外創(chuàng)建內(nèi)部類的實例:(new Outerclass()).new Innerclass(); ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 或 ??Inner inner = new Outer().new Inner()

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 或 ??Outer outer = new Outer(); Inner inner = outer.new Inner();

案例:從外部類的非靜態(tài)方法中實例化內(nèi)部類對象。

1 class Outer { 2 private int i = 10; 3 public void makeInner(){ 4 Inner in = new Inner(); 5 in.seeOuter(); 6 } 7 class Inner{ 8 public void seeOuter(){ 9 System.out.print(i); 10 } 11 } 12 }

表面上,我們并沒有創(chuàng)建外部類的對象就實例化了內(nèi)部類對象,和上面的話矛盾。
事實上,如果不創(chuàng)建外部類對象也就不可能調(diào)用makeInner()方法,所以到頭來還是要創(chuàng)建外部類對象的。
你可能試圖把makeInner()方法修飾為靜態(tài)方法,即static public void makeInner()。
這樣不創(chuàng)建外部類就可以實例化外部類了!但是在一個靜態(tài)方法里能訪問非靜態(tài)成員和方法嗎?顯然不能。

-->?必須先有外部類的實例 ?才能創(chuàng)建成員內(nèi)部類對象

案例:從外部類的靜態(tài)方法中實例化內(nèi)部類對象

1 class Outer { 2 private int i = 10; 3 class Inner{ 4 public void seeOuter(){ 5 System.out.print(i); 6 } 7 } 8 public static void main(String[] args) { 9 Outer out = new Outer(); 10 Outer.Inner in = out.new Inner(); 11 //Outer.Inner in = new Outer().new Inner(); 12 in.seeOuter(); 13 } 14 }

被注釋掉的那行是它上面兩行的合并形式,一條簡潔的語句。
對比一下:在外部類的非靜態(tài)方法中實例化內(nèi)部類對象是普通的new方式:Inner in = new Inner();
在外部類的靜態(tài)方法中實例化內(nèi)部類對象,必須先創(chuàng)建外部類對象:Outer.Inner in = new Outer().new Inner();

?

1.3 成員內(nèi)部類操作外部類

?

成員內(nèi)部類可以訪問它的外部類的所有成員變量和方法,不管是靜態(tài)的還是非靜態(tài)的都可以

內(nèi)部類就像一個實例成員一樣存在于外部類,所以內(nèi)部類可以訪問外部類的所有成員就想訪問自己的成員一樣沒有限制。

?

內(nèi)部類中的this指的是內(nèi)部類的實例對象本身,如果要用外部類的實例對象就可以用類名.this的方式獲得。

普通的類可以用this引用當前的對象,內(nèi)部類也是如此。

但是假若內(nèi)部類想引用外部類當前的對象呢?用“外部類名”.this;的形式,如下例的Outer.this。

1 class Outer { 2 class Inner{ 3 public void seeOuter(){ 4 System.out.println(this); 5 System.out.println(Outer.this); 6 } 7 } 8 9 public static void main(String[] strs){ 10 new Outer().new Inner().seeOuter(); 11 } 12 } 13 14 輸出: 15 Outer$Inner@61de33 16 Outer@14318bb

1.4?內(nèi)部類對象中不能有靜態(tài)成員

原因很簡單,內(nèi)部類的實例對象是外部類實例對象的一個成員,若沒有外部類對象,內(nèi)部類就不會存在,何談靜態(tài)成員呢。

1 class Outer { 2 class Inner{ 3 static int i = 0; 4 public void seeOuter(){ 5 System.out.println(this); 6 System.out.println(Outer.this); 7 } 8 } 9 10 public static void main(String[] strs){ 11 new Outer().new Inner().seeOuter(); 12 } 13 }

我們編譯這個類:

1 E:\>javac Outer.java 2 Outer.java:3: 內(nèi)部類不能有靜態(tài)聲明 3 static int i = 0; 4 ^ 5 1 錯誤

?

2?局部內(nèi)部類local inner class

?

局部內(nèi)部類local inner class 也可以成為方法內(nèi)部類

顧名思義,就是把類放在方法內(nèi)。局部內(nèi)部類定義在方法中,比方法的范圍還小。是內(nèi)部類中最少用到的一種類型。

像局部變量一樣,不能被public, protected, private和static修飾。

局部內(nèi)部類在方法中定義,所以只能在方法中使用,即只能在方法當中生成局部內(nèi)部類的實例并且調(diào)用其方法。

1 class Outer { 2 public void doSomething(){ 3 class Inner{ 4 public void seeOuter(){ 5 System.out.println("inner class"); 6 } 7 } 8 9 Inner inner = new Inner(); 10 inner.seeOuter(); 11 } 12 13 public static void main(String ... args){ 14 new Outer().doSomething(); 15 } 16 }

輸出:

inner class

局部內(nèi)部類只能在聲明的方法內(nèi)是可見的,因此定義局部內(nèi)部類之后,想用的話就要在方法內(nèi)直接實例化,
記住這里順序不能反了,一定是要先聲明后使用,否則編譯器會說找不到。

方法內(nèi)部類的修飾符:
? 與成員內(nèi)部類不同,方法內(nèi)部類更像一個局部變量。
? 可以用于修飾方法內(nèi)部類的只有final和abstract。


注意事項:

A: 方法內(nèi)部類只能在定義該內(nèi)部類的方法內(nèi)實例化,不可以在此方法外對其實例化
B: 方法內(nèi)部類對象不能使用該內(nèi)部類所在方法的非final局部變量。

原因:

? ? ?因為方法的局部變量位于棧上,只存在于該方法的生命期內(nèi)。當一個方法結(jié)束,其棧結(jié)構(gòu)被刪除,局部變量成為歷史。
? ? 但是該方法結(jié)束之后,在方法內(nèi)創(chuàng)建的內(nèi)部類對象可能仍然存在于堆中!例如,如果對它的引用被傳遞到其他某些代碼,并存儲在一個成員變量內(nèi)。
? ? 正因為不能保證局部變量的存活期和方法內(nèi)部類對象的一樣長,所以內(nèi)部類對象不能使用它們。下面是完整的例子:

1 class Outer { 2 public void doSomething(){ 3   final int a =10; 4   class Inner{ 5     public void seeOuter(){ 6       System.out.println(a); 7     } 8   } 9   Inner in = new Inner(); 10   in.seeOuter(); 11 } 12   public static void main(String[] args) { 13     Outer out = new Outer(); 14     out.doSomething(); 15 } 16 }

? C:靜態(tài)方法內(nèi)的方法內(nèi)部類。

? ? ?靜態(tài)方法是沒有this引用的,因此在靜態(tài)方法內(nèi)的內(nèi)部類遭受同樣的待遇,即:只能訪問外部類的靜態(tài)成員。

?

3?匿名內(nèi)部類Anonymous Inner Class

顧名思義,沒有名字的內(nèi)部類。

匿名內(nèi)部類就是沒有名字的局部內(nèi)部類,不使用關(guān)鍵字class, extends, implements, 沒有構(gòu)造方法。

匿名內(nèi)部類隱式地繼承了一個父類或者實現(xiàn)了一個接口

匿名內(nèi)部類使用得比較多,通常是作為一個方法參數(shù)。

?

A、繼承式的匿名內(nèi)部類。

1 class Car { 2 public void drive(){ 3 System.out.println("Driving a car!"); 4 } 5 } 6 7 8 class Test{ 9 public static void main(String[] args) { 10 Car car = new Car(){ 11 public void drive(){ 12 System.out.println("Driving another car!"); 13 } 14 }; 15 car.drive(); 16 } 17 }

?

結(jié)果輸出了:Driving another car!


建立匿名內(nèi)部類的關(guān)鍵點是重寫父類的一個或多個方法。再強調(diào)一下,是重寫父類的方法,而不是創(chuàng)建新的方法。
因為用父類的引用不可能調(diào)用父類本身沒有的方法!創(chuàng)建新的方法是多余的。簡言之,參考多態(tài)。

?

B、接口式的匿名內(nèi)部類。

1 interface Vehicle { 2 public void drive(); 3 } 4 5 6 class Test{ 7 public static void main(String[] args) { 8 Vehicle v = new Vehicle(){ 9 public void drive(){ 10 System.out.println("Driving a car!"); 11 } 12 }; 13 v.drive(); 14 }

這種形式的代碼我們一定寫過,這也是內(nèi)部類的存在的一個重要作用:便于編寫 線程和事件驅(qū)動的代碼

1 public class ThreadDemo { 2 public static void main(String[] args) { 3 4 new Thread(new Runnable(){ 5 public void run(){ 6 System.out.println("Hello World!"); 7 } 8 }).start(); 9 } 10 } 11 12 13 E:\>javac ThreadDemo.java 14 E:\>java ThreadDemo 15 Hello World! 1 public class SwingTest 2 { 3 public static void main(String[] args) 4 { 5 JFrame frame = new JFrame("JFrame"); 6 JButton button = new JButton("JButton"); 7 8 button.addActionListener(new ActionListener(){ 9 10 @Override 11 public void actionPerformed(ActionEvent arg0){ 12 System.out.println("Hello World"); 13 14 } 15 }); 16 17 frame.getContentPane().add(button); 18 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 frame.setSize(200, 200); 20 21 frame.addWindowListener(new WindowAdapter() { 22 23 @Override 24 public void windowClosing(WindowEvent e){ 25 System.out.println("Closing"); 26 System.exit(0); 27 } 28 }); 29 30 frame.setVisible(true); 31 } 32 }

若你了解安卓的話 ?會發(fā)現(xiàn)這樣的代碼編寫方式有著很多的應(yīng)用

好處就是簡化我們的代碼。

?

C、參數(shù)式的匿名內(nèi)部類。

1 class Bar{ 2 void doStuff(Foo f){} 3 } 4 5 inteface Foo{ 6 void foo(); 7 } 8 9 class Test{ 10 static void go(){ 11 Bar b = new Bar(); 12 b.doStuff(new Foo(){ 13 public void foo(){ 14 System.out.println("foofy"); 15 } 16 }); 17 } 18 } 19

?

4?靜態(tài)內(nèi)部類static inner class?

?

在定義成員內(nèi)部類的時候,可以在其前面加上一個權(quán)限修飾符static。此時這個內(nèi)部類就變?yōu)榱遂o態(tài)內(nèi)部類。

同樣會被編譯成一個完全獨立的.class文件,名稱為OuterClass$InnerClass.class的形式。

只可以訪問外部類的靜態(tài)成員和靜態(tài)方法,包括了私有的靜態(tài)成員和方法。

生成靜態(tài)內(nèi)部類對象的方式為:OuterClass.InnerClass inner = new OuterClass.InnerClass();

?

靜態(tài)內(nèi)部類使用代碼:

1 package com.learnjava.innerclass; 2 3 class StaticInner 4 { 5 private static int a = 4; 6 7 // 靜態(tài)內(nèi)部類 8 public static class Inner 9 { 10 public void test() 11 { 12 // 靜態(tài)內(nèi)部類可以訪問外部類的靜態(tài)成員 13 // 并且它只能訪問靜態(tài)的 14 System.out.println(a); 15 } 16 17 } 18 } 19 20 public class StaticInnerClassTest 21 { 22 23 public static void main(String[] args) 24 { 25 StaticInner.Inner inner = new StaticInner.Inner(); 26 inner.test(); 27 } 28 }

?

與一般內(nèi)部類不同,在靜態(tài)代碼中不能夠使用this操作,所以在靜態(tài)內(nèi)部類中只可以訪問外部類的靜態(tài)變量和靜態(tài)方法。
使用靜態(tài)內(nèi)部類的目的和使用內(nèi)部類相同。如果一個內(nèi)部類不依賴于其外部類的實例變量,或與實例變量無關(guān),則選擇應(yīng)用靜態(tài)內(nèi)部類。

可以在靜態(tài)內(nèi)部類的方法中,直接訪問外部類的靜態(tài)變量和調(diào)用靜態(tài)方法。但不允許訪問外部類的實例變量以及實例方法。
靜態(tài)內(nèi)部類的實例方法中亦只允許訪問外部類的靜態(tài)成員。

?

靜態(tài)內(nèi)部類不同于其他3種內(nèi)部類,他有著自己特殊的特性,參看:解析靜態(tài)內(nèi)部類的使用目的與限制

?

5 小結(jié)

?

5.1?幾種內(nèi)部類的共性:

A、內(nèi)部類仍然是一個獨立的類,在編譯之后會內(nèi)部類會被編譯成獨立的.class文件,但是前面冠以外部類的類命和$符號。
B、內(nèi)部類不能用普通的方式訪問。內(nèi)部類是外部類的一個成員,因此內(nèi)部類可以自由地訪問外部類的成員變量,無論是否是private的。

?

5.2?java中為什么要引入內(nèi)部類?還有匿名內(nèi)部類?

?

1)可以是單繼承的一種補充解決方案 inner classes能有效實際地允許“多重實現(xiàn)繼承(multiple implementation)”

? ?Java中一個類只能繼承一個類 可以通過內(nèi)部類達到繼承多個類的效果

? ?:每個inner class都能夠各自繼承某一實現(xiàn)類(implementation),因此,inner class不受限于outer class是否已繼承自某一實現(xiàn)類。?

2)針對具體的問題提供具體的解決方案,同時又能對外隱藏實現(xiàn)細節(jié) ? ?看具體的案例

?

案例1

在集合中可以使用Iterator遍歷 但每一種集合的數(shù)據(jù)結(jié)構(gòu)不同 ?導致遍歷的方法必然也不同
所以Java在每個具體的集合里定義了一個內(nèi)部類Itr ?他實現(xiàn)了Iterator接口 ? 從而根據(jù)所在類的具體情況進行遍歷

1 public interface Iterator {//迭代器的功能 2 boolean hasNext(); 3 Object next(); 4 } 5 6 public interface Iterable {//返回迭代器的能力 7 Iterator iterator(); 8 } 9 10 public interface Collection extends Iterable { 11 Iterator iterator(); 12 } 13 14 public interface List extends Collection { 15 Iterator iterator(); 16 } 17 18 public class ArrayList implements List { 19 public Iterator iterator() { 20 return new Itr(); 21 } 22 23 private class Itr implements Iterator { 24 //每種集合的具體實現(xiàn)采用了不同的數(shù)據(jù)結(jié)構(gòu) 25 public boolean hasNext() {......} 26 public Object next(){......} 27 } 28 } 29 30 Collection c = new ArrayList(); 31 c.add("hello"); 32 c.add("world"); 33 c.add("java"); 34 Iterator it = c.iterator(); //new Itr(); 35 while(it.hasNext()) { 36 String s = (String)it.next(); 37 System.out.println(s); 38 }

Itr是private的類 對外并不可見 因為我的遍歷方法我自己知道就可以了 別人并不需要了解

集合類有實現(xiàn)了Tterable接口 通過里面的iterator方法獲取該內(nèi)部類實例 外部不能直接創(chuàng)建該內(nèi)部類的實例

?

案例2

為某個類提供特定的數(shù)據(jù)結(jié)構(gòu) :? 為了共同解決一個具體的問題 但又可以對外部保持透明

如HashMap中有Entry ? ConcurrentHashMap有HashEntry 和Segment ?

看HashMap中的內(nèi)部類:

1 public class HashMap<K,V> 2 extends AbstractMap<K,V> 3 implements Map<K,V>, Cloneable, Serializable 4 { 5 6 static final Entry<?,?>[] EMPTY_TABLE = {}; 7 transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE; 8 9 static class Entry<K,V> implements Map.Entry<K,V> { 10 final K key; 11 V value; 12 Entry<K,V> next; 13 int hash; 14 // ... ... 15 } 16 }

關(guān)于HashMap 可以參考:HashMap源碼解析

關(guān)于ConcurrentHashMap:ConcurrentHashMap??ConcurrentHashMap原理分析

轉(zhuǎn)載于:https://www.cnblogs.com/wihainan/p/4773090.html

總結(jié)

以上是生活随笔為你收集整理的Java Inner Class 内部类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。