Heim  >  Artikel  >  Java  >  Erklären Sie, wie Sie in Java innere Klassenobjekte erstellen und auf Objekte zugreifen

Erklären Sie, wie Sie in Java innere Klassenobjekte erstellen und auf Objekte zugreifen

高洛峰
高洛峰Original
2017-01-20 17:42:381234Durchsuche

Konstruieren Sie interne Klassenobjekte durch Reflexion
Schreiben Sie zunächst eine Klasse mit internen Klassen unter dem Javalang-Paket:

package javalang;
 
public class Outer {
  public static class Inner1{}
}

Beachten Sie, dass diese Klasse öffentlich statisch ist. Wir werden sie verlangsamen später nach unten Entfernen Sie diese Modifikatoren langsam.

Um das Inner1-Objekt durch Reflexion zu erstellen, müssen Sie zunächst das Klassenobjekt von Inner1 abrufen. Wir schreiben die Hauptmethode in Outer:

public class Outer {
  public static class Inner1{}
   
  public static void main(String[] args) {
    System.out.println(Inner1.class);
  }
}

Ausgabeergebnis:

class javalang.Outer$Inner1

Dann versuchen wir herauszufinden, ob dieser Klassenname korrekt ist:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1"));
}

Führen Sie es aus, das ist richtig. Dann verwenden Sie es einfach, um Objekte zu erstellen. Das Erstellen von Objekten basiert auf Konstruktoren. Verfügt diese Klasse über eine Konstruktormethode? Wir können schreiben:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1").getConstructors().length);
}


Führen Sie es aus und geben Sie 1 aus. Es scheint so zu sein. Dann schauen Sie sich an, wie diese Konstruktionsmethode aussieht:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1").getConstructors()[0]);
}


Ausgabeergebnis: public javalang.Outer$Inner1(). Dies ist die Standardkonstruktionsmethode. Wir können also so schreiben:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1")
      .getConstructors()[0].newInstance();
}

Ausgabeergebnis: javalang.Outer$Inner1@ca0b6. Dies zeigt an, dass die Ausführung erfolgreich war.

Als nächstes entfernen wir das öffentliche Schlüsselwort Inner und führen es erneut aus. Das Ergebnis ist ein Fehler:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

Dies bedeutet, dass die Bauweise nicht gefunden wurde. Wirklich nicht? Wir ändern die Hauptmethode zurück:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1")
      .getConstructors().length);
}

Ausgabeergebnis: 0. Gibt es wirklich keinen Konstruktor? Eigentlich nein, es ist nur so, dass die Bauweise nicht öffentlich ist. Zu diesem Zeitpunkt müssen wir getDeclaredConstructors() verwenden, um Folgendes zu erhalten:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1")
      .getDeclaredConstructors().length);
}

Ausgabeergebnis: 1. Dies findet die Bauweise. Dann rufen wir diesen Konstruktor weiterhin auf:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1")
      .getDeclaredConstructors()[0].newInstance());
}

Ausgabeergebnis: javalang.Outer$Inner1@ca0b6. Jetzt können wir Reflektion verwenden, um Objekte nicht öffentlicher innerer Klassen zu konstruieren.

Als nächstes entfernen wir das statische Schlüsselwort. Zu diesem Zeitpunkt wurde ein Fehler gemeldet:
Ausnahme im Thread „main“ java.lang.IllegalArgumentException: falsche Anzahl von Argumenten

Was bedeutet das? Wir haben beim Aufruf keine Parameter übergeben und der Fehlerinhalt bestand darin, dass die Anzahl der Parameter falsch war. Welche Parameter hat dieser Konstruktor? Lassen Sie uns den Code ändern und einen Blick darauf werfen:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1")
      .getDeclaredConstructors()[0]);
}

Ausgabeergebnis: javalang.Outer$Inner1(javalang.Outer)

Es stellt sich heraus, dass der Konstruktor einen Outer-Typparameter benötigt. Das geht ganz einfach:

public static void main(String[] args) throws Exception {
  System.out.println(Class.forName("javalang.Outer$Inner1")
      .getDeclaredConstructors()[0].newInstance(new Outer()));
}

Ausgabeergebnis:

javalang.Outer$Inner1@ca0b6

OK, das war's. Es scheint, dass nicht statische innere Klassen keine Standardkonstruktionsmethode haben und während der Konstruktion eine Instanz einer äußeren Klasse als Parameter übergeben werden muss.


Java: So greifen Sie auf ein Objekt zu
Ein Problem für Java-Anfänger ist die Frage, wie man entscheidet, ob ein Objekt als Methodenvariable oder als Mitgliedsvariable definiert werden soll.

