[Java] Um die Typinformationen der Typparameter zur Laufzeit zu kennen

0. Fazit zuerst


1. Herausforderung

Der Typ der Elemente des Arrays kann später mit array.getClass (). GetComponentType (), gefunden werden. Mit Listen wie ArrayList und LinkedList ist es schwierig, dasselbe zu tun!


2. Zielgruppe


3. Schlechtes Beispiel


Vorbereitung

class Hoge
{
    public static void main(String[] args)
    {
        ArrayList<Number> inteList = new ArrayList<>();
        System.out.println(new ParamGetter(inteList).get());
        //Holen Sie sich von ParamGetter Klasse()In der Methode
        //Ich möchte "Nummer" usw. anzeigen.
    }
}

3.1 T.class ist nicht möglich

class ParamGetter
{
    Class paramClass;
    <T> ParamGetter(List<T> list)
    {
        this.paramClass = T.class;
        //× Dies ist NG
    }
    Class get(){return paramClass;}
}

3.2 Reflexion schlägt fehl [1]

//(Für diejenigen, die nachgedacht haben)
class ParamGetter
{
    Type paramType;
    <T> ParamGetter(List<T> list)
    {
        this.paramType = ((ParameterizedType)new ArrayList<T>(){}.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }
    Type get(){return paramType;}
}

Ergebnis: "T" wird angezeigt Gleiches gilt für die Methode [2], die die Methode "getGenericType ()" der Klasse "Field" verwendet.


3.3 Array mit toArray () fehlgeschlagen

class ParamGetter
{
    Object array;
    <T>ParamGetter(List<T> list)
    {
        this.array = (T[])list.toArray();
        //☆System.out.println((T[])list.toArray());
    }

    Type get() throws NoSuchFieldException, SecurityException
    {
        return this.array.getClass().getComponentType();
    }
}

Ergebnis (main): "Klasse java.lang.Object" wird angezeigt.

<!--

Serpentin Die Idee, "ein Element aus einer Liste zu nehmen und seinen Typ zu untersuchen", ist zwar möglich, aber tatsächlich unangemessen.


4. Grundursache

Die Typinformationen verschwinden in der Phase der Übergabe an die Methode


In 3.3 wird zunächst das tatsächliche Argument vom Typ "ArrayList " an das Dummy-Argument vom Typ "List " übergeben. Als nächstes wird es in ein Array vom Typ "T" konvertiert und in einem Feld vom Typ "Objekt" gespeichert. Wenn dann get () aufgerufen wird, wird der "Laufzeittyp" (Array-Typ) erhalten und der Typ des Elements des Arrays wird überprüft.


Weil das Ergebnis "Objekt" ist Dies bedeutet, dass "T" = "Objekt" anstelle von "T" = "Zahl".


Wenn ich den Code von ☆ ausführe, wird tatsächlich angezeigt, dass er vom Typ Object [] ist. → Immerhin T [] = Object []

System.out.println((T[])list.toArray());//Object[]Es kommt mit einer Form heraus.

Daraus ist ersichtlich, dass die Typparameterinformationen verschwunden sind, während sie als Argument übergeben wurden. Wird beim Kompilieren tatsächlich gelöscht (wird zum abstraktesten Typ, der empfangen werden kann) [3]


5. Lösung

Was zur Laufzeit verschwindet, kann nicht einmal durch Reflexion entfernt werden (Reflexion ist eine Technologie zur Laufzeit [4]). →


5.1 Ersetzen Sie den Typparameter durch ein Argument

class Hoge<T> Fuga Überleben Fuga as
new Hoge(); × Geben Sie Parameter von Instanzmethoden ein
new Hoge<Fuga>(); Geben Sie die Parameter der Klasse ein[5]
new Hoge(Fuga.class) Klassentyp-Argument

△ ・ ・ ・ Es ist nicht unmöglich, aber es wird überflüssig.


5.2 ArrayList<T>
ArrayList_<T>

Was Sie tun möchten: new ArrayList_ <Number> (Object ...); new ArrayList <Number> (Object ...); und Machen Sie es fast die gleiche Bedeutung Und machen Sie Number zur Laufzeit verfügbar


Hat fast die gleiche Bedeutung → Realisierbar durch Vererbung Schreiben Sie unter Bezugnahme auf den Kommentar von Herrn saka1029 in diesem Artikel

public class ArrayList_<T> extends ArrayList<T> {

    public final Class<?> clazz;

    public ArrayList_(T... dummy) {
        if (dummy.length > 0)
            throw new IllegalArgumentException(
                "Geben Sie kein Dummy-Argument an");
        clazz = dummy.getClass().getComponentType();
    }

    public Class getComponentClass() {
        return clazz;
    }
}


6 (Bonus) Aktiviert new Hoge <t.getClass ()>

Eine Instanz des generischen Typs "Hoge " kann nicht aus einer Variablen vom Typ "Klasse " erstellt werden.


Kurz gesagt, new Hoge <t.getClass ()> kann nicht durchgeführt werden. Wenn Sie es in die Methode schreiben, ist es bis zu einem gewissen Grad als "new Hoge <?>" Hoge<t.getClass()>.getClass().getDeclaredConstructor().newInstance() Es ist nirgendwo möglich, eine generische Instanz zu erstellen.


Wenn Sie dies tun möchten, übergeben Sie eine Variable vom Typ Class <?> Type als Argument.

public class ArrayList_<T> extends ArrayList<T> {

    public final Class<?> clazz;

