內部類及匿名內部類的詳細描述
內部類(Inner Class)
內部類的定義:
在Java中,允許在一個類的內部定義類,這樣的類稱作內部類也叫做巢狀類, 這個內部類所在的類稱作外部類。
內部類的建立:
語法: 外部類名.內部類名 變數名=new 外部類名().new 內部類名();
舉例: 假設A是外部類,B是內部類
A.B b=new A().new B();
建立內部類物件時應注意:
1.在外部類的內部可以直接使用inner s=new inner();(因為外部類知道inner是哪個類,所以可以生成物件。)
2.在外部類的外部,要生成(new)一個內部類物件,需要首先建立一個外部類物件(外部類可用),然後在生成一個內部類物件。
內部類的表現形式:
1.靜態內部類
2.成員內部類
3.方法內部類
4.匿名內部類
內部類的共性:
1.內部類仍然是一個獨立的類,在編譯之後會內部類會被編譯成獨立的.class檔案,但是前面冠以外部類的類命和$符號。
2.內部類不能用普通的方式訪問。內部類是外部類的一個成員,因此內部類可以自由地訪問外部類的成員變數,無論是否是private的。
內部類的優點:
1.內部類成員可以直接訪問外部類的成員(包括私有成員)。
2.比類具有更好的封裝性
基本形式:
public class Outer1 {
public class Inner{
}
}
例子:
(1).public class Outer {
private int num=4; //定義成員變數
public void test(){
Inner inner =new Inner();
inner.show();
}
//下面的程式碼定義了一個成員內部類
class Inner{
void show(){
//在成員內部類的方法中訪問外部類的成員變數
System.out.println("num="+num);
}
}
}
public class Example {
public static void main(String[] args){
Outer.Inner inner =new Outer().new Inner(); //建立內部類物件
inner.show(); //呼叫test()方法
}
}
(2).public class Myclass {
public Myclass() {
System.out.println("產生MyClass");
}
class M {
public M() {
System.out.println("產生M");
}
}
public static void main(String[] args) {
Myclass my = new Myclass();
// 內部類相當於外部類的屬性,內部類物件的產生要依賴於外部類物件,只要是屬性可以有的修飾符都可以修飾內部類。
// 內部類在編譯時同樣會產生class檔案。命名為:外部類名$內部類名.class
Myclass.M m = my.new M();
}
}
匿名內部類(Anonymous Inner Class)
匿名內部類的定義:
沒有名字的內部類。表面上看起來那是它的名字,實際上不是它的名字。
使用匿名內部類的前提:
必須繼承父類或實現一個介面
匿名內部類的分類:
1.繼承式的匿名內部類
2.介面式的匿名內部類
3.引數式的匿名內部類
特點:
匿名內部類一定是跟在new的後面,用其隱含實現一個介面或一個類,沒有類名,根據多型,我們使用其父類名。因為匿名內部類屬於區域性類,所以區域性類的所有限制對其生效。匿名內部類是唯一一種無構造方法的類。匿名內部類在編譯時,系統自動起名Out$1.class。如果一個物件編譯時的型別是介面,那麼其執行的型別為實現這個介面的類。
注意點:
1.不能有構造方法
2.不能定義任何靜態成員、方法或類
3.不能是public,protected,private,static。
4.只能建立匿名內部類的一個例項。
匿名內部類的優點:
可以使命名變得簡潔
使程式碼更加緊湊,簡潔,封裝性比內部類更優
一個類用於繼承其他類或是實現介面,無需增加其他的方法,只是對繼承方法實現 覆蓋。
匿名內部類的缺點:
可讀性差
例子:
(1).public class Dog { //建立一個Dog類
static abstract class Ball { //建立一個抽象類
abstract String getName(); //建立一個抽象方法,抽象方法必須用abstract來修飾
}
void play(Ball b){
System.out.println(b.getName());
}
public static void main(String[] args){
Dog dog = new Dog();
dog.play(new Ball(){ //匿名內部類實現抽象方法getName();
@Override
String getName() {
return "qiu qiu";
}});
}
}
(2).
public interface Product {
public double getPrice();
public String getName();
}
public class TestAnonymous {
public void test(Product p){
System.out.println("我購買了一個"+p.getName()+",花掉了"+p.getPrice());
}
public static void main(String[] args){
TestAnonymous ta=new TestAnonymous();
//呼叫test方法,需要傳入一個Product引數,此處傳入其匿名,實現類的例項
ta.test(new Product(){
public double getPrice(){
return 40;
}
public String getName(){
return "水晶球";
}
});
}
}
//以上的匿名內部類相當於
/*
class AnonymousProduct implements Product //implements是實現介面的關鍵字
{
public double getPrice(){
return 40;
}
public String getName(){
return "水晶球";
}
}
ta.test(new AnonymousProduct());
*/