最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java內(nèi)部類(lèi)的使用教程詳解

 更新時(shí)間:2023年04月07日 10:53:54   作者:可愛(ài)的小鋒  
在Java中,有些類(lèi)可以被定義在另一個(gè)類(lèi)的內(nèi)部,我們把在一個(gè)類(lèi)里面定義的類(lèi)稱(chēng)為內(nèi)部類(lèi)。本文主要介紹了Java內(nèi)部類(lèi)的使用,需要的可以參考一下

一. 內(nèi)部類(lèi)簡(jiǎn)介

1. 概念

在Java中,我們通常是把不同的類(lèi)創(chuàng)建在不同的包里面,對(duì)于同一個(gè)包里的類(lèi)來(lái)說(shuō),它們都是同一層次的。但其實(shí)還有另一種情況,有些類(lèi)可以被定義在另一個(gè)類(lèi)的內(nèi)部,我們把在一個(gè)類(lèi)里面定義的類(lèi)稱(chēng)為內(nèi)部類(lèi)(InnerClass)或嵌套類(lèi),把外面定義的類(lèi)稱(chēng)為外部類(lèi)(OutClass)或宿主類(lèi)。 也就是說(shuō),在類(lèi)的內(nèi)部既可以定義成員變量和方法,也可以定義其他的類(lèi)。定義內(nèi)部類(lèi)的常見(jiàn)格式如下:

class Outer {//外部類(lèi)
    
    class Inner {//內(nèi)部類(lèi)
        
        //方法和屬性
    }
    
}

上面的代碼中,Outer是普通的外部類(lèi),Inner就是內(nèi)部類(lèi)。它與普通外部類(lèi)最大的不同,在于其實(shí)例對(duì)象不能單獨(dú)存在,必須依附于一個(gè)外部類(lèi)的實(shí)例對(duì)象。

內(nèi)部類(lèi)可以很好地實(shí)現(xiàn)隱藏,一般的非內(nèi)部類(lèi)是不允許有private 與 protected權(quán)限的,但內(nèi)部類(lèi)卻可以,而且內(nèi)部類(lèi)還擁有外部類(lèi)中所有元素的訪問(wèn)權(quán)限??傊?,對(duì)內(nèi)部類(lèi)的很多訪問(wèn)規(guī)則都可以參考變量和方法。

但是要注意,雖然我們使用內(nèi)部類(lèi)可以使程序結(jié)構(gòu)變得更加緊湊,但卻在一定程度上破壞了面向?qū)ο蟮乃枷搿?/p>

2. 優(yōu)點(diǎn)

內(nèi)部類(lèi)的存在,具有如下優(yōu)點(diǎn):

  • 內(nèi)部類(lèi)使得多繼承的解決方案變得更完整:每個(gè)內(nèi)部類(lèi)都能獨(dú)立的實(shí)現(xiàn)接口,無(wú)論外部類(lèi)是否已經(jīng)實(shí)現(xiàn)了接口或繼承了父類(lèi),對(duì)于內(nèi)部類(lèi)都沒(méi)有影響;
  • 既可以方便地將存在一定邏輯關(guān)系的類(lèi)組織在一起,又可以對(duì)外界隱藏;
  • 方便各類(lèi)編寫(xiě)事件驅(qū)動(dòng)程序;
  • 方便編寫(xiě)線程代碼。

3. 分類(lèi)

Java中的內(nèi)部類(lèi)可以分為如下幾種類(lèi)型:

  • 成員內(nèi)部類(lèi)
  • 靜態(tài)內(nèi)部類(lèi)
  • 局部?jī)?nèi)部類(lèi)
  • 匿名內(nèi)部類(lèi)

雖然大多數(shù)時(shí)候,內(nèi)部類(lèi)用得并不多,但我們也有必要了解它們是如何具體使用的。

4. 內(nèi)部類(lèi)的特點(diǎn)

內(nèi)部類(lèi)相比外部類(lèi),具有如下特點(diǎn):

  • 內(nèi)部類(lèi)可以訪問(wèn)外部類(lèi)的私有成員,且不破壞封裝性;
  • 內(nèi)部類(lèi)仍是一個(gè)獨(dú)立的類(lèi),在編譯之后內(nèi)部類(lèi)會(huì)被編譯成獨(dú)立的.class文件,但前面會(huì)冠以外部類(lèi)的類(lèi)名和$符號(hào),該文件名的格式是外部類(lèi)名$內(nèi)部類(lèi)名.class;
  • 因?yàn)閮?nèi)部類(lèi)是外部類(lèi)的一個(gè)成員,所以?xún)?nèi)部類(lèi)不能用普通的方式訪問(wèn),但內(nèi)部類(lèi)可以自由地訪問(wèn)外部類(lèi)里的成員變量,無(wú)論是否被private修飾;
  • 如果是靜態(tài)內(nèi)部類(lèi),我們不能隨便訪問(wèn)外部類(lèi)的成員變量,只能訪問(wèn)外部類(lèi)的靜態(tài)成員變量。