    public ArrayList_(T... dummy) {
        if (dummy.length > 0)
            throw new IllegalArgumentException(
                "Geben Sie kein Dummy-Argument an");
        clazz = dummy.getClass().getComponentType();
    }

    public ArrayList_(Class<T> clazz)//Füge das hinzu
    {
        this.clazz = clazz;
    }

    public Class getComponentClass() {
        return clazz;
    }
}

Referenz

[1]http://unageanu.hatenablog.com/entry/20071105/1194264963 [2]https://codeday.me/jp/qa/20181216/16785.html [3]https://qiita.com/pebblip/items/1206f866980f2ff91e77 Der "akzeptabelste Typ" im Text bedeutet die "Obergrenze" in [3]. [4]https://java.keicode.com/lang/reflection.php [5] Der Punkt von Herrn saka1029 in diesem Artikel Andere: https://java-beginner.com/thread-thread-and-runnable/

Recommended Posts

[Java] Um die Typinformationen der Typparameter zur Laufzeit zu kennen
Ausgabe des Buches "Einführung in Java"
[Java] Achten Sie auf den Schlüsseltyp der Karte
Java Willkommen im Sumpf der zweidimensionalen Arrays
[Java] So erhalten Sie die URL der Übergangsquelle
Wie schreibe ich Scala aus der Perspektive von Java
[Java] So erhalten Sie den Maximalwert von HashMap
Ich möchte die Antwort der Janken-App wissen
Ich war süchtig nach getXxxx von ResultSet, weil es ein primitiver Typ ist (Java)
[Rails] So erhalten Sie den Inhalt starker Parameter
Java: Verwenden Sie Stream, um den Inhalt einer Sammlung zu sortieren
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
Kommen Sie zu den Abkürzungen aus den fünf Beispielen für kursive Java-Listen
20190803_Java & k8s on Azure Die Geschichte vom Festivalbesuch
Befehl zum Überprüfen der Anzahl und des Status von Java-Threads
So erhalten Sie die längsten Informationen von Twitter ab dem 12.12.2016
So leiten Sie den letzten Tag des Monats in Java ab
Die Geschichte, Java mithilfe der BitBucket-Pipeline nach Heroku zu bringen
Stellen Sie sicher, dass Sie das Java compareTo-Ergebnis mit 0 vergleichen
Wiedereinführung in Java for Humanities 0: Den Akt der Programmierung verstehen
Gibt an, ob die Serverseite zum Zeitpunkt der Systemwiederherstellung mit Kotlin oder Java erstellt werden soll
Eingabe in die Java-Konsole
Kennen Sie jetzt die Bequemlichkeit von Docker (-compose) (Informationsliste, auf die ich bei der Verwendung verwiesen habe)
[Java] Verschiedene Zusammenfassungen an die Leiter von Klassen und Mitgliedern
Untersuchen Sie die Systeminformationen der AWS Lambda-Betriebsumgebung in Java
Ich möchte den Ablauf der Spring-Verarbeitungsanforderungsparameter verstehen
Java Konvertiert unterschiedliche Zeichencodes gleichzeitig in denselben Zeichencode
Ich habe den Eingabe- / Ausgabetyp von Java Lambda ~ Map Edition ~ ausprobiert
Möchten Sie wissen, was Ruby n die Potenz von 2 ist? (Machturteil von 2)
Die in /lib/calendars.properties von Java jre festgelegte Millisekunde ist UTC
Vom jungen Java (3 Jahre) bis zu Node.js (4 Jahre). Und der Eindruck, nach Java zurückzukehren
Ich habe versucht, die Methoden von Java String und StringBuilder zusammenzufassen
[Java] So konvertieren Sie vom Typ String in den Pfadtyp und erhalten den Pfad
So überprüfen Sie den Inhalt der Java-Zeichenfolge mit fester Länge
So ermitteln Sie die Länge einer Audiodatei mit Java
So erhöhen Sie den Wert von Map in einer Zeile in Java
[Java] Löschen Sie die Elemente von List
[java8] Um die Stream-API zu verstehen
Kompilieren Sie Java an der Eingabeaufforderung
[Java Edition] Geschichte der Serialisierung
[Java] Laufzeitdatenbereiche von JVM
Willkommen im Sumpf der Java-Bibliotheken! !!
[Java] Korrekter Vergleich des String-Typs
Der Weg von JavaScript nach Java
Der Ursprung von Java-Lambda-Ausdrücken
Verwendung des Java-Aufzählungstyps
Java regulärer Ausdruck - kein Wissensverlust -
[Java] So rufen Sie die von HTML auf der Serverseite übergebenen Parameter ab
Die Geschichte, zu vergessen, eine Datei in Java zu schließen und zu scheitern
[Java Servlet] Die Straße von Senri ist auch ein Schritt zum ersten
Ich möchte die JSP des offenen Portlets bei der Entwicklung von Liferay kennen
Rufen Sie den Typ eines Elements eines Arrays ab, um festzustellen, ob es sich um ein Array handelt
So finden Sie heraus, welche Java-Version der Klassendatei kompiliert wurde
Grund, L zu der Zahl hinzuzufügen, die in den langen Java-Typ eingegeben werden soll
[Java] Wie man mit der String-Klasse an die Spitze eines bestimmten Strings kommt
So ermitteln Sie die Gesamtzahl der Seiten beim Paging in Java
So ändern Sie den Wert einer Variablen an einem Haltepunkt in IntelliJ
So ermitteln Sie den absoluten Pfad eines in Java ausgeführten Verzeichnisses
[Java-Verbesserungsfall] Wie man die Grenze des Selbststudiums und darüber hinaus erreicht