1. 程式人生 > >內部類簡介(包括在Swing中的例項應用)

內部類簡介(包括在Swing中的例項應用)

各種介紹語法的程式書上經常出現內部類InnerClass,儘管語法上並不複雜,但如果沒有實際例子供參考的話,在概念上比較難以理解,也難以體會到內部類的精妙之處。

希望這篇博文能幫助你更好地理解內部類 ^_^

一個非常常見的例子:你要在JavaSwing里加一個按鈕,點選按鈕觸發事件。

你知道要觸發按鈕的事件ActionEvent,就得實現ActionListener介面。通過addActionListener(this)來監聽。在事件發生時呼叫ActionListener接口裡的actionPerformed方法。

示意程式碼:(在頁面上加一個按鈕,點選按鈕顯示Hello)

import javax.swing.*;
import java.awt.event.*;

public class SimpleGui implements ActionListener {	//需要ActionListener介面
	JButton button;
	public static void main (String[] args) {
		SimpleGui gui = new SimpleGui();
		gui.go();
	}

	public void go() {
		... 
		button = new JButton("Click me");	//new一個Swing的按鈕
		button.addActionListener(this);		//按鈕繫結事件
		... 
	}

	//實現ActionListener介面內的actionPerformed方法,點選按鈕會顯示Hello
	public void actionPerformed(ActionEvent event) {
		button.setText("Hello");
	}
}
上面這段程式碼可以達到目的,但顯然不會有人這樣去做。因為如果頁面上需要多個按鈕呢?你無法為接口裡的actionPerformed方法提供多個實現。

比如,頁面上有兩個按鈕,點選一個按鈕顯示hello,點選另一個按鈕顯示world:

public class SimpleGui implements ActionListener {
	JButton button1;    //兩個按鈕
	JButton button2;
	...
        public static void main (String[] args) {
		SimpleGui gui = new SimpleGui();
		gui.go();
	}

	public void go() {
		... 
		button1 = new JButton("Click me");  //new一個Swing的按鈕
		button.addActionListener(this);
		button2 = new JButton("Click me2"); //再new一個Swing的按鈕
		button2.addActionListener(this);
		... 
	}
	
	public void actionPerformed(ActionEvent event) {
		//how???你無法為一個方法提供多個實現
	}
}
或許你會這樣來實現actionPerformed方法,以達到點選一個按鈕顯示hello,點選另一個按鈕顯示world的目的:
public void actionPerformed(ActionEvent event) {
	if (event.getSource() == button1) {
		button1.setText("Hello");
	} else if (event.getSource() == button2) {
		button2.setText("world");
	}
}
但這樣看起來太面向過程了,顯得很屌絲,與你高富帥的氣質形象極度不符。你真正需要的是內部類。

顧名思義,定義在一個類內部的類,就是內部類。它外層的類就是外部類。

內部類可以使用外部類的所有方法和變數,就算是外部類的private方法和變數也可以用。但內部類的方法和成員不能被外部類直接使用(即使內部類的public成員也無法被外部類直接訪問),只能通過內部類物件來訪問:

class MyOuterClass {
	private int x;

	class MyInnerClass {		//定義在一個類內部的類,稱為內部類
		void go() { x = 42; }	//沒問題,外部類的private變數也能被內部類訪問
	}
}
定義完內部類,這樣來建立內部類物件:
class MyOuter {
	private int x;
	MyInner inner = new MyInner();	//建立內部類例項,內部類例項一定會綁在外部類例項上

	public void doStuff() { 
		//go();			//Error編譯出錯,外部類無法直接訪問內部類內部的成員,哪怕是public也不行
		inner.go();		//通過內部類物件才能呼叫內部類裡的方法
	}

	class MyInner {			//內部類定義處
		void go() { x = 42; }
	}
}
還有種建立內部類物件的方法,不太常見,但你可以瞭解下:
MyOuter outerObj = new MyOuter();
MyOuter.MyInner innerObj = outerObj.new MyInner();
原理是一樣的,內部類的物件一定會綁在外部類物件上。建立外部類物件,用該外部類物件建立內部類物件。

例子程式碼改成:

public class SimpleGui {
	JButton button1;
	JButton button2;
	...
	public static void main (String[] args) {
		SimpleGui gui = new SimpleGui();
		gui.go();
	}

	public void go() {
		...
		JButton button1 = new JButton("Click me");
		button1.addActionListener(new buttonListener1());
		JButton button2 = new JButton("Click me2");
		button2.addActionListener(new buttonListener2());
		...
	}

	class buttonListener1 implements ActionListener {		//內部類1
		public void actionPerformed(ActionEvent event) {
			button1.setText("Hello");
		}
	}

	class buttonListener2 implements ActionListener {		//內部類2
		public void actionPerformed(ActionEvent event) {
			button2.setText("world");
		}
	}
}

上面都是自解釋程式碼,應該能幫助你理解內部類的精妙:內部類提供了在同一個類中對同一個方法,提供多種實現

PS:

上面這樣將內部類作為外部類的成員來定義(即定義內部類和外部類自身的成員變數和 方法處以同一級別),被稱為成員內部類。

除此之外還有區域性內部類,匿名內部類,靜態內部類。

區域性內部類:定義在類的方法或任意作用域中

interface OutInterface { ... }

class OuterClass {
	public OutInterface doit() {
		class InnerClass implements OutInterface {	//顧名思義,定義在外部類方法或任意作用域中的就是區域性內部類
			...
		}
		return new InnerClass();
	}

	public static void main(String args[]) {
		OuterClass out = new OuterClass();
		out.doit();	
	}
}

該區域性內部類是doit方法的一部分,非OuterClass的一部分,因此doit方法外部無法訪問該內部類。但內部類可以訪問外部類成員(private成員)這一特性仍舊不變。

匿名內部類:沒有類名的內部類

interface OutInterface { … }

class OuterClass {
	public OutInterface doit(){
		return new OutInterface(){	//顧名思義,無類名的稱為匿名內部類(因為無類名,所以只能用預設建構函式)
			...
		};
	}

	public static void main(String args[]) {
		OuterClass out = new OuterClass();
		out.doit();	
	}
}
靜態內部類:內部類前加上static就是靜態內部類。

靜態內部類中可以宣告static成員,而非靜態內部類中不可宣告static成員。且靜態內部類不可以使用外部類的非靜態成員。且不需要外部物件來建立靜態內部類物件:

public class OuterClass {
	int x=0;
	static class Inner{		//靜態內部類
		void doitInner(){
			//x = 5;	//編譯Error,不能在靜態內部類中訪問外部類的非靜態成員
		}
		public static void main(String args[]){ … }   //可將外部類main函式,寫入靜態內部類
	}
}
上面這樣將外部類的static main函式,放入靜態內部類後,編譯將生成OuterClass.class和OuterClass$Inner.class。

執行java OuterClass$Inner就可以執行程式。這樣當完成測試後,需要將.class檔案打包時,只要刪除OuterClass$Inner.class即可。

總結

無論什麼內部類(成員,區域性,匿名,靜態)本質上仍舊是個類,具有普通類的一切特性。

但畢竟是定義在一個普通類的內部,生成訪問許可權受到一定限制(如只能通過外部類物件訪問內部類),不能在程式中直接new一個內部類物件。內部類能訪問外部類的一切成員(靜態內部類有一定限制),但外部類無法直接訪問內部類的成員,只能通過內部類物件來訪問。

如果上面的說法比較難記,可以將外部類想象成丈夫,內部類想象成妻子。對妻子來說,你(丈夫)的就是我的,但我的仍舊是我的。外人無法直接拜訪妻子,必須通過丈夫引見才能拜訪到妻子。

內部類最強大之處在於:能在同一個類中對同一個方法,提供多種實現

相關推薦

部類簡介包括Swing例項應用

各種介紹語法的程式書上經常出現內部類InnerClass,儘管語法上並不複雜,但如果沒有實際例子供參考的話,在概念上比較難以理解,也難以體會到內部類的精妙之處。 希望這篇博文能幫助你更好地理解內部類 ^_^ 一個非常常見的例子:你要在JavaSwing里加一個按鈕,點選按

Java File列出指定目錄的所有檔案包括子目錄的檔案

需求: replace(" ",&nbsp)對指定目錄中所有內容的列出(包括子目錄中的內容) 也可以理解為:深度遍歷 注意:如果使用的是listFiles(pathname)方法列出檔案和目錄,則不能之間整個磁碟的內容,而是列出某個檔案中的內容。 程式碼: import

Alias 例項: 使用表名稱別名在SQL應用

Alias 可以為列名稱和表名稱指定別名 表的SQL  alias語法 Select column_name(s) from table_name AS alias_name 列的SQL alias 語法 Select  column_name AS alias_na

Python計算一個目錄下所有檔案包括子目錄所有檔案指定的檔案型別個數

 輸入工程名計算一個工程專案中C++,Java,Python,GO語言的檔案個數,並找出Python檔案中最大檔案的檔名 1、先讀取檔案地址,找到該資料夾 import os import os.path path = 'C:/python學習/Python作業/' +

java程式 一次改變指定目錄下所有檔案編碼包括子目錄的檔案

package transCoding; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInpu

獲取碼值各種類型字符、英的ASCII和進制轉換系統包括正負數、小數

獲取碼值 進制轉換 十進制小數負數轉二進制 java進制轉換 ASCII 獲取碼值和進制轉換程序由來: 本人發現計算機中的計算器木有將十進制小數轉二進制的功能,後來發現一些網站將十進制負數轉二進制只是求出整數的二進制,然後前面加“-”,這種表示不是真正的負數二進制。於是愛較真兒