5. Java類(lèi)的創(chuàng)建要求

我們?cè)趧?chuàng)建定義Java類(lèi)時(shí),應(yīng)該遵循如下要求:

  • 一個(gè)java文件中可以編寫(xiě)多個(gè)類(lèi),但只能有一個(gè)類(lèi)使用public關(guān)鍵詞進(jìn)行修飾,這稱(chēng)之為主類(lèi);
  • 主類(lèi)名必須與文件名一致,在開(kāi)發(fā)中,應(yīng)盡量只在一個(gè)java文件中編寫(xiě)一個(gè)類(lèi);
  • 外部類(lèi)只有兩種訪問(wèn)級(jí)別:public 和默認(rèn);內(nèi)部類(lèi)則有 4 種訪問(wèn)級(jí)別:public、protected、 private 和默認(rèn);
  • 在外部類(lèi)中,可以直接通過(guò)內(nèi)部類(lèi)的類(lèi)名來(lái)訪問(wèn)內(nèi)部類(lèi);
  • 在外部類(lèi)以外的其他類(lèi)中,需要通過(guò)內(nèi)部類(lèi)的完整類(lèi)名來(lái)訪問(wèn)內(nèi)部類(lèi);
  • 內(nèi)部類(lèi)與外部類(lèi)不能重名。

接下來(lái)我們就針對(duì)上面提到的幾種內(nèi)部類(lèi),分別給大家講解這幾種內(nèi)部類(lèi)的用法。

二. 成員內(nèi)部類(lèi)

1. 概念

成員內(nèi)部類(lèi)就是指沒(méi)有被static修飾的內(nèi)部類(lèi),也可以稱(chēng)為非靜態(tài)內(nèi)部類(lèi)。

2. 特點(diǎn)

成員內(nèi)部類(lèi)具有如下特點(diǎn):

  • 在早期的jdk版本中,成員內(nèi)部類(lèi)中只能定義非靜態(tài)的屬性和方法,除非同時(shí)使用final和static進(jìn)行修飾;
  • 在新版的jdk中,成員內(nèi)部類(lèi)中也可以定義靜態(tài)的屬性和方法;
  • 成員內(nèi)部類(lèi)可以訪問(wèn)外部類(lèi)的所有成員,包括私有和靜態(tài)的成員,即使是多層嵌套時(shí)也如此;
  • 外部類(lèi)不能直接訪問(wèn)內(nèi)部類(lèi)的成員,必須通過(guò)內(nèi)部類(lèi)的實(shí)例對(duì)象訪問(wèn);
  • 在外部類(lèi)的靜態(tài)方法和外部類(lèi)以外的其他類(lèi)中,必須通過(guò)外部類(lèi)的實(shí)例創(chuàng)建內(nèi)部類(lèi)的實(shí)例對(duì)象;
  • 外部類(lèi)的實(shí)例與內(nèi)部類(lèi)實(shí)例是一對(duì)多的關(guān)系,即一個(gè)內(nèi)部類(lèi)實(shí)例只對(duì)應(yīng)一個(gè)外部類(lèi)實(shí)例,但一個(gè)外部類(lèi)實(shí)例則可以對(duì)應(yīng)多個(gè)內(nèi)部類(lèi)實(shí)例。

3. 語(yǔ)法

如果是在外部類(lèi)中,創(chuàng)建成員內(nèi)部類(lèi)對(duì)象的基本語(yǔ)法格式如下:

內(nèi)部類(lèi) 對(duì)象名 = new 內(nèi)部類(lèi)();

如果是在外部的其他類(lèi)中,或者是在外部類(lèi)的靜態(tài)方法中,創(chuàng)建成員內(nèi)部類(lèi)對(duì)象的基本語(yǔ)法格式如下:

內(nèi)部類(lèi) 對(duì)象名 = new 外部類(lèi)().new 內(nèi)部類(lèi)();

4. 案例

4.1 定義成員內(nèi)部類(lèi)

