Wildcard und class type

Hallo zusammen,

ich möchte mir eine Klasse bereitstellen, die das speichern und laden von JSON - Dateien vereinfacht.

Beim Laden aus einer JSON Datei muss ich jedoch den Type der Klasse
Java:
Class<?> classOfT
angeben, damit dieses auch deserialisiert werden kann.

Aktueller Stand der Klasse

Java:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import com.google.gson.Gson;

public class GsonObjectReader<T> {

    private final String path;
    
    public GsonObjectReader(final String path) {
        this.path = path;
    }
    
    public T read(Class<T> classId) {
        T t = null;
        
        try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
            
            t = (T) new Gson().fromJson(reader, classId);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return t;
    }
}

Nur stört mich an dieser Stelle, dass ich in der Methode
Java:
read(...)
noch extra die
Java:
Class<T>
mitgeben muss, damit die Methode
Java:
fromJson
passend aufgerufen werden kann.


Meine Frage
Gibt es eine Möglichkeit, den Parameter, den ich der Methode read als Parameter mitgeben, über den Wildcard Type T zu bekommen, oder ist das so, wie ich es mir vorstelle nicht möglich?
 

httpdigest

Top Contributor
Es geht nicht direkt, allerdings kannst du einen beliebten Trick anwenden, indem du deine `GsonObjectReader` Klasse als abstract markieren und vom Nutzer/Client mit einem konkreten Typargument ableiten lässt. Das macht aus der Klasse, die der Nutzer verwendet, eine konkrete Typdeklaration und bei abgeleiteten Klassen wird das Typargument erhalten:
Java:
public abstract class GsonObjectReader<T> {
  private final String path;
  protected GsonObjectReader(String path) {
    this.path = path;
  }
  public final T read() {
    Class<?> clazz = myClass();
    // Nutze clazz hier...
  }
  private Class<?> myClass() {
    ParameterizedType t = (ParameterizedType) getClass().getGenericSuperclass();
    Class<?> clazz = (Class<?>) t.getActualTypeArguments()[0];
    return clazz;
  }
}
Nutzung ist dann:
Java:
new GsonObjectReader<MyClass>("./pfad/der/datei.json"){}.read();
Beachte die geschweiften Klammern hier, die daraus eine anonyme Klasse machen, die sofort instanziiert wird und auf deren Instanz wir dann read() aufrufen!

Das ist übrigens dasselbe Konzept wie bei "Type Tokens": https://www.baeldung.com/java-super-type-tokens
 
Zuletzt bearbeitet:

httpdigest

Top Contributor
Wozu die Klasse abstract halten? Sehe dafür ehrlich gesagt keinen Grund.
Das dient nur dazu, dass die Klasse selbst nicht instanziiert werden kann, weil die Lösung ansonsten nicht funktioniert.
Die Klasse ohne Subclassing selbst zu instanziieren, erlaubt es eben nicht, das Typargument zu behalten, da Typargumente nur bei Typdeklarationen gespeichert werden. Wir brauchen also die Klasse als Superklasse einer anderen vom Benutzer definierten Klasse mit Typargument.
Das ist der ganze Punkte der Type Tokens Lösung. Hast du dir die Lösung und insbesondere die Methode `myClass()` darin mal angeguckt? Dort wird auf den generischen Supertyp zugegriffen, um sein Typargument zu bekommen.
 

X5-599

Top Contributor
Das ergibt keinen Sinn. Der einzige Unterschied ist, dass bei deiner Lösung die zusätzlichen "{}" geschrieben werden müssen beim Instanziieren da "abstract". Eine einfache Klasse mit Generic Angabe würde genauso funktionieren:

Code:
public class Testing<T>
{
	private String path;
	
	public Testing(String path)
	{
		this.path = path;
	}
	
	public T read()
	{
		ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
	    Class<?> clazz = (Class<?>) type.getActualTypeArguments()[0];
	    
	    T t = null;
        
        try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
            
            t = (T) new Gson().fromJson(reader, clazz);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return t;
	}
	
	public static void main(String[] args)
	{
		new Testing<Devices>("path/to/json").read();
	}
}
 

httpdigest

Top Contributor
Und genau das (also ohne explizite Subklasse) funktioniert eben nicht, wie @mihe7 oben schon geschrieben hat, da hier per Type Erasure die Generics Typparameter und die Typargumente bei der Instanziierung verschwinden.
Deine Lösung funktioniert alleine deswegen schon nicht, weil du jetzt ja auch auf getGenericSuperclass() zugreifst, wo es gar keine generic Superclass (nämlich nur java.lang.Object) mehr gibt.
Der alleinige Grund, warum bei meiner Lösung die geschweiften Klammern stehen, ist der, dass wir eine Typdeklaration (in diesem Fall eine anonyme Klasse) brauchen, um die Typargumente zu behalten!
Ich empfehle dir sehr, dir nochmal die verlinkte Seite zu "Super Type Tokens" durchzulesen.
 

