一、什麼是內部類?
一個類的定義放在另一個類的內部,這個類就叫做內部類
二、內部類有那些特性?
1、內部類仍然是一個獨立的類,在編譯之後內部類會被編譯成獨立的.class文件,但是前面冠以外部類的類名和$符號 。
2、內部類不能用普通的方式訪問。內部類是外部類的一個成員,因此內部類可以自由地訪問外部類的成員變量,無論是否是private的 。
3、內部類聲明成靜態的,就不能隨便的訪問外部類的成員變量了,此時內部類只能訪問外部類的靜態成員變量 。
三、內部類有哪幾種?
1.成員內部類
如: 1 package com.test01;
2
3 public class A {
4 // 內部類 B 繼承 TestPojo 和實現 TestInterface 接口
5 class B extends TestPojo implements TestInterface{
6 //內部類 B 自己的方法
7 public void run(){
8 System.out.println("我正在跑!");
9 }
10 //重寫的接口方法
11 public void testf() {
12 System.out.println("實現接口!");
13 }
14 }
15 // 方法裡面調用內部類
16 public void test(){
17 B b = new B() ;
18 b.testf() ; // 掉用重寫接口方法
19 b.run() ; // 調用自己的方法
20 b.testpojo() ; // 調用繼承父類的方法
21 }
22 // main 方法測試
23 public static void main(String[] args) {
24 A a = new A() ;
25 a.test() ;
26 }
27 }
28 // 定義了一個接口 ,方法為testf()
29 interface TestInterface{
30 public void testf() ;
31 }
32 // 定義了一個普通類 方法testpojo()
33 class TestPojo{
34 public void testpojo(){
35 System.out.println("我是簡單的pojo類");
36 }
37 }
38 // 實現 調用內部類裡面的方法
39 class Textone{
40 public static void main(String[] args) {
41 A.B b = new A().new B() ; //調用類A裡面的內部類B
42 /** 等同於 下面代碼
43 * A a = new A() ;
44 * A.B b = a.new B() ;
45 * */
46 b.testf() ; // 掉用重寫接口方法
47 b.run() ; // 調用自己的方法
48 b.testpojo() ; // 調用繼承父類的方法
49 }
50 }
2、方法內部類
1 package com.test01;
2
3 public class PerTest {
4 public void test(){ // 定義一個方法
5 class Ne{ // 定義一個方法內部類
6 public void fle(){ // 定義方法內部類的方法
7 System.out.println("我正在飛翔!");
8 }
9 } ;
10 new Ne().fle() ; //調用內部類的方法
11 }
12 public static void main(String[] args) {
13 new PerTest().test() ; //測試
14 }
15 }
注意: (1)、方法內部類只能在定義該內部類的方法內實例化,不可以在此方法外對其實例化。
(2)、方法內部類對象不能使用該內部類所在方法的非final局部變量。
因為方法的局部變量位於棧上,只存在於該方法的生命期內。當一個方法結束,其棧結構被刪除,
局部變量成為歷史。但是該方法結束之後,在方法內創建的內部類對象可能仍然存在於堆中!
例如,如果對它的引用被傳遞到其他某些代碼,並存儲在一個成員變量內。正因為不能保證局部變
量的存活期和方法內部類對象的一樣長,所以內部類對象不能使用它們。 (該理解來源於百度百科)
3、匿名內部類
1)、抽象匿名內部類
1 package com.anonymous;
2
3 public class AbstractClass {
4 public void test(){ //方法為test
5 TestA a = new TestA(){ //實現抽象類
6 @Override
7 public void run() { //實現抽象類的方法
8 System.out.println("我正在使用抽象匿名內部類");
9 }
10 } ;
11 a.run() ; //調用內部類的方法
12 }
13 public static void main(String[] args) {
14 new AbstractClass().test() ; //測試
15 }
16 }
17 //定義一個抽象類 TestA 抽象方法為run()
18 abstract class TestA{
19 public abstract void run() ;
20 }
2)、接口匿名內部類
1 package com.anonymous;
2
3 public class TestAnonymous {
4 MyInterface m = new MyInterface(){ //實現接口
5 public void eat() { //重寫MyInterface 接口方法
6 System.out.println("我正在吃飯!");
7 }
8 } ;
9 public void ss(){ //方法ss
10 m.eat() ; //調用重寫的方法
11 }
12 public static void main(String[] args) {
13 new TestAnonymous().ss() ; //測試
14 }
15 }
16 //定義一個接口 方法為 eat
17 interface MyInterface{
18 public void eat() ;
19 }
注意:匿名內部 類 可以定義在方法內也可以定義在類的成員中,不管是那種匿名內部類都不能被外部類直接調用
四、內部類的作用?
每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。如果沒有
內部類提供的可以繼承多個具體的或抽象的類的能力,一些設計與編程問題就很難解決。從這個角度看,內部類使得多重繼承的解決方案變得完整。
接口解決了部分問題,而內部類有效地實現了“多重繼承”。