/**
 * 成員內(nèi)部類(lèi)
 */
public class OuterClass {

	// 外部類(lèi)的非靜態(tài)成員
	String name = "一一哥";
	private String hobby = "擼碼";
	static int age = 30;

	// 非靜態(tài)方法
	public void show() {
		//這里的this是指OuterClass對(duì)象
		System.out.println("show方法...name="+this.name);

        //如果是在外部類(lèi)里面創(chuàng)建內(nèi)部類(lèi)的對(duì)象,就不需要?jiǎng)?chuàng)建外部類(lèi)實(shí)例,可以直接new 內(nèi)部類(lèi)()
		//InnerClass inner = new InnerClass();
	}

	// 定義一個(gè)成員內(nèi)部類(lèi)
	public class InnerClass {
		// 也可以定義私有屬性
		private int a = 10;

		//在早期的JDK中,成員內(nèi)部類(lèi)中不能定義靜態(tài)變量;但在新版JDK中,成員內(nèi)部類(lèi)中可以定義靜態(tài)變量
		static int b = 20;

		// 非靜態(tài)方法
		public void m1() {
			// 這里的this對(duì)象是InnerClass內(nèi)部類(lèi)對(duì)象
			System.out.println("成員內(nèi)部類(lèi)的成員變量:" + this.a);
			
			//外部類(lèi).this.屬性或方法,這個(gè)this是外部類(lèi)對(duì)象
			System.out.println("外部類(lèi)的成員變量:" + OuterClass.this.name);
			
            //內(nèi)部類(lèi)中可以訪問(wèn)外部類(lèi)的私有成員和靜態(tài)成員
			System.out.println("外部類(lèi)的私有成員變量:" + hobby);
			System.out.println("外部類(lèi)的靜態(tài)變量:" + age);
		}

		//在早期的JDK中,成員內(nèi)部類(lèi)中不能定義靜態(tài)方法;但在新版JDK中,成員內(nèi)部類(lèi)中可以定義靜態(tài)方法
		public static void m2() {
			System.out.println("調(diào)用成員內(nèi)部類(lèi)的靜態(tài)變量:" + b);
			System.out.println("調(diào)用外部類(lèi)的靜態(tài)變量:" + age);

            //在靜態(tài)方法中創(chuàng)建內(nèi)部類(lèi)對(duì)象,也要通過(guò)內(nèi)部類(lèi) 對(duì)象名 = new 外部類(lèi)().new 內(nèi)部類(lèi)();的格式
			//InnerClass innerClass = new OuterClass().new InnerClass();
		}

	}

}

我們要注意,在早期的JDK中,成員內(nèi)部類(lèi)中不能定義靜態(tài)屬性和方法;但在新版JDK中,成員內(nèi)部類(lèi)中可以定義靜態(tài)的屬性和方法。并且我們要搞清楚在不同的位置上,創(chuàng)建內(nèi)部類(lèi)對(duì)象的方式,以及this的具體含義。

4.2 定義測(cè)試類(lèi)

我們?cè)谕獠康钠渌?lèi)中,要想創(chuàng)建出一個(gè)成員內(nèi)部類(lèi)的對(duì)象,需要通過(guò)如下形式:

內(nèi)部類(lèi) 對(duì)象名 = new 外部類(lèi)().new 內(nèi)部類(lèi)();

public class InnerClassTest {

	public static void main(String[] args) {
		
		//在外部的其他類(lèi)中,不能直接創(chuàng)建內(nèi)部類(lèi)對(duì)象,否則:
		//No enclosing instance of type OuterClass is accessible. 
		//Must qualify the allocation with an enclosing instance of type OuterClass 
		//(e.g. x.new A() where x is an instance of OuterClass).
		//InnerClass inner=new InnerClass();

        //在外部的其他類(lèi)中創(chuàng)建內(nèi)部類(lèi)對(duì)象,需要通過(guò)如下格式:
		//內(nèi)部類(lèi) 對(duì)象名 = new 外部類(lèi)().new 內(nèi)部類(lèi)();
		//InnerClass inner=new OuterClass().new InnerClass();
		
		//也可以拆分成如下格式:
		OuterClass outer=new OuterClass();
		InnerClass inner=outer.new InnerClass();
		
		inner.m1();
		
		InnerClass.m2();
		
	}
}

5. 訪問(wèn)方式小結(jié)

學(xué)習(xí)到這里,你可能會(huì)被內(nèi)部類(lèi)與外部類(lèi)之間的調(diào)用訪問(wèn)關(guān)系整蒙圈,所以給大家梳理了一下訪問(wèn)方式:

  • 成員內(nèi)部類(lèi) 訪問(wèn) 外部類(lèi)的成員(屬性、方法),可以【直接訪問(wèn)使用】;
  • 外部類(lèi) 訪問(wèn) 成員內(nèi)部類(lèi),需要【直接創(chuàng)建內(nèi)部類(lèi)對(duì)象后再訪問(wèn)】,即 new InnerClass();
  • 外部的其他類(lèi) 訪問(wèn) 成員內(nèi)部類(lèi),需要【創(chuàng)建外部類(lèi)對(duì)象,再創(chuàng)建內(nèi)部類(lèi)對(duì)象后訪問(wèn)】,即 InnerClass inner=new OuterClass().new InnerClass();

6. 關(guān)于this的注意事項(xiàng)

在之前給大家講過(guò)this的作用和用法,但在內(nèi)部類(lèi)中,關(guān)于this,我們需要注意以下兩點(diǎn):

如果同時(shí)存在外部類(lèi)和內(nèi)部類(lèi),那么this在哪個(gè)類(lèi)中使用,this就代表哪個(gè)類(lèi)的對(duì)象;

 如果內(nèi)部類(lèi)想要通過(guò)this來(lái)調(diào)用外部類(lèi)的屬性和方法,需要使用外部類(lèi)名.this.屬性或者方法名。

三. 局部?jī)?nèi)部類(lèi)

1. 概念

局部?jī)?nèi)部類(lèi)是指在方法中定義的內(nèi)部類(lèi)。

2. 特點(diǎn)

局部?jī)?nèi)部類(lèi)具有如下特點(diǎn):

  • 局部?jī)?nèi)部類(lèi)只能在方法中定義和創(chuàng)建對(duì)象,也只在當(dāng)前方法中有效;
  • 局部?jī)?nèi)部類(lèi)中可以訪問(wèn)外部類(lèi)的所有成員;
  • 局部?jī)?nèi)部類(lèi)與局部變量一樣,不能使用訪問(wèn)控制修飾符(public、private和protected)和static修飾符;
  • 在jdk 7版本中,如果局部變量是在局部?jī)?nèi)部類(lèi)中使用,必須顯式地加上final關(guān)鍵字;在jdk 8版本中,會(huì)默認(rèn)添加final關(guān)鍵字;
  • 局部?jī)?nèi)部類(lèi)只能訪問(wèn)當(dāng)前方法中final類(lèi)型的參數(shù)與變量。如果方法中的成員與外部類(lèi)的成員同名,可以使用 .this. 的形式訪問(wèn)外部類(lèi)成員;
  • 局部?jī)?nèi)部類(lèi)中還可以包含內(nèi)部類(lèi),但這些內(nèi)部類(lèi)也不能使用訪問(wèn)控制修飾符(public、private 和 protected) 和 static修飾符;
  • 局部變量在方法執(zhí)行結(jié)束后會(huì)被銷(xiāo)毀,而局部?jī)?nèi)部類(lèi)的對(duì)象會(huì)等到內(nèi)存回收機(jī)制進(jìn)行銷(xiāo)毀。如果是局部?jī)?nèi)部類(lèi)里的常量,該常量會(huì)被存放在常量池中。

3. 語(yǔ)法

創(chuàng)建局部?jī)?nèi)部類(lèi)對(duì)象的基本語(yǔ)法格式如下:

public class PartClass {
    
    public void method() {
        //在方法中定義的內(nèi)部類(lèi),就是局部?jī)?nèi)部類(lèi)
        class Inner {
            //屬性

            //方法
        }
    }
    
}

4. 案例

4.1 定義局部?jī)?nèi)部類(lèi)

我們來(lái)定義一個(gè)局部?jī)?nèi)部類(lèi)的案例代碼。

/**
 * 
  * 局部?jī)?nèi)部類(lèi)---定義在方法中的內(nèi)部類(lèi)
 */
public class PartOuterClass {

	//類(lèi)的成員變量
	String name="一一哥";
    private int age=30;
    static String hobby="java";
    
