內部類簡介(包括在Swing中的例項應用)
各種介紹語法的程式書上經常出現內部類InnerClass,儘管語法上並不複雜,但如果沒有實際例子供參考的話,在概念上比較難以理解,也難以體會到內部類的精妙之處。
希望這篇博文能幫助你更好地理解內部類 ^_^
一個非常常見的例子:你要在JavaSwing里加一個按鈕,點選按鈕觸發事件。
你知道要觸發按鈕的事件ActionEvent,就得實現ActionListener介面。通過addActionListener(this)來監聽。在事件發生時呼叫ActionListener接口裡的actionPerformed方法。
示意程式碼:(在頁面上加一個按鈕,點選按鈕顯示Hello)
上面這段程式碼可以達到目的,但顯然不會有人這樣去做。因為如果頁面上需要多個按鈕呢?你無法為接口裡的actionPerformed方法提供多個實現。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"); } }
比如,頁面上有兩個按鈕,點選一個按鈕顯示hello,點選另一個按鈕顯示world:
或許你會這樣來實現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???你無法為一個方法提供多個實現 } }
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(" ", )對指定目錄中所有內容的列出(包括子目錄中的內容) 也可以理解為:深度遍歷 注意:如果使用的是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、分類 (一)成員內部類 特點:
hadoop中slot簡介(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.點選 控制面板->時鐘、語言和
linux中fork()函式詳解(原創!!例項講解)
所以打印出結果: 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