Heim  >  Artikel  >  Java  >  Java-Verbesserung Kapitel (9) – Detaillierte Erläuterung anonymer interner Klassen

Java-Verbesserung Kapitel (9) – Detaillierte Erläuterung anonymer interner Klassen

黄舟
黄舟Original
2017-02-09 13:48:501293Durchsuche

Eine kurze Einführung in anonyme innere Klassen finden Sie im Kapitel „Java-Verbesserung – Detaillierte Erläuterung interner Klassen“. Es gibt jedoch viele andere detaillierte Probleme mit internen Klassen, weshalb dieser Blog abgeleitet wurde. In diesem Blog erfahren Sie mehr über die Verwendung anonymer innerer Klassen, worauf Sie bei anonymen inneren Klassen achten sollten, wie Sie anonyme innere Klassen initialisieren und warum die von anonymen inneren Klassen verwendeten formalen Parameter endgültig sein müssen.


1. Verwenden Sie anonyme innere Klassen. Interne Klassen

Da anonyme innere Klassen keine Namen haben, ist die Art und Weise, wie sie erstellt werden, etwas seltsam. Das Erstellungsformat ist wie folgt:

new 父类构造器(参数列表)|实现接口()    
    {    
     //匿名内部类的类体部分    
    }

Hier sehen wir, dass wir zur Verwendung anonymer innerer Klassen eine übergeordnete Klasse erben oder eine Schnittstelle implementieren müssen. Natürlich können wir nur eine übergeordnete Klasse erben oder eine Schnittstelle implementieren . Gleichzeitig fehlt das Schlüsselwort class, da anonyme innere Klassen new direkt verwenden, um einen Verweis auf ein Objekt zu generieren. Natürlich ist dieser Hinweis implizit.

public abstract class Bird {  
    private String name;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
      
    public abstract int fly();  
}  
  
public class Test {  
      
    public void test(Bird bird){  
        System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米");  
    }  
      
    public static void main(String[] args) {  
        Test test = new Test();  
        test.test(new Bird() {  
              
            public int fly() {  
                return 10000;  
            }  
              
            public String getName() {  
                return "大雁";  
            }  
        });  
    }  
}  
------------------  
Output:  
大雁能够飞 10000米

In der Testklasse akzeptiert die test()-Methode einen Bird-Typ-Parameter. Gleichzeitig wissen wir, dass es keine Möglichkeit gibt, eine abstrakte Klasse direkt neu zu erstellen Klasse, bevor wir sie neu implementieren können. Verwenden Sie also die anonyme innere Klasse direkt in der Hauptmethode, um eine Bird-Instanz zu erstellen.

Da eine anonyme innere Klasse keine abstrakte Klasse sein kann, muss sie alle abstrakten Methoden in ihrer abstrakten übergeordneten Klasse oder Schnittstelle implementieren.

Dieser anonyme innere Klassencode kann tatsächlich in die folgende Form aufgeteilt werden:

public class WildGoose extends Bird{  
    public int fly() {  
        return 10000;  
    }  
      
    public String getName() {  
        return "大雁";  
    }  
}  
  
WildGoose wildGoose = new WildGoose();  
test.test(wildGoose);

Hier erstellt das System ein Objekt der anonymen Klasse, das von der Bird-Klasse geerbt wurde, und das Objekt wird transformiert werden. Ein Verweis auf den Bird-Typ.

Es gibt einen Fehler bei der Verwendung anonymer innerer Klassen, das heißt, sie können nur einmal verwendet werden. Beim Erstellen einer anonymen inneren Klasse wird sofort eine Instanz der Klasse erstellt und die Definition dieser Klasse erstellt Die Klasse verschwindet sofort, sodass anonyme innere Klassen nicht wiederverwendet werden können. Wenn wir im obigen Beispiel die innere Klasse in der test()-Methode mehrmals verwenden müssen, wird empfohlen, die Klasse neu zu definieren, anstatt eine anonyme innere Klasse zu verwenden.