    public void show() {
    	//局部變量
        //JDK 7之前,匿名內(nèi)部類(lèi)和局部?jī)?nèi)部類(lèi)中訪問(wèn)外部的局部變量時(shí),該變量需要明確地帶有final修飾符
        //final int num = 10;
        
        //Effectively final特性
        int num = 10;
        
        //局部?jī)?nèi)部類(lèi),類(lèi)似于是方法中的局部對(duì)象
        class PartInnerClass{
        	
        	//內(nèi)部可以正常定義方法
            public void m1() {
            	//訪問(wèn)外部類(lèi)的非靜態(tài)成員,可以使用OuterClass.this.成員的格式,也可以直接訪問(wèn)
            	//System.out.println("外部類(lèi)的成員變量"+name);
                System.out.println("外部類(lèi)的成員變量"+PartOuterClass.this.name);
                System.out.println("外部類(lèi)私有的成員變量"+age);
                System.out.println("外部類(lèi)的靜態(tài)變量"+hobby);
                
                //局部?jī)?nèi)部類(lèi),可以直接訪問(wèn)方法中的局部變量
                System.out.println("訪問(wèn)局部變量"+num);
            }
            
            //在新版的jdk中,也可以定義靜態(tài)的屬性和方法,老版的jdk則不行
            static int b=10;
            
            public static void m2() {
            	System.out.println("外部類(lèi)的靜態(tài)變量,hobby="+hobby+",b="+b);
            }
        }
        
        //創(chuàng)建局部?jī)?nèi)部類(lèi)對(duì)象
        PartInnerClass inner = new PartInnerClass();
        inner.m1();
        
        //在當(dāng)前類(lèi)中,局部?jī)?nèi)部類(lèi)可以直接訪問(wèn)靜態(tài)成員
        PartInnerClass.m2();
        
    }    
    
}

在JDK 7之前,匿名內(nèi)部類(lèi)和局部?jī)?nèi)部類(lèi)中訪問(wèn)外部的局部變量時(shí),該變量需要明確地帶有final修飾符。但從JDK 8之后,我們可以不帶final修飾符,而是由系統(tǒng)默認(rèn)添加了。

4.2 定義測(cè)試類(lèi)

接下來(lái)我們對(duì)上面的案例進(jìn)行測(cè)試。

public class PartInnerClassTest {

	public static void main(String[] args) {
		//創(chuàng)建外部類(lèi)對(duì)象,調(diào)用方法,執(zhí)行局部?jī)?nèi)部類(lèi)
		PartOuterClass outer=new PartOuterClass();
		outer.show();
	}
}

4.3 Effectively final特性

一般情況下,Java中的局部?jī)?nèi)部類(lèi)和匿名內(nèi)部類(lèi)訪問(wèn)局部變量時(shí),該變量必須由 final修飾,以保證內(nèi)部類(lèi)和外部類(lèi)的數(shù)據(jù)一致性。但從 Java 8開(kāi)始,我們可以不加 final修飾符,而是由系統(tǒng)默認(rèn)添加,當(dāng)然這在 Java 8以前是不允許的。Java將這個(gè)新的特性稱(chēng)為 Effectively(有效的、實(shí)際的) final 功能。

另外在 Lambda表達(dá)式中,使用局部變量時(shí)也要求該變量必須是 final 修飾的,所以 effectively final特性在 Lambda表達(dá)式的上下文中非常有用。

其實(shí)effectively final特性,只是讓我們不用顯式地把變量聲明為final修飾的,它給我們自動(dòng)添加了final修飾詞,但并沒(méi)有取消final,主要是減少了一點(diǎn)不必要的操作,給開(kāi)發(fā)節(jié)省了點(diǎn)時(shí)間。

四. 匿名內(nèi)部類(lèi)

1. 概念

匿名內(nèi)部類(lèi)就是指沒(méi)有類(lèi)名的內(nèi)部類(lèi),必須在創(chuàng)建時(shí)使用 new 語(yǔ)句來(lái)聲明。匿名內(nèi)部類(lèi)不能在Outer Class外部類(lèi)中定義,而是要在某個(gè)方法的內(nèi)部,通過(guò)匿名類(lèi)(Anonymous Class)的形式來(lái)定義。 匿名內(nèi)部類(lèi)本身就是一個(gè)對(duì)象。

通常情況下,如果一個(gè)方法的參數(shù)是接口類(lèi)型,且該接口只需要實(shí)現(xiàn)一次,那么我們就可以通過(guò)匿名內(nèi)部類(lèi)的形式來(lái)進(jìn)行定義。另外如果該接口的實(shí)現(xiàn)每次都不同,也可以使用匿名內(nèi)部類(lèi)的形式進(jìn)行定義。我們也可以把這種定義形式叫做 “接口回調(diào)” 。匿名內(nèi)部類(lèi)的代碼格式使得代碼更加簡(jiǎn)潔、緊湊,模塊化程度也更高。

