Datentypen Generische Collections und Warnings

Die4Me

Mitglied
Hey,
ich bin gerade ein bisschen verwirrt. Ich habe vor eine generische Collection zu bauen und bin dort auf eine Sach gestoßen, welche ich nicht so wirklich kapiere. Wenn ich mir die ArrayList, den Vector oder die HashMap anschaue, dann werden die Elemente in einem Object-Array, bzw Entry-Array gehalten, welches ja nicht generisch ist. Fragt man dann die Elemente ab, wird gecastet und es kommt mit dem richtigen Typen raus. So wie alles sein sollte. Programmiere ich nun ähnlich, bekomme ich eine Warnung. "Unchecked cast from Object to E". Ich hänge mal kurz ein kleines Bsp ran.
Java:
public class MeineCollection< E > {

	private Object[] elementData;
	
	private int count;

	public MeineCollection() {
		elementData = new Object[ 10 ];
		count = 0;
	}
	
	public boolean add( E value ) {
		elementData[ count++ ] = value;
		return true;
	}

	public E get( int index ) {
		return ( E ) elementData[ index ];
	}

}
Das ist ja so im Grunde genommen das gleiche, was bei den genannten Collections auch passiert.
Warum bekomme ich dort eine Warnung? Kann man diese umgehen (nicht unterdrücken)? Und wenn ja wie? Oder ist diese Warnung wirklich nur mit @SuppressWarnings( "unchecked" ) zu "beheben"?
Ich weiß, dass man sich auch ein generisches Array mit
Java:
( E[] ) Array.newInstance( componentType, size );
erstellen kann. Aber das muss ich ja auch wieder mit @SuppressWarnings( "unchecked" ) unterdrücken.
Ich bin in dem Sinne gerade echt verwirrt und würde mich freuen, wenn ihr mir helfen könntet ein bisschen Licht ins dunkel zu bringen ^^

mfg
die4me
 
Das ist in Ordnung und richtig so, wie Du es machst, aber leider kann man die Warnung lediglich unterdrücken.

Der Übersetzer geht in Zeile 18 sturr davon aus, daß sich in elementData irgendwelche Objekte wie String oder Data befinden, und die dürfte man selbstverständlich nicht einfach in E umwandeln. Du als Klassenentwickler weißt an dieser Stelle mehr, nämlich daß ausschließlich Objekte vom Typ E in elementData gespeichert werden können, denn alles andere verbietet die Schnittstelle add(E value).

> Aber das muss ich ja auch wieder mit @SuppressWarnings( "unchecked" ) unterdrücken.
Beim Übersetzen werden die Typinformationen gelöscht, E ist nicht mehr bekannt. Der Übersetzer kann daher nie prüfen, ob die Typen richtig sind, und darauf möchte er Dich hinweisen. Da die Informationen nicht zur Verfügung stehen, kannst Du das aber auch nicht prüfen – es geht nur, indem man die Warnung unterdrückt.

AngelikaLanger.com - Java Generics - Type Erasure and Raw Types - Angelika Langer Training/Consulting
 
Zuletzt bearbeitet:
Gut. Das ich mehr weiß ist schön und so langsam steig ich auch dahinter. Außerdem sind Warnungen ja keine Fehler und man muss das nur ein bisschen absichern.
Ich hab nun mal ein bisschen im Quellcode von Java rum geschnüffelt. Ich nehme mal einen Auszug aus der ArrayList, wie es dort steht. Da dort nen Copyright steht, mach ich das nun mal nicht. Aber bei jedem SDK sind ja auch die Sourcen dabei und man kann mal schnell rein schauen. Wie machen das die Java Entwickler? Nehmen diese die Warnungen in kauf, oder übersetzten die mit
Code:
javac -Xlint:-unchecked
Denn ich habe dort im Quellcode kein @SuppressWarnings( "unchecked" ) gefunden.
Auch wenn sich das nun naiv anhört, aber ich mag keine Warnungen! 😀
mfg
die4me

[Edit]
Des weiteren habe ich eine Klasse, welche Generische Typen enthält. Wie bilde ich nun daraus ein Array?
[Java]public class MeineCollection< E > {

private Entry<E>[] elementData;

public MeineCollection() {
elementData = new Entry[ 10 ];
}

}[/Java]Lasse ich bei der Deklaration den Typ-Parameter weg, oder initialisiere ich und Caste dann mit Typparameter oder wie macht man das am besten konform? Oder habe ich wirklich nur ein Object und Caste dann jeweils beim get so wie ich das ja in dem Beispiel davor gemacht habe?
 