2. Hinweise

Bei der Verwendung anonymer innerer Klassen müssen wir auf die folgenden Punkte achten:

1. Bei der Verwendung anonymer innerer Klassen müssen wir dies tun erben Eine Klasse oder eine Schnittstelle implementieren, aber Sie können nicht beides gleichzeitig haben, Sie können nur eine Klasse erben oder eine Schnittstelle implementieren.

2. Konstruktoren können nicht in anonymen inneren Klassen definiert werden.

3. In anonymen inneren Klassen dürfen keine statischen Mitgliedsvariablen und statischen Methoden vorhanden sein.

4. Anonyme innere Klassen sind lokale innere Klassen, daher gelten alle Einschränkungen für lokale innere Klassen auch für anonyme innere Klassen.

5. Eine anonyme innere Klasse kann nicht abstrakt sein. Sie muss alle abstrakten Methoden der geerbten Klasse oder der implementierten Schnittstelle implementieren.


3. Warum sollten die verwendeten formalen Parameter endgültig sein?

Referenzdatei: http://android.blog.51cto.com/268543/384844

Wenn wir Parameter an anonyme innere Klassen übergeben und der formale Parameter in der inneren Klasse verwendet werden muss, muss der formale Parameter endgültig sein. Das heißt: Wenn der formale Parameter der Methode in der inneren Klasse verwendet werden muss, muss der formale Parameter endgültig sein.

Warum muss es endgültig sein?

Zunächst wissen wir, dass die interne Klasse nach erfolgreicher Kompilierung eine Klassendatei generiert. Diese Klassendatei ist nicht dieselbe Klassendatei wie die externe Klasse. Sie behält nur Verweise auf die externe Klasse . Wenn die von der externen Klasse übergebenen Parameter von der internen Klasse aufgerufen werden müssen, werden sie aus Sicht des Java-Programms direkt aufgerufen:

public class OuterClass {  
    public void display(final String name,String age){  
        class InnerClass{  
            void display(){  
                System.out.println(name);  
            }  
        }  
    }  
}

Aus dem obigen Code scheint der Name zu sein Parameter sollte direkt von der internen Klasse aufgerufen werden? Tatsächlich ist dies nicht der Fall. Die eigentliche Operation nach der Java-Kompilierung ist wie folgt:

public class OuterClass$InnerClass {  
    public InnerClass(String name,String age){  
        this.InnerClass$name = name;  
        this.InnerClass$age = age;  
    }  
      
      
    public void display(){  
        System.out.println(this.InnerClass$name + "----" + this.InnerClass$age );  
    }  
}

Aus dem obigen Code ruft die innere Klasse die von der Methode übergebenen Parameter nicht direkt auf, sondern verwendet sie sein eigener Konstruktor, um Parameter zu sichern, und was von der eigenen internen Methode aufgerufen wird, sind tatsächlich ihre eigenen Eigenschaften und nicht die von der externen Methode übergebenen Parameter.

       直到这里还没有解释为什么是final?在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。

      简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。

      故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。


       四、匿名内部类初始化

       我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。

public class OutClass {  
    public InnerClass getInnerClass(final int age,final String name){  
        return new InnerClass() {  
            int age_ ;  
            String name_;  
            //构造代码块完成初始化工作  
            {  
                if(0 < age && age < 200){  
                    age_ = age;  
                    name_ = name;  
                }  
            }  
            public String getName() {  
                return name_;  
            }  
              
            public int getAge() {  
                return age_;  
            }  
        };  
    }  
      
    public static void main(String[] args) {  
        OutClass out = new OutClass();  
          
        InnerClass inner_1 = out.getInnerClass(201, "chenssy");  
        System.out.println(inner_1.getName());  
          
        InnerClass inner_2 = out.getInnerClass(23, "chenssy");  
        System.out.println(inner_2.getName());  
    }  
}

以上就是 java提高篇(九)-----详解匿名内部类的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn