快速學習JAVA內部類
內部類
將一個類定義在另一個類裡面或者一個方法裡面,這樣的類稱為內部類。廣泛意義上的內部類一般來說包括這四種:成員內部類、區域性內部類、匿名內部類和靜態內部類
1、成員內部類
成員內部類內部類中最為簡單的部分,就是在類A中再定義一個類B。顯然類B必須在類A裡面
public class Animal { private String name; public static int age; public String getName() { return name; } public void setName(String name) { this.name = name; } //內部類,作為Animal類的一個成員 class Dog{ public void getVoice(){ age=1; setName("旺財"); System.out.println(age+"歲的"+name+"發出\"汪汪\"的叫聲"); } } }
從上面的程式碼可以看出Animal是Dog的外部類,Dog是Animal的內部類。重要的是成員內部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態成員)。
那麼如何例項化成員內部類?如何呼叫它的成員?
成員內部類是依附外部類而存在的,也就是說,如果要建立成員內部類的物件,前提是必須存在一個外部類的物件。
public static void main(String[] args) { //第一種方式 Animal animal = new Animal(); Animal.Dog dog1=animal.new Dog(); dog1.getVoice(); //第二種方式 Animal.Dog dog2=new Animal().new Dog(); dog2.getVoice(); }
不過要注意的是,當成員內部類擁有和外部類同名的成員變數或者方法時,會發生隱藏現象,即預設情況下訪問的是成員內部類的成員。如果要訪問外部類的同名成員,需要以下面的形式進行訪問:
外部類.this.成員變數
外部類.this.成員方法
現在我們已經知道了如何呼叫內部類成員,那麼內部類如何訪問外部類的成員?在外部類中如果要訪問成員內部類的成員,必須先建立一個成員內部類的物件,再通過指向這個物件的引用來訪問:
public class Animal { //例項化內部類 private Dog getInstance(){ return new Dog(); } public void getAnimalVoice(){ //呼叫內部類的方法 getInstance().getVoice(); } //內部類,作為Animal類的一個成員 class Dog{ public void getVoice(){ System.out.println("汪、汪、汪。。。。。"); } } }
2、區域性內部類
在方法或者作用域裡面定義的內部類叫做區域性內部類,它和成員內部類的區別在於區域性內部類的訪問僅限於方法內或者該作用域內。
與區域性變數類似,區域性內部類不能有訪問說明符,因為它不是外圍類的一部分,但是它可以訪問當前程式碼塊內的常量,和此外圍類所有的成員。
需要注意的是:
(1)、區域性內部類只能在定義該內部類的方法內例項化,不可以在此方法外對其例項化。
(2)、區域性內部類物件不能使用該內部類所在方法的非final區域性變數。
案例程式碼:
public class Fruit {
public Fruit() { }
}
class Apple{
public Apple(){}
public Fruit getOrange(){
//方法裡面定義的類
class Orange extends Fruit{
String name="橘子";
public void printName(){
System.out.println(name);
}
}
return new Orange();
}
}
匿名內部類
匿名內部類就是沒有名字的內部類。
如果滿足下面的一些條件,使用匿名內部類是比較合適的:
- 只用到類的一個例項。
- 類在定義後馬上用到。
- 類非常小(SUN推薦是在4行程式碼以下)
- 給類命名並不會導致你的程式碼更容易被理解。
在使用匿名內部類時,要記住以下幾個原則:
- 匿名內部類不能有構造方法。
- 匿名內部類不能定義任何靜態成員、方法和類。
- 匿名內部類不能是public,protected,private,static。
- 只能建立匿名內部類的一個例項。
- 一個匿名內部類一定是在new的後面,用其隱含實現一個介面或實現一個類。
- 因匿名內部類為區域性內部類,所以區域性內部類的所有限制都對其生效。
案例
//當我們想運用一個執行緒,但又不想自定義一個類通過繼
//承Thread類來實現的時候,我們可以採用匿名內部類的實現方式
//這就是一個最為簡單的匿名內部類
Thread thread=new Thread(){
@Override
public void run() {
System.out.println("我是一個匿名內部類的方法");
}
};
靜態內部類
靜態內部類也是定義在另一個類裡面的類,只不過在類的前面多了一個關鍵字static。靜態內部類是不需要依賴於外部類的,這點和類的靜態成員屬性有點類似,並且它不能使用外部類的非static成員變數或者方法,這點很好理解,因為在沒有外部類的物件的情況下,可以建立靜態內部類的物件,如果允許訪問外部類的非static成員就會產生矛盾,因為外部類的非static成員必須依附於具體的物件。
案例
//定義
public class Fruit {
public Fruit() { }
static class Apple{
public Apple(){}
}
}
//例項化
Fruit.Apple apple=new Fruit.Apple();