內部類是指在一個外部類的內部再定義一個類。類名不需要和文件夾相同。
*內部類可以是靜態static的,也可用public,default,protected和private修飾。(而外部頂級類即類名和文件名相同的只能使用public和default)。
前言
Java從JDK1.1的時候,就開始引入內部類的概念了,那么小編也通過這篇博客來分享一下Java中有關內部類的一些特性。
什么是內部類?
在很多情況下,類被定義成一個獨立的程序單元,但是有時候也會把一個類放在另一個類的內部定義,這個定義在其他類內部的類就稱為內部類。
從語法上來看的話,定義內部類和定義外部類的語法大致相同,內部類除了需要定義在其他類里面之外,還存在如下兩點區別。
1.內部類比外部類多使用三個修飾符:private——protected、static——外部類不可以使用這三個修飾符。
2.非靜態內部類不能擁有靜態成員。
除了以上兩點之外,其他的地方都與普通的類相同,下面來列舉一下常見的內部類操作。
非靜態內部類
定義內部類也非常簡單,只要把一個類放在另一個類內部定義即可,甚至都可以放置在方法的內部。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
<span style= "font-family:Comic Sans MS;font-size:18px;" > package com.test; public class Cow { private double weight; // 外部類的兩個重載的構造器 public Cow(){} public Cow( double weight) { this .weight = weight; } // 定義一個非靜態內部類 private class CowLeg { // 非靜態內部類的兩個實例變量 private double length; private String color; // 非靜態內部類的兩個重載的構造器 public CowLeg(){} public CowLeg( double length , String color) { this .length = length; this .color = color; } // 下面省略length、color的setter和getter方法 public void setLength( double length) { this .length = length; } public double getLength() { return this .length; } public void setColor(String color) { this .color = color; } public String getColor() { return this .color; } // 非靜態內部類的實例方法 public void info() { System.out.println( "當前牛腿顏色是:" + color + ", 高:" + length); // 直接訪問外部類的private修飾的成員變量 System.out.println( "本牛腿所在奶牛重:" + weight); //① } } public void test() { CowLeg cl = new CowLeg( 1.12 , "黑白相間" ); cl.info(); } public static void main(String[] args) { Cow cow = new Cow( 378.9 ); cow.test(); } } </span> |
在上述中非靜態內部類的成員可以訪問外部類的private成員,但反過來就不成立了。非靜態內部類的成員只在非靜態內部類范圍內是可知的,并不能被外部類直接使用。如果外部類需要訪問非靜態內部類的成員,則必須顯式創建非靜態內部類對象來調用訪問其實例成員。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<span style= "font-family:Comic Sans MS;font-size:18px;" > package com.test; public class Outer { private int outProp = 9 ; class Inner { private int inProp = 5 ; public void acessOuterProp() { // 非靜態內部類可以直接訪問外部類的private成員變量 System.out.println( "外部類的outProp值:" + outProp); } } public void accessInnerProp() { // 外部類不能直接訪問非靜態內部類的實例變量, // 下面代碼出現編譯錯誤 // System.out.println("內部類的inProp值:" + inProp); // 如需訪問內部類的實例變量,必須顯式創建內部類對象 System.out.println( "內部類的inProp值:" + new Inner().inProp); } public static void main(String[] args) { // 執行下面代碼,只創建了外部類對象,還未創建內部類對象 Outer out = new Outer(); //① out.accessInnerProp(); } } </span> |
注意:非靜態內部類中不能有靜態方法、靜態成員變量、靜態初始化塊。
靜態內部類
如果使用static來修飾一個內部類,則這個內部類就屬于外部類本身,而不屬于外部類的某個對象,因此使用static修飾的內部類被稱為類內部類,有的地方也稱為靜態內部類。靜態內部類可以包含靜態成員,也可以包含非靜態成員。根據靜態成員不能訪問非靜態成員的規則,靜態內部類不能訪問外部類的實例成員,只能訪問外部類的類成員。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<span style= "font-family:Comic Sans MS;font-size:18px;" > package com.test; public class StaticInnerClassTest { private int prop1 = 5 ; private static int prop2 = 9 ; static class StaticInnerClass { // 靜態內部類里可以包含靜態成員 private static int age; public void accessOuterProp() { // 下面代碼出現錯誤: // 靜態內部類無法訪問外部類的實例變量 System.out.println(prop1); // 下面代碼正常 System.out.println(prop2); } } } </span> |
匿名內部類
使用匿名內部類可以創建那種只需要一次使用的類,并且創建匿名內部類時會立即創建一個該類的實例,但是也需要注意一下規則
1.匿名內部類不能是抽象類,因為系統在創建匿名內部類時,會立即創建匿名內部類的對象,因此不允許將匿名內部類定義成為抽象類
2.匿名內部類不能定義構造器,由于匿名內部類沒有類名,所以無法定義構造器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<span style= "font-family:Comic Sans MS;font-size:18px;" > package com.test; interface Product { public double getPrice(); public String getName(); } public class AnonymousTest { public void test(Product p) { System.out.println( "購買了一個" + p.getName() + ",花掉了" + p.getPrice()); } public static void main(String[] args) { AnonymousTest ta = new AnonymousTest(); // 調用test()方法時,需要傳入一個Product參數, // 此處傳入其匿名實現類的實例 ta.test( new Product() { public double getPrice() { return 567.8 ; } public String getName() { return "AGP顯卡" ; } }); } } </span> |
下面給大家總結以下內部類的共性編輯
(1)、內部類仍然是一個獨立的類,在編譯之后內部類會被編譯成獨立的.class文件,但是前面冠以外部類的類名和$符號 。
(2)、內部類不能用普通的方式訪問。內部類是外部類的一個成員,因此內部類可以自由地訪問外部類的成員變量,無論是否是private的 。
(3)、內部類聲明成靜態的,就不能隨便的訪問外部類的成員變量了,此時內部類只能訪問外部類的靜態成員變量 。