httpdigest

Top Contributor
Vielleicht nochmal deutlicher zur Veranschauung:
Das hier:
Java:
new Testing<Devices>("path/to/json");
ist eine Typinstanziierung, bei der sämtliche Typargumente aus dem Bytecode unwiederbringlich verschwinden.

Das hier:
Java:
new Testing<Devices>("path/to/json"){};
sind zwei Dinge:
1. eine Typdeklaration (eine anonyme Klasse, die von Testing<Devices> (per Typargument) ableitet)
2. eine Typinstanziierung (nämlich von dieser anonymen Klassen)
Der Punkt ist, dass die Typdeklaration eben sehr wohl das Typargument im Bytecode behält, weil es eine Klassendeklaration ist und im Bytecode die Typargumente, mit denen generische Supertypen abgeleitet werden, drin stehen bleiben und per Reflection abfragbar sind.
 
Hat mir auch sehr weitergeholfen. Wirklich sehr interessant, wie gut es veranschaulicht wurde.

Bin selbst noch nicht ganz so tief in Generics, Wildcards u.ä. Themen vertieft. Wirkt also für mich immer noch etwas exotisch. Wird aber mit der Zeit sicherlich werden.

Danke noch einmal an jeden hier im Thread für die guten Tipps, Tricks und Ratschläge.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
darekkay Generics: Wildcard und Object Allgemeine Java-Themen 5
V Wildcard aus Parameter in return type Allgemeine Java-Themen 2
O Text mit Wildcard gegen regulären Ausdruck prüfen Allgemeine Java-Themen 3
M Datei auswählen mit Wildcard Allgemeine Java-Themen 11
V String in String suchen mit Wildcard? Allgemeine Java-Themen 8
H Frage zu Wildcard Eingabe in Java! Allgemeine Java-Themen 5
D NoClassDefFoundError: Could not initialize class Allgemeine Java-Themen 0
J Class to link Java Allgemeine Java-Themen 4
C Was passt hier nicht bei der Calendar-Class Allgemeine Java-Themen 2
E Class.getResourceAsStream() gibt null zurück Allgemeine Java-Themen 2
Erwin82a Object cannot be converted to Custom Class in Lampda Expression Allgemeine Java-Themen 2
T Java Robot Class - Bot Allgemeine Java-Themen 3
S Class File Editor -> Source not found Allgemeine Java-Themen 4
G javafx "class path" exception Allgemeine Java-Themen 5
S Java class direved from inner class Allgemeine Java-Themen 6
S Inner Class Allgemeine Java-Themen 11
M Java model class ? Allgemeine Java-Themen 9
Thallius Ist meine static Helper Class Thread save? Allgemeine Java-Themen 9
S class path resource [config.properties}] cannot be opened because it does not exist Allgemeine Java-Themen 4
J Reflection Aufruf: .class durch .dll ersetzen Allgemeine Java-Themen 4
T Compiler-Fehler NoClassDefFoundError beim Laden einer Class Allgemeine Java-Themen 11
J Class Decompile als String (Procyon) Allgemeine Java-Themen 2
H Class 'java.io.BuferedReader' is not present in JRE Emulation Libary | GWT Fehler?! Allgemeine Java-Themen 0
I Datentypen String in class sicher verwahren Allgemeine Java-Themen 17
R Dynimc Class Loading Allgemeine Java-Themen 5
J Inner class + Leer-Konstruktor Allgemeine Java-Themen 1
Neumi5694 Methoden Generic: Rückgabetyp als Class-Parameter übergeben Allgemeine Java-Themen 3
D Collections.sort funktioniert nicht in exportierten .class Dateien Allgemeine Java-Themen 10
V Eclipse .class Dateien Allgemeine Java-Themen 9
KeexZDeveoper Von .class zu .java Allgemeine Java-Themen 7
N Wo ist Object.class ? Allgemeine Java-Themen 0
K Nicht alle class-Dateien im JRE? Allgemeine Java-Themen 2
M *.class Files ausführen Allgemeine Java-Themen 2
L Klassen Nested Class In Nested Class Allgemeine Java-Themen 3
perlenfischer1984 Dialect class not found exception Allgemeine Java-Themen 15
Tort-E Manifest Main-Class Allgemeine Java-Themen 8
I JSoup Class auslesen Allgemeine Java-Themen 1
K Generic class und Reflection Allgemeine Java-Themen 2
R .class Datei in .jar austauschen Allgemeine Java-Themen 2
R Java .class-File-Konstrunkt mit Programm visualisieren Allgemeine Java-Themen 18
A main-class Not found Allgemeine Java-Themen 3
T Java Class Intrumentation mit Annotations in Laufzeit Allgemeine Java-Themen 1
N Per Reflection auf (method) local inner class zugreifen? Allgemeine Java-Themen 3
P JDK installieren Error: Could not find or load main class HelloWorld.java Allgemeine Java-Themen 3
B public class JarFilter extends FileFilter « Falsch? Allgemeine Java-Themen 4
D Object nach Vererbung mit Class Object überprüfen Allgemeine Java-Themen 4
T Hash von *.class-Datein überprüfen Allgemeine Java-Themen 1
F java.lang.ClassNotFoundException: .class Allgemeine Java-Themen 5
T InvalidClassException - Read null attempting to read class descriptor for object Allgemeine Java-Themen 8
Phash Can't find Main Class Allgemeine Java-Themen 4
B Erste Schritte Plugin erkennen und Class Dateien anzeigen lassen Allgemeine Java-Themen 3
B json zu java class Allgemeine Java-Themen 2
antonbracke Aus Jar eine Class laden und damit arbeiten! Allgemeine Java-Themen 5
D Class<CAP#1> statt Class<...> Allgemeine Java-Themen 5
T Class-Objekt mit URLClassloader Allgemeine Java-Themen 7
A Class Datei aus Verzeichnis über URLClassLoader laden Allgemeine Java-Themen 2
L Class Files , Methode .delete() Allgemeine Java-Themen 13
E NetBeans warning: [options] bootstrap class path not set in conjunction with -source 1.6 Allgemeine Java-Themen 4
X Could not find the main class programm will exit (textdokument) Allgemeine Java-Themen 3
S Could not find the main class Allgemeine Java-Themen 7
B Mal wieder "Could not find the main class" Allgemeine Java-Themen 3
B Variable class in java.lang.Object Allgemeine Java-Themen 11
C Could not find the main class. Allgemeine Java-Themen 15
S Klassen .jar - eine .class datei ändern? Allgemeine Java-Themen 23
A Could not find main class: start Allgemeine Java-Themen 5
S main() class finden Allgemeine Java-Themen 7
hdi Could not find main class? Allgemeine Java-Themen 8
R Warum Class.forName(); Allgemeine Java-Themen 7
C class.class angefordert ? Allgemeine Java-Themen 2
S Methoden Class.forName() >> Methoden - Reihenfolge Allgemeine Java-Themen 5
B Test$1.class mit dem javac compiler Allgemeine Java-Themen 7
G jar Datei findet Main Class nicht... Allgemeine Java-Themen 2
P Java Editor Could not find the main class GUI. Programm will exit. Allgemeine Java-Themen 3
D class Datei einlesen Allgemeine Java-Themen 4
T Interface > Abstract > Class Allgemeine Java-Themen 11
TheDarkRose Subversion .class Dateien auch commiten? Allgemeine Java-Themen 3
D API - Beispiel + static member in inner (non static) class Allgemeine Java-Themen 2
E String name in class convertieren Allgemeine Java-Themen 4
F Änderung in .jar bzw. .class vornehmen ? Allgemeine Java-Themen 18
H2SO3- bestimmte class immer mit 1.4 compilieren Allgemeine Java-Themen 5
B class dateien "einlesen" und objekte erzeugen Allgemeine Java-Themen 6
G Unterschied MyClass.class vs this Allgemeine Java-Themen 2
S mit Class eine Klasse nur einmal instantiieren Allgemeine Java-Themen 4
Sonecc Zugriff auf Class File einer anderen Jar während der Laufzeit Allgemeine Java-Themen 2
M Klasse aus xyz.class Datei laden / package entfernen? Allgemeine Java-Themen 4
BattleMaster246 Could not find the Main class Allgemeine Java-Themen 30
N class Task extends TimerTask ohne Blockieren Allgemeine Java-Themen 15
H .class in .java umwandeln Allgemeine Java-Themen 3
T class.newinstance + try/catch-konstruktor Allgemeine Java-Themen 6
X Cannot refer to a non-final variable settings inside an inner class defined in a different method Allgemeine Java-Themen 4
J Class.forName und CLASSPATH -Problem Allgemeine Java-Themen 5
T Class-files zur Laufzeit zu Reflection-Zwecken laden Allgemeine Java-Themen 18
G Thread in Methode oder in inner class Allgemeine Java-Themen 3
woezelmann referenz der outer class aus static nested class heraus Allgemeine Java-Themen 7
reibi Main-Class in Jarfile Allgemeine Java-Themen 3
E Timer class macht einfach garnichts :/ Allgemeine Java-Themen 6
D Class.forName Allgemeine Java-Themen 2
S Class RGB Farbe Allgemeine Java-Themen 2
S JavaDoc aus .class Datei extrahieren Allgemeine Java-Themen 5
mongole Class.class.getResource(...) Allgemeine Java-Themen 10

Ähnliche Java Themen

Neue Themen


Oben