------ Java教育訓練、Android教育訓練、iOS教育訓練、.Net教育訓練、期待與您交流! ------- 内部類 1,什麼叫内部類?
顧名思義,内部類就是定義在一個類中的類。
2,為什麼會有内部類?怎麼來的?
當我們進行java開發時,有時需要實作一個僅包含1-2個方法的接口。
例 : 在學習集合架構的時候,有一個疊代器(Iterator接口),它裡面就有一個方法iterator(),是專門用來給Colleaction集合進行疊代的,檢視其底層發現它是嵌入在集合接口内部的。
例 : 在我們學習GUI時,當一個display元件需要一個事件回調方法時,如:一個按鈕的ActionListener時,也是用到了内部類。 那麼,以上兩個例子要說明什麼呢?
通過上面兩個例子,我們會發現,如果我們不用内部類的方式來完成,而是使用普通類來實作這些操作,最終會得到很多僅在單個位置上使用的小型類,僅僅是為類一個小小的功能,就要建立一個類,是不是有點浪費呢? 是以為了解決這個問題就出現了内部類這個看上去很難懂的類。
當然,内部類還有很多理由值得我們來用,
理由(1)内部類可以直接通路外部類中的成員,包括私有。
理由(2)内部類可以對同一個包中的其它類隐藏起來。
理由(3)當想要定義一個回調函數且不想編寫大量代碼時,使用匿名内部類比較友善。
3,内部類的通路規則
(1)内部類可以直接通路外部類中的成員,包括私有。之是以可以直接通路外部類中的成員,是因為内部類中持有了一個外部類引用,格式:外部類名.this。
(2)外部類要通路内部類,必須要建立内部類對象。
代碼:
//外部類
class Outer {
//外部類私有成員變量
private int x = 3;//Outer.this.x
//内部類
class Inner {
//内部類成員
int x = 4;//this.x
//内部類成員方法
void function() {
//内部類局部變量
int x = 6;//x
System.out.println("Inner :" + x);//6
System.out.println("Inner :" + this.x);//4
//内部類可以直接通路外部類成員,包括私有
System.out.println("Inner :" +Outer.this. x);//3
}
}
//外部類成員方法
void method() {
//建立内部類成員變量
Inner in = new Inner();//外部類要通路内部類必須要建立内部類對象。
//調用内部類成員方法
in.function();
}
}
//測試類
public class InnerDemo {
public static void main(String[] args) {
//建立外部類對象
Outer out = new Outer();
//調用外部類成員方法。
out.method();
//直接通路内部類中的成員方法
Outer.Inner outin = new Outer().new Inner();
outin.function();
}
}
4,當内部類在成員位置上,并且被修飾符所修飾。
比如:private:将内部類在外部類中進行封裝。
static:内部類具備靜态的特性。 當内部類被static修飾後,隻能直接通路外部類的static成員。出現了通路權限。 代碼:
//外部類
class Outer1
{
//私有靜态成員變量
private static int x= 3;
//靜态内部類1
static class Inner1{
//靜态内部類中的靜态成員變量
static int x = 4;
//靜态内部類中的靜态成員方法
static void function(){
//非靜态通路了靜态
int x = 5;
//列印靜态成員方法中的非靜态變量
System.out.println(x);
//列印靜态内部類中靜态成員變量
System.out.println(Inner1.x);
//列印外部類的靜态成員變量
System.out.println(Outer1.x);
}
}
//靜态内部類2
static class Inner2{
//靜态内部類的非靜态成員方法
void function(){
//靜态内部類通路外部類的靜态成員變量
System.out.println(Outer1.x);
}
}
}
//測試類
public class InnerDemo2 {
public static void main(String[] args) {
//外部類通路靜态内部類的靜态方法
Outer1.Inner1.function();
//外部類通路靜态内部類的非靜态方法
new Outer1.Inner2().function();
}
}
注意:當内部類中定義了靜态成員,該内部類必須是靜态的。(因為靜态隻能通路靜态)
當外部類的靜态方法通路内部類時,内部類必須是靜态的(同上)
5,什麼時候使用内部類?
當描述事物時,事物的内部還有事物,該事物用内部類來描述。因為内部類事物在使用外部類事物的内容。
6,當内部類定義在局部時
(1)不可以被成員修飾符修飾。
(2)可以直接通路外部類中的成員,因為還持有外部類的引用。但是不可以通路它所在的局部中的變量,隻能通路被final修飾的局部變量。
代碼:
//外部類
class Outer2{
int x = 3;//Outer2.this.x
void method(final int a){
final int y = 4;
//局部内部類
class Inner{
void function(){
//局部内部類通路局部變量時,該變量必須是final常量。
System.out.println(y);
System.out.println(a);
System.out.println(x);//還持有外部類的引用
}
}
//外部類成員方法通路局部内部類的成員方法。
new Inner().function();
}
}
//測試類
public class InnerDemo3 {
public static void main(String[] args) {
//調用方法
new Outer2().method(7);
}
}
7,匿名内部類
(1)匿名内部類其實就是内部類的簡寫格式。
(2)定義匿名内部類前提:内部類必須是繼承一個類或者實作接口。
(3)匿名内部類的格式:new 父類或者接口(){定義子類的内容}
(4)匿名内部類是一個匿名子類對象,可以了解為帶内容的對象。
(5)匿名内部類中定義的方法最好不要超過三個。
代碼:
//抽象類
abstract class AbsDemo{
//抽象方法
abstract void show();
}
//外部類
class Outer3{
int x = 3;
public void function(){
//建立匿名内部類的對象
AbsDemo d= new AbsDemo(){//父類引用指向子類對象
void show(){
System.out.println(x);
}
};
//實作接口的子類對象調用複寫父類的方法。
d.show();
//-------------------------------------------------------------------
//通過匿名内部類的匿名子類對象來調用複寫父類的方法。
new AbsDemo(){//父類引用指向子類對象
void show(){
System.out.println(x);
}
}.show();
}
}
//測試類
public class InnerDemo4 {
public static void main(String[] args) {
//通過外部類匿名對象調用方法
new Outer3().function();
}