Einsteigern wird das zunächst egal sein. Aber wenn die geschriebenen Programme immer größer werden und es immer mehr Klassen gibt, entsteht auch diese Art von Bedrängnis.

Aber was ich hier schreiben möchte, ist: Wie man ein Objekt nach Belieben anordnet, damit man jederzeit darauf zugreifen kann. Sobald Sie dies beherrschen, können Sie frei entscheiden, wo Sie ein Objekt platzieren möchten.

Hier ist ein einfaches Beispiel:

public class AccessingObject {
   
  public static void main(String[] args) {
    Date date = new Date();
  }
   
  // 获得 date 对象一小时后的时间
  private static void anHourLater() {
    // 这里如何获得 main() 方法中的 date 变量?
  }
}

Wie in der anHourLater()-Methode beschrieben, möchten Sie die Uhrzeit eine Stunde nach dem Datum erhalten. Was zu tun? Im Folgenden finden Sie mehrere Methoden.

(1) Parameterübergabe

public class AccessingObject {
   
  public static void main(String[] args) {
    Date date = new Date();
    anHourLater(date);
  }
   
  // 获得 date 对象一小时后的时间
  private static void anHourLater(Date d) {
    Date anHourLater = new Date(d.getTime() + 3600000);
  }
}

(2) Als Mitglied definiert. Auf Mitglieder kann mit allen Methoden zugegriffen werden, und die Mitgliederinitialisierung kann dort platziert werden, wo sie definiert sind, oder in einer beliebigen Methode.

public class AccessingObject {
   
  private static Date date;
   
  public static void main(String[] args) {
    date = new Date();
    anHourLater();
  }
   
  // 获得 date 对象一小时后的时间
  private static void anHourLater() {
    Date anHourLater = new Date(date.getTime() + 3600000);
  }
}

(3) Ordne es einer anderen Klasse zu. Im folgenden Beispiel können alle Klassen im selben Paket auf DateHolder.date zugreifen, nicht nur die AccessingObject-Klasse.

public class AccessingObject {
   
  public static void main(String[] args) {
    DateHolder.date = new Date();
  }
   
  // 获得 date 对象一小时后的时间
  private static void anHourLater() {
    Date anHourLater = new Date(DateHolder.date.getTime() + 3600000);
  }
}
   
class DateHolder {
  public static Date date;
}

Vergleicht man diese drei Beispiele, können die ersten beiden nur innerhalb der Klasse verwendet werden und sind relativ sicher. Wenn Sie nicht möchten, dass dieses Objekt direkt von anderen Klassen geändert wird, verwenden Sie nicht die dritte Methode.

Der Unterschied zwischen der ersten Methode und der zweiten Methode besteht darin, dass, wenn ein Objekt nur in einer Methode verwendet wird, das Objekt bei Ausführung der Methode problemlos recycelt werden kann (beachten Sie, dass es nicht sofort recycelt wird). . Wenn das Objekt als Mitglied einer Klasse definiert ist, wird es erst recycelt, nachdem die Klasse, in der es sich befindet, recycelt wurde. Offensichtlich ist die erste Methode die ressourcenschonendste, und wir sollten versuchen, die erste Methode zu verwenden.

Rückblickend auf diese drei Beispiele: Wenn die main()-Methode die in der anHourLater()-Methode erhaltene Zeit eine Stunde später erhalten möchte, gibt es auch mehrere entsprechende Möglichkeiten. Die letzten beiden Beispiele müssen nicht geändert werden. Im ersten Beispiel kann direkt auf das Datumsobjekt zugegriffen werden. Es gibt zwei Änderungsmethoden:

(1) als Rückgabewert

public class AccessingObject {
   
  public static void main(String[] args) {
    Date date = new Date();
    Date anHourLater = anHourLater(date);
  }
   
  // 获得 date 对象一小时后的时间
  private static Date anHourLater(Date d) {
    return new Date(d.getTime() + 3600000);
  }
}

(2) Den Inhalt von Parametern direkt ändern

public class AccessingObject {
   
  public static void main(String[] args) {
    Date date = new Date();
    anHourLater(date);
  }
   
  // 获得 date 对象一小时后的时间
  private static void anHourLater(Date d) {
    d.setTime(d.getTime() + 3600000);
  }
}

Die zweite Methode sollte verwendet werden mit Vorsicht, denn Es ist falsch, die Sachen anderer Leute beiläufig anzufassen. Sie wissen nicht, ob es dem Aufrufer der Methode gefällt oder nicht.

Weitere Artikel, die erklären, wie man interne Klassenobjekte erstellt und auf Objekte in Java zugreift, finden Sie auf der chinesischen PHP-Website!

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