目錄
- 成員內部類
- 定義
- 成員內部類特點
- 如何使用成員內部類
- 靜態內部類
- 定義
- 靜態內部類的特點
- 如何使用靜態內部類
- 區域內部類
- 定義
- 區域內部類的特點
- 如何使用區域內部類
- 匿名內部類
- 定義
- 前提
- 格式:
- 匿名內部類的特點
- 如何使用匿名內部類
- 定義
成員內部類
定義
- 成員內部類 :定義在外部類中方法外的類
定義格式:
[修飾符] class 外部類名 [extends 外部類的父類] [implements 外部類的父介面們] {
[修飾符] class 內部類名 [extends 非靜態內部類自己的父類] [implements 非靜態內部類的父介面們] {
靜態內部類的成員串列;
}
// 外部類的其他成員串列
}
外部類、內部類的父類、父介面沒有關系,各是各的
成員內部類特點
-
成員內部類仍然是一個獨立的類,在編譯之后內部類會被編譯成獨立的.class檔案,但是前面冠以外部類的類名和$符號,例如:Outer$Inner.class
-
成員內部類可以使用修飾符public,protected,預設,private
-
成員內部類還可以使用final或abstract修飾
-
成員內部類中不可以宣告靜態成員
-
成員內部類可以直接使用外部類的所有成員,包括私有的,如果成員內部類有與外部類的非靜態屬性重名時,可以通過“外部類名.this.屬性”進行區別,如果與外部類的靜態屬性重名時,可以通過“外部類名.類變數”進行區別
-
外部類要訪問內部類的成員,必須要建立內部類的物件,
如何使用成員內部類
-
在外部類中使用成員內部類:
- 在外部類的靜態成員中不能使用非靜態的成員內部類
- 在外部類的非靜態成員中,直接創建內部類的物件來訪問內部類的屬性與方法,此時把它當做一個普通的類即可
-
在外部類的外面使用成員內部類:
-
要么通過外部類的物件,去創建內部類的物件
外部類名 外部物件名 = new 外部型別(); 內部類名 物件名 = 外部物件名.new 外部型別(); //可合并為: 外部類名.內部類名 物件名 = new 外部型別().new 內部型別(); -
要么通過外部類的物件,去獲取內部類的物件
Outer out = new Outer(); Outer.Inner in = out.getInner();
-
代碼演示:
public class MemberClassTest {
public static void main(String[] args) {
Outer out = new Outer();
out.outerMethod();
//通過外部類的物件,去創建內部類的物件
Outer.Inner oi = out.new Inner();
oi.innerMethod();
//通過外部類的物件,去獲取內部類的物件
Outer.Inner obj = out.getInner();
obj.innerMethod();
}
}
class Outer{
private int a = 1;
private static int b = 2;
public static void outerStaticMethod(){
/*Inner in = new Inner();//錯誤,靜態成員中不能使用非靜態成員內部類
in.innerMethod();*/
}
public void outerMethod(){
System.out.println("外部類的方法");
/*Inner in = new Inner();//可以
in.innerMethod();*/
}
class Inner{
private int a = 3;
private int b = 4;
public void innerMethod(){
System.out.println("內部類的方法");
System.out.println("內部類的方法訪問外部類的私有非靜態屬性:"+Outer.this.a);
System.out.println("內部類的方法訪問外部類的私有靜態屬性:"+Outer.b);
}
}
//通過外部類的某個方法回傳內部類的物件
public Inner getInner(){
return new Inner();
}
}
外部類的方法
內部類的方法
內部類的方法訪問外部類的私有非靜態屬性:1
內部類的方法訪問外部類的私有靜態屬性:2
內部類的方法
內部類的方法訪問外部類的私有非靜態屬性:1
內部類的方法訪問外部類的私有靜態屬性:2
靜態內部類
定義
靜態內部類:定義在外部類中方法外,使用 static 修飾的類
定義格式:
[修飾符] class 外部類名 [extends 外部類的父類] [implements 外部類的父介面們] {
[修飾符] static class 內部類名 [extends 靜態內部類自己的父類] [implements 靜態內部類的父介面們] {
靜態內部類的成員串列;
}
// 外部類的其他成員串列
}
靜態內部類的特點
-
靜態內部類仍然是一個獨立的類,在編譯之后內部類會被編譯成獨立的.class檔案,但是前面冠以外部類的類名和$符號,例如:Outer$Inner.class
-
靜態內部類可以使用修飾符public,protected,default,private
-
靜態內部類還可以使用final或abstract修飾
-
靜態內部類中可以宣告靜態成員
-
靜態內部類可以直接使用外部類的靜態成員,包括私有的,但不能使用外部類的非靜態成員,
-
靜態內部類中有與外部類的靜態屬性重名時,如果要使用外部類的屬性,那么用“外部類名.屬性”
如何使用靜態內部類
-
在外部類中使用靜態內部類:就和使用其他普通類一樣
-
在外部類的外面使用成員內部類:
- 使用靜態內部類的靜態成員:外部類名.靜態內部類名.靜態內部類的靜態成員
- 使用靜態內部類的非靜態成員:外部類名.靜態內部類名 obj = new 外部類名.靜態內部類名(); obj.靜態內部類的非靜態成員
代碼演示:
public class StaticInnerClassTest {
public static void main(String[] args) {
Outer.StaticInnerClass.innerStaticMethod();
Outer.StaticInnerClass os = new Outer.StaticInnerClass();
os.innerMethod();
}
}
class Outer{
public static void outerStaticMethod(){
StaticInnerClass.innerStaticMethod();
StaticInnerClass si = new StaticInnerClass();
si.innerMethod();
}
public static void outerMethod(){
StaticInnerClass.innerStaticMethod();
StaticInnerClass si = new StaticInnerClass();
si.innerMethod();
}
static class StaticInnerClass{
public static void innerStaticMethod(){
System.out.println("內部類的靜態方法");
}
public void innerMethod(){
System.out.println("內部類的非靜態方法");
}
}
}
區域內部類
定義
- 區域內部類:定義在方法內、代碼塊內、構造器內
定義格式:
[修飾符] class 外部類名 [extends 外部類的父類] [implements 外部類的父介面們] {
[修飾符] 回傳值型別 方法名([形參串列]){
[修飾符] class 內部類名 [extends 區域內部類自己的父類] [implements 區域內部類的父介面們] {
區域內部類的成員串列;
}
}
// 外部類的其他成員串列
}
區域內部類的特點
-
區域內部類仍然是一個獨立的類,在編譯之后內部類會被編譯成獨立的.class檔案:“外部類的類名$數字編號內部類名.class”,
-
區域內部類和區域變數地位類似,不能使用 public,protected,private,static 這些成員修飾符,但是可以使用abstract或final
-
區域內部類不能使用static修飾,因此也不能包含靜態成員,
-
只能在宣告它的方法或代碼塊中使用,而且是先宣告后使用,除此之外的任何地方都不能使用該類,因為作用域的問題,
-
區域內部類可以使用外部類的成員,包括私有的,但是是否可以使用外部類的非靜態成員要看所在方法是否是非靜態的,
-
區域內部類可以使用包含它的外部方法中的區域變數
如何使用區域內部類
只能在宣告它的方法或代碼塊中使用,而且是先宣告后使用,除此之外的任何地方都不能使用該類,
但是它的物件可以通過包含此區域內部類的外部方法的回傳值回傳使用,回傳值型別只能是區域內部類的父類或父介面型別,
代碼演示:
public class LocalInnerClassTest {
public static void main(String[] args) {
Outer out = new Outer();
Object obj = out.outerMethod();
System.out.println(obj);
System.out.println();
}
}
class Outer{
int value = https://www.cnblogs.com/sun10367/p/5;
public Object outerMethod(){
final int localValue = 10;
class LocalInnerClass {
public void innerMethod(){
System.out.println("區域內部類的方法");
System.out.println("區域內部類的方法可以使用外部類的成員變數:"+value);
System.out.println("區域內部類的方法可以使用外部類的區域變數:"+localValue);
}
}
//先宣告后使用
LocalInnerClass li = new LocalInnerClass();
li.innerMethod();
return li;
}
}
區域內部類的方法
區域內部類的方法可以使用外部類的成員變數:5
區域內部類的方法可以使用外部類的區域變數:10
demo3.Outer$1LocalInnerClass@6b2fad11
匿名內部類
定義
- 匿名內部類 :本質是一個
帶具體實作的父類或者父介面的匿名的子類物件,
如果介面的實作類(或者是父類的子類)只需要使用唯一的一次,那么這種情況下就可以省略該類的定義,而改為使用【匿名內部類】,
特征:宣告匿名內部類的同時創建該類的物件
前提
存在一個類或者介面,這里的類可以是抽象類也可以是普通類,
格式:
繼承父類:
new 父類名稱([實參串列]){
// 類的成員串列
};
說明:如果子類呼叫的是父類的無參構造,那么()中實參串列不用寫,如果子類呼叫的是父類的有參構造,那么就在()中傳入實際引數
實作介面:
new 介面名稱(){
// 類的成員串列
};
介面不是不能實體化創建物件嗎,new關鍵字的后面為什么跟著介面名?
對格式“new 介面名稱() {...}”進行決議:
- new代表創建物件的動作
- 介面名稱表示匿名內部類需要實作哪個介面
- {...}是匿名內部類的內容
匿名內部類的特點
-
匿名內部類仍然是一個獨立的類,在編譯之后內部類會被編譯成獨立的.class檔案::外部類名$數字編號.class
-
匿名內部類必須繼承父類或實作介面
-
匿名內部類只能有一個物件
-
匿名內部類物件只能使用多型形式參考
-
匿名內部類是特殊的區域內部類,區域內部類的所有限制對它都適用
如何使用匿名內部類
以介面舉例,當你使用一個介面時,似乎得做如下幾步操作:
- 定義介面實作類
- 重寫介面中的方法
- 創建子類物件
- 呼叫重寫后的方法
我們的目的,最終只是為了呼叫方法,那么能不能簡化一下,把以上四步合成一步呢?
案例需求:
定義筆記本電腦類,電腦有USB介面,通過插入滑鼠、鍵盤等不同設備,實作各自不同功能,
傳統方式:
定義介面:
public interface USB {
// 使用USB設備的方法
public void use();
}
定義筆記本類,定義滑鼠類、鍵盤類分別實作USB介面:
class Mouse implements USB {
@Override
public void use() {
System.out.println("點擊滑鼠操控電腦...");
}
}
class KeyBoard implements USB {
@Override
public void use() {
System.out.println("鍵盤輸入資料...");
}
}
public class NoteBook {
// USB設備插入筆記本電腦的方法,要求傳遞的物件要實作USB介面
public void plugIn(USB usb) {
usb.use();
}
}
測驗類:
public class AnonymousClassTest {
public static void main(String[] args) {
NoteBook noteBook = new NoteBook();
USB mouse = new Mouse();
noteBook.plugIn(mouse);
USB keyBoard = new KeyBoard();
noteBook.plugIn(keyBoard);
}
}
匿名內部類方式:
定義介面:
public interface USB {
public void use();
}
定義筆記本電腦類:
public class NoteBook {
// 要求傳遞的物件要實作USB介面
public void plugIn(USB usb) {
usb.use();
}
}
測驗類:
public class AnonymousClassTest {
public static void main(String[] args) {
NoteBook noteBook = new NoteBook();
// 下面這段代碼,宣告了實作USB介面的匿名內部類,也創建了它的物件
// 但是這個物件既沒有賦值給一個變數,也沒有直接呼叫方法,無法直接使用
new USB() {
@Override
public void use() {
System.out.println("實作了USB介面");
}
};
// 使用方式一:
// 把創建的物件賦值給一個變數,然后呼叫重寫的use方法
// 多型參考
USB mouse = new USB() {
@Override
public void use() {
System.out.println("點擊滑鼠操控電腦...");
}
};
mouse.use();
// 使用方式二:
// 用創建的物件直接呼叫重寫的use方法
new USB() {
@Override
public void use() {
System.out.println("鍵盤輸入資料...");
}
}.use();
// 使用方式三:
// 把創建的物件作為方法實參
noteBook.plugIn(new USB() {
@Override
public void use() {
System.out.println("U盤傳輸資料...");
}
});
}
}
測驗結果:
點擊滑鼠操控電腦...
鍵盤輸入資料...
U盤傳輸資料...
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/55054.html
標籤:Java
上一篇:C語言