Zuletzt bearbeitet:
Was mir nun auch mal aufgefallen ist nachdem ich den Artikel ein bisschen sacken lassen hab. Folgendes Beispiel..
[Java]public class Beispiel< E > {

private E[] meinArray;

public Beispiel( Class< E > componentType, int length ) {
this.meinArray = ( E[] ) Array.newInstance( componentType, buffersize );
}

}[/Java]Durch Class< E > ist doch eigentlich auch gesichert, dass kein anderes Class-Objekt übergeben werden kann, wie ich möchte. Jedoch bekomme ich dort auch eine Warnung.
[Java]public static main( String[] args ) {
Beispiel< Integer > bsp1 = new Beispiel< Integer >( String.class, 10 ); // Schlägt fehl
Beispiel< Integer > bsp2 = new Beispiel< Integer >( Integer.class, 10 ); // Das geht dann
}[/Java]Dort ist doch gesichert, dass nur ein Class< Integer > übergeben werden kann, oder übersehe ich dort was?
 
Zuletzt bearbeitet:
Die Typinformationen werden beim Compilieren gelöscht - deshalb warnt der Compiler davor.
Bei Generics kann man nicht alle Warnungen beseitigen, einige "muss" man unterdrücken.

Zum Warnungen unterdrücken:
Immer so kleine Bereiche wie möglich unterdrücken. Am besten immer nur die Zeile selbst (ggf. die Zeile in eine Hilfsmethode auslagern und die Warnung in dieser Hilfsmethode unterdrücken). Denn es gibt Warnungen, die man beheben kann und sollte, und beim Unterdrücken über einem großen Bereich übersieht man diese evtl.

Noch ein paar generelle Tipps zum Thema Generics und warum man z.B. auch keine Arrays von Generics erstellen kann:
http://java.sun.com/docs/books/effective/generics.pdf
 
Danke an euch beide für eure konstruktiven Beiträge. Der erste Link von Wortraum hat mir schon mal sehr gut gefallen und ich denke auf der Seite gibt es noch mehr lesenswertes zu Generics und vielen anderen Sachen.
Zu dieser Sache muss ich ganz ehrlich sagen, dass ich mir das auf Garantie auch noch mal zu Gemüt führe. Jedoch sind 36 Seiten erst ein mal ganz schön viel um mal schnell drüber zu schauen.
Aber es ist gespeichert und ich werde es mit garantiert noch mal anschauen.
Um nun aber zu einem Ende zu kommen und mal einen Weg zu Zeigen wie ich mir das nun mal gedacht habe. (In Anlehnung an)
Immer so kleine Bereiche wie möglich unterdrücken. Am besten immer nur die Zeile selbst (ggf. die Zeile in eine Hilfsmethode auslagern und die Warnung in dieser Hilfsmethode unterdrücken). Denn es gibt Warnungen, die man beheben kann und sollte, und beim Unterdrücken über einem großen Bereich übersieht man diese evtl.
Dort habe ich mir nun folgendes gedacht..
Java:
public class ObjectExtentions {

	private ObjectExtentions() {
	}

	@SuppressWarnings("unchecked")
	public static < E > E castTo( Object o ) {
		return ( E ) o;
	}

}
Java:
import static ObjectExtentions.castTo;
public class Beispiel< E > {
 
    private E[] meinArray;
 
    public Beispiel( Class< E > componentType, int length ) {
        this.meinArray = castTo( Array.newInstance( componentType, buffersize ) );
    }
 
}
Somit wird ja dann in einem kleinen Block dieser Cast durchgeführt. Ich habe den Vorteil, das ich nicht andauernd dieses unchecked unterdrücken muss und es ist trotzdem noch dynamisch um es auch an anderen Stellen einzusetzen. Ich hoffe mal, das die Einheit wo es zu einem falschen Cast kommen könnte so weit wie möglich runter gebrochen habe. Sollte ich dort irgendwas falsch machen oder dies ist zu unsicher, sinnlos, oder was auch immer... Dann schreibt mir bitte. Aber wie gesagt, ich möchte nicht über jede dritte Methode ein SupressWarnings( "unchecked" ) drüber schreiben.
Also, danke noch mal an euch beide.

mfg
die4me
 
Eigentlich hab ich das ja schon und ich hab sogar schon angefangen das zu lesen. Aber nun werde ich mich mal wirklich dahinter setzen. Naja... Ein bisschen Spaß muss ja sein.
Aber wie ich oben schon mal geschrieben habe, ist das nun eine Lösung, welche mir eben mal so in den Sinn gekommen ist und ich wollte diese mit euch teilen. Wenn die Lösung falscher als Falsch ist, dann werde ich das auch gleich wieder raus nehmen. Denn es ist ja nicht von Vorteil falsche Sachen zu sehen...
Also, ich würde es dann nun erst einmal abhacken und mich dann mal weiterhin mit dem PDF beschäftigen.
 

Zurück
Oben