2. 特點(diǎn)

匿名內(nèi)部類(lèi)具有如下特點(diǎn):

  • 匿名內(nèi)部類(lèi)本身就是一個(gè)對(duì)象;
  • 一般在匿名內(nèi)部類(lèi)中不會(huì)定義屬性和方法,因?yàn)闆](méi)有意義;
  • 匿名內(nèi)部類(lèi)的父類(lèi)一般都是抽象類(lèi)或者是接口;
  • 匿名內(nèi)部類(lèi)和局部?jī)?nèi)部類(lèi)一樣,可以訪問(wèn)外部類(lèi)的所有成員;
  • 如果匿名內(nèi)部類(lèi)位于方法中,則該類(lèi)只能訪問(wèn)方法中 final 類(lèi)型的局部變量和參數(shù);
  • 匿名內(nèi)部類(lèi)中允許使用非靜態(tài)代碼塊對(duì)成員進(jìn)行初始化操作;
  • 匿名內(nèi)部類(lèi)的非靜態(tài)代碼塊會(huì)在父類(lèi)的構(gòu)造方法之后被執(zhí)行。

3. 語(yǔ)法

通常匿名內(nèi)部類(lèi)有兩種實(shí)現(xiàn)方式:

  • 繼承一個(gè)類(lèi),重寫(xiě)其方法;
  • 實(shí)現(xiàn)一個(gè)或多個(gè)接口,并實(shí)現(xiàn)其方法。

創(chuàng)建匿名內(nèi)部類(lèi)對(duì)象的基本語(yǔ)法格式如下:

new <類(lèi)或接口> (){
重寫(xiě)類(lèi)或接口的方法
}

4. 案例

為了給大家演示匿名內(nèi)部類(lèi)的用法,接下來(lái)壹哥設(shè)計(jì)一個(gè)用于模擬按鈕點(diǎn)擊事件的案例。當(dāng)我們進(jìn)行安卓等設(shè)備開(kāi)發(fā)時(shí),面板上有個(gè)按鈕,點(diǎn)擊該按鈕,如何監(jiān)聽(tīng)點(diǎn)擊事件?在Android系統(tǒng)中提供了各種對(duì)應(yīng)的按鈕點(diǎn)擊監(jiān)聽(tīng)事件。所以這里壹哥就通過(guò)實(shí)現(xiàn)接口的形式來(lái)定義匿名內(nèi)部類(lèi),模擬一個(gè)單擊事件。

4.1 定義接口

首先我們需要定義一個(gè)接口,表示單擊監(jiān)聽(tīng),內(nèi)部有個(gè)點(diǎn)擊事件。

/**
 * 點(diǎn)擊監(jiān)聽(tīng)事件
 */
public interface OnClickListener {

	//點(diǎn)擊事件
	void onClick();
	
}

4.2 定義Button按鈕類(lèi)

然后定義一個(gè)Button按鈕類(lèi),給Button按鈕安排一個(gè)點(diǎn)擊監(jiān)聽(tīng)方法。

/**
 * 
 * 局部?jī)?nèi)部類(lèi)---定義在方法中的內(nèi)部類(lèi)
 */
public class Button {

	//處理案例點(diǎn)擊的監(jiān)聽(tīng)事件
    public void setOnClickListener(OnClickListener listener) {
    	
    	listener.onClick();
    }
    
}

4.3 定義測(cè)試類(lèi)

接下來(lái)我們就測(cè)試運(yùn)行上面的代碼。

/**
 * 匿名內(nèi)部類(lèi)測(cè)試
 */
public class AnonyInnerClassTest {

	public static void main(String[] args) {
		//外部變量
		int num=20;
		
		//測(cè)試匿名內(nèi)部類(lèi)
		Button btn=new Button();
		
		//模擬處理按鈕的點(diǎn)擊事件
		btn.setOnClickListener(new OnClickListener() {//這里就是一個(gè)匿名內(nèi)部類(lèi)
			
			//在匿名內(nèi)部類(lèi)中,可以允許使用非靜態(tài)代碼塊進(jìn)行成員初始化操作。
			int i; 
			
			{    // 非靜態(tài)代碼塊,在構(gòu)造方法之后執(zhí)行
		        i = 100;    //成員初始化
		    }
			
			@Override
			public void onClick() {
				System.out.println("按鈕被點(diǎn)擊啦...i="+i+",num="+num);
			}
		});
		
	}
}