java部類實現可能導致記憶體洩漏

在使用java內部類的時候要注意可能引起的記憶體洩漏 程式碼如下 package com.example; public class MyClass { public static void main(String[] args) throws Throwab

Python遞迴求出列表包括列表的子列表的最大值

          Python遞迴求出列表(包括列表中的子列表)中的最大值 要求:求出列表中的所有值的最大數,包括列表中帶有子列表的。 按照Python給出的內建函式(max)只能求出列表中的最大值,無法求出包括列表中的子列表的最大值 Python3程式碼如下: #

PHP基礎到高階開發教程包括Js,Mysql例項

課時1 01-01-PHP語言基礎與技術點( apache 配置網頁伺服器) 課時2 01-02-PHP-apache 配置靜態網頁伺服器與MYSQL軟體安裝 課時3 01-03-PHP-MYSQL軟體安裝(修改環境變數 配置與打包軟體) 課時4 02-0

部類 列舉enum基本屬性和使用詳解

☆☆☆內部類和列舉的使用解析 列舉創建於呼叫 一、內部類 概念: 一個類中又定義了一個完整的類結構。 被包含的類 稱為 內部類 類體中包含其他類的類 稱為 外部類 其他的類 稱為 外部其他類 1、分類 (一)成員內部類 特點:

hadoopslot簡介map slot 和 reduce slot

Slots是Hadoop的一個重要概念。然而在Hadoop相關論文,slots的闡述難以理解。網上關於slots的概念介紹也很少,而對於一個有經驗的Hadoop開發者來說,他們可能腦子裡已經理解了slots的真正含義,但卻難以清楚地表達出來,Hadoop初學者聽了還是雲裡

Java 部類,多執行緒Synchronized與wait,notify的使用

工作內容: 1.成員內部類    與成員方法,屬性的訪問許可權一致 2.靜態內部類    修飾符 stactic 類名{...} 3.匿名內部類    new 類名()/介面名(重寫介面方法) 4.區域性內部類    程式碼塊中 5.執行緒Thread wait,noti

四種部類Inner Class

內部類: 定義在內部的類,不一定非得是定義在類的內部, 可以分為4種類型。 第一: 靜態內部類(定義在類中) 靜態的內部類與其外部類是編譯成 兩個.class檔案 的,注意的是外部類是不可以定義為靜態的。 為什麼外部的類不可以定義為靜態的 解釋

JAVA筆試:一道綜合考察題部類,傳值呼叫,多型

public class Tree { private static String tree = "tree"; String getTree() { return t

開發過程RecyclerView遇到的坑包括巢狀使用時

1.使用recyclerView時,遇到了一個問題,裡面的內容怎麼也顯示不出來,試了一下將recyclerView的高度固定就能顯示了,經過在網上查詢,發現是使用wrap_content屬性不起作用,這個是recyclerView自帶的一個坑。 解決方法:提升一下recyc

解決win10建自帶應用顯示語言為英文包括商店,郵件等

剛剛買了美版電腦,win10系統。按照網上漢化教程,成功漢化,也就是區域,語言,輸入法等能設定成中文的全部設定完成。突然發現自帶的應用全部為英文。然後一直上網搜資料嘗試。最後總結了以下方法,供大家參考,應該都能成功:) 1.點選 控制面板->時鐘、語言和

linuxfork函式詳解原創!!例項講解

    所以打印出結果:    0 parent 2043 3224 3225    0 child  3224 3225    0    第二步:假設父程序p3224先執行,當進入下一個迴圈時,i=1,接著執行fork,系統中又新增一個程序p3226,對於此時的父程序,p2043->p3224(當前程

Oracle資料庫的系統引數包括隱藏和廢棄的

Oracle資料庫系統根據初始化引數檔案init.ora中設定的引數來配置自身的啟動,每個例項在啟動之前,首先讀取這些引數檔案中設定的不同引數。Oracle系統中的引數,根據系統使用情況可以簡單分為兩大類,普通引數,也就是Oracle系統正常使用的一些引數,另外一類就是特殊

LibSVM 在matlab的配置包括SVDD、libsvm-faruto

LibSVM的配置是初學LibSVM者遇到的最麻煩的問題,網上已經有很多關於配置的教程但是質量參差不齊,很多內容已過時,本人綜合網上的教程和自己的實踐,整理出更為實用簡潔的教程。 1. 需要的檔案或程式: MATLAB2010b及以後版本、VS2010及以後版本(其他版本

C#呼叫C++的dll的引數為指標型別的匯出函式包括二級指標的情況

一:首先什麼是IntPtr 先來看看MSDN上說的:用於表示指標或控制代碼的平臺特定型別。這個其實說出了這樣兩個事實,IntPtr 可以用來表示指標或控制代碼、它是一個平臺特定型別。對於它的解釋,這個哥們寫的比較好:It's a class that wraps a