根據(jù)上面的案例可知:

  • 在匿名內(nèi)部類(lèi)中,可以允許使用非靜態(tài)代碼塊進(jìn)行成員初始化操作;
  • 匿名內(nèi)部類(lèi)的非靜態(tài)代碼塊,會(huì)在構(gòu)造方法之后執(zhí)行;
  • 匿名內(nèi)部類(lèi)也可以直接使用外部類(lèi)的成員。

五. 靜態(tài)內(nèi)部類(lèi)

1. 概念

靜態(tài)內(nèi)部類(lèi)和成員內(nèi)部類(lèi)的定義類(lèi)似,但要使用static修飾,所以稱(chēng)為靜態(tài)內(nèi)部類(lèi)(Static Nested Class)。

靜態(tài)內(nèi)部類(lèi)和成員內(nèi)部類(lèi)有很大的不同,它不再依附于Outer的實(shí)例,而是一個(gè)完全獨(dú)立的類(lèi),因此無(wú)法引用Outer.this的方式調(diào)用。但它可以訪問(wèn)Outer類(lèi)的private靜態(tài)字段和靜態(tài)方法,如果我們把靜態(tài)內(nèi)部類(lèi)移到Outer類(lèi)之外,就失去了訪問(wèn)private的權(quán)限。

2. 特點(diǎn)

靜態(tài)內(nèi)部類(lèi)中可以定義非靜態(tài)的屬性和方法,也可以定義靜態(tài)的屬性和方法;

靜態(tài)內(nèi)部類(lèi)中只能訪問(wèn)靜態(tài)外部類(lèi)的靜態(tài)屬性和方法。

3. 語(yǔ)法

創(chuàng)建靜態(tài)內(nèi)部類(lèi)對(duì)象的基本語(yǔ)法格式如下:

內(nèi)部類(lèi) 對(duì)象名 = new 外部類(lèi).內(nèi)部類(lèi)();

4. 案例

4.1 定義靜態(tài)內(nèi)部類(lèi)

這里我們先簡(jiǎn)單定義一個(gè)靜態(tài)內(nèi)部類(lèi),后面我們?cè)趯W(xué)習(xí)內(nèi)部類(lèi)時(shí)再專(zhuān)門(mén)講解。在這個(gè)靜態(tài)內(nèi)部類(lèi)中,定義了一個(gè)方法,來(lái)訪問(wèn)外部類(lèi)中的普通屬性和靜態(tài)屬性。我們要記住以下幾點(diǎn):

  • 靜態(tài)內(nèi)部類(lèi)訪問(wèn)外部類(lèi)的成員變量時(shí),需要先創(chuàng)建外部類(lèi)對(duì)象;
  • 非靜態(tài)內(nèi)部類(lèi)可以直接訪問(wèn)使用外部類(lèi)的成員變量,如同使用本類(lèi)中的變量;
  • 所有的內(nèi)部類(lèi)訪問(wèn)外部類(lèi)的靜態(tài)變量時(shí),可以直接通過(guò)"外部類(lèi).靜態(tài)變量"的形式訪問(wèn)。
/**
 * 外部類(lèi)和內(nèi)部類(lèi)
 */
public class OuterClass {
	
	//普通屬性,屬于外部類(lèi)
	static int outerNum=10;
	
	//定義一個(gè)靜態(tài)的內(nèi)部類(lèi),如果不帶static,就是一個(gè)普通的內(nèi)部類(lèi)。
	//內(nèi)部類(lèi)的使用,和普通類(lèi)一樣,里面可以正常定義屬性、方法、構(gòu)造方法等。
    //static前面可以帶public等任意訪問(wèn)修飾符,也可以不帶!
	static class InnerClass{
		//私有屬性無(wú)法在類(lèi)的外部直接訪問(wèn)
		//private int innerNum=20;
		
		int innerNum=20;
		
		public void printNum() {
			//定義外部類(lèi)對(duì)象
			OuterClass outer=new OuterClass();

            //這里的this是指InnerClass內(nèi)部類(lèi)對(duì)象!
			System.out.println("innerNum="+this.innerNum+",outerAge="+outer.outerAge+",outerNum="+OuterClass.outerNum);
		}
	}

}

對(duì)于靜態(tài)內(nèi)部類(lèi)而言,static前面可以帶public等任意訪問(wèn)修飾符,也可以不帶!

4.2 定義測(cè)試類(lèi)

我們?cè)俣x一個(gè)測(cè)試類(lèi),看看內(nèi)部類(lèi)對(duì)象是怎么調(diào)用的。

/**
 * 測(cè)試訪問(wèn)內(nèi)部類(lèi)
 */
public class InnerClassTest {
	
	public static void main(String[] args) {
		//創(chuàng)建內(nèi)部類(lèi)對(duì)象,格式為“外部類(lèi).內(nèi)部類(lèi) 對(duì)象名 = new 外部類(lèi).內(nèi)部類(lèi)的構(gòu)造方法”
		OuterClass.InnerClass inner = new OuterClass.InnerClass();
		
		//調(diào)用內(nèi)部類(lèi)的方法
		inner.printNum();
		
		//訪問(wèn)外部類(lèi)屬性
	    System.out.println("outerNum="+OuterClass.outerNum);
	    
	    //訪問(wèn)內(nèi)部類(lèi)屬性
	    System.out.println("innerNum="+inner.innerNum);
	}

}

5. 訪問(wèn)方式小結(jié)

對(duì)于靜態(tài)內(nèi)部類(lèi)的訪問(wèn)要求,給大家總結(jié)如下:

  • 靜態(tài)內(nèi)部類(lèi)中可以直接訪問(wèn)外部類(lèi)的所有靜態(tài)方法,包含私有的,但不能直接訪問(wèn)非靜態(tài)成員;
  • 靜態(tài)內(nèi)部類(lèi)可以添加任意訪問(wèn)修飾符(public、protected、默認(rèn)、private),因?yàn)樗牡匚痪褪且粋€(gè)成員;
  • 如果靜態(tài)內(nèi)部類(lèi) 訪問(wèn) 外部類(lèi) 的靜態(tài)屬性、靜態(tài)方法等,訪問(wèn)方式是【直接訪問(wèn)】;
  • 如果外部類(lèi)或外部的其他類(lèi)來(lái) 訪問(wèn) 靜態(tài)內(nèi)部類(lèi),訪問(wèn)方式是【外部類(lèi).內(nèi)部類(lèi) 對(duì)象名 = new 外部類(lèi).內(nèi)部類(lèi)的構(gòu)造方法】,創(chuàng)建出內(nèi)部類(lèi)對(duì)象后再訪問(wèn)。

六. 結(jié)語(yǔ)

至此我們就把內(nèi)部類(lèi)給大家詳細(xì)地介紹了,現(xiàn)在你學(xué)會(huì)了嗎?我們來(lái)總結(jié)一下內(nèi)部類(lèi)的重點(diǎn)內(nèi)容吧:

  • 內(nèi)部類(lèi)分為成員內(nèi)部類(lèi)、局部?jī)?nèi)部類(lèi)、匿名內(nèi)部類(lèi)和靜態(tài)內(nèi)部類(lèi);
  • 成員內(nèi)部類(lèi)和匿名內(nèi)部類(lèi)在本質(zhì)上是相同的,都必須依附于外部類(lèi)的實(shí)例,會(huì)隱含地持有Outer.this實(shí)例,并擁有外部類(lèi)的private訪問(wèn)權(quán)限;
  • 靜態(tài)內(nèi)部類(lèi)是獨(dú)立類(lèi),但擁有外部類(lèi)的private訪問(wèn)權(quán)限;
  • 如果外部類(lèi)和內(nèi)部類(lèi)中的成員重名時(shí),內(nèi)部類(lèi)訪問(wèn)時(shí)默認(rèn)會(huì)遵循就近原則;如果想訪問(wèn)外部類(lèi)的成員,則可以用【外部類(lèi)名.成員】的形式來(lái)訪問(wèn)。

到此這篇關(guān)于Java內(nèi)部類(lèi)的使用教程詳解的文章就介紹到這了,更多相關(guān)Java內(nèi)部類(lèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

阿鲁科尔沁旗| 剑阁县| 台前县| 红原县| 平塘县| 彭山县| 英德市| 子长县| 高尔夫| 海晏县| 陵川县| 蕉岭县| 军事| 勐海县| 台南市| 洪湖市| 康保县| 育儿| 平果县| 海安县| 宝丰县| 长岭县| 巍山| 长乐市| 韩城市| 大悟县| 谢通门县| 平安县| 贵州省| 邯郸县| 盐山县| 梨树县| 交口县| 伊吾县| 安宁市| 正宁县| 阿图什市| 美姑县| 宝山区| 华蓥市| 西城区|