Czy java jest okaleczona? generic types

1

Hej,
przykro mi ale musze to z siebie wyrzucić.
Wpadł mi jakiś pomysł dzisiaj i myślałem że skrobnę go na szybko w javie.
Chce przy tym tworzyć tablice dwuwymiarowe w klasie *Grid *dla dowolnego typu danych, więc myślę sobie że użyje klasy template jak to się robi w c++.

public class Grid<T> extends GridObject<T> {
	private T[][] GridArray;
	@SuppressWarnings("unchecked")
	public Grid(short  width, short height     /*,GridType type*/){
		GridArray = (T[][]) new Object[width][height];//dirty workaround ^_-
	}
	public GridType getGridType() {
                T t;
		return gridType( t ) ; //ERR~!
	}

//np.
    private GridType gridType( boolean jestemkobietą) {
        return GridType.GRID_BOOLEAN;
    }
}
 

Okazuje się, że java nie pozwala na definiowanie tablic typu generic(T), nie pozwala też przekazywać typu generic do metod przyjmujących zdefiniowany typ(gridType()). Obeszłem te problemy i okazuje się że nie mogę stworzyć szablonu który jako parametr przyjmie typ prymitywny jak int! Mogę użyć Integer i wyjdzie na to samo, ale byte już nie przejdzie....

 
new Grid<boolean>(width,height); //no because fuck you.

Czy pozostaje mi klepać na twardo implementacje dla każdego typu tablicy metodą kopiegopasta, lub klepać wrappery dla każdego bitu, inta i shorta???2

PS nie chce używać gotowych implementacji.

0

Do każdego prymitywu masz wrappera, np do byte jest Byte. Niestety dla prymitywów wprost musiałbyś robić oddzielne klasy, bo żaden prymityw nie dziedziczy po Object, a wymazywanie typów w Javie konwertuje każdy typ generyczny do Object. Ewentualnie możesz użyć Scali i adnotacji @specialized :]

1

Ewentualnie możesz użyć Scali i adnotacji @specialized

Albo C# ;P

0

A C# nie utworzyłby tutaj kolekcji obiektów? Bo ZTCW to int oznacza w C# zarówno prymityw jak i wrappera i pakowanie/ rozpakowanie dzieje się automatycznie.
Np w tabicy Integerów w Javie można wynullować dowolną pozycję w tej tablicy.

1

Nie, w C# tablice intów (te generyczne też) to tablice intów. Jeżeli używamy indekserów przy dostępie do niej to boxing nigdy nie zajdzie. Z tego powodu poleca się stosowanie generycznych kontenerów i unikanie ArrayList.

0

Typy generyczne zostały wprowadzone w Javie daleko po tym gdy język został zaprojektowany. Stąd konieczne stało się wymazywanie typów w czasie wykonywania kodu (dla zgodności z istniejącym kodem - w tym wszystkimi bibliotekami Javy) oraz współpraca tylko z typami obiektowymi. Tak więc generyki istnieją głównie w czasie kompilacji. Z kolei tablice działają zupełnie odwrotnie - pilnują zgodności typów właśnie w czasie wykonywania kodu. Połączenie więc tablic z kodem szablonowym jest ekwilibrystyką. Z drugiej strony wszystkie kontenery obiektowe (a te głównie potrzebują kodu szablonów) mogą dobrze współdziałać z szablonami i to je należy wykorzystywać w takim kodzie zamiast tablic. A to, że same kontenery obiektowe są wewnętrznie zbudowane na tablicach, to tylko szczegół, który powoduje ból głowy tylko twórców tych kontenerów. Generalnie jeżeli potrzeba zmusić do działania tablice w szablonach, to trzeba je deklarować jako Object[], a następnie rzutować do właściwego typu elementów. Warto sobie w konkretnych przypadkach wewnątrz obiektu zdefiniować prywatną metodę cast, która będzie miała osłabione sprawdzanie typów i wtedy będzie to jedyne takie miejsce, gdzie może w ogóle pojawić się ostrzeżenie o braku kontroli typów.
Kilka przykładów użycia z rzeczywistego kodu:

	private /*Bucket<K, V>*/ Object[] table;
	//...
	private /*Bucket<K, V>*/ Object[] newTable;
	//...
	@SuppressWarnings("unchecked")
	private Bucket<K, V> cast(Object bucket)
	{
		return (Bucket<K, V>) bucket; //jedyne miejsce z osłabionym sprawdzaniem typów
	}
	//...
	newTable = new Object[newSize];
	//...
	final Bucket<K,V> oldBucket = cast(table[oldAddress]);
	//...
	Bucket<K, V> newBucket = cast(newTable[newAddress]);
	//...
	newTable[newAddress] = new Bucket<>();
	//...
	newBucket = cast(newTable[newAddress]);
	//...
	newBucket.add(pair);

Sama metoda cast zostanie przez kompilator potraktowana jako inline, więc wywołań nie będzie, a ponieważ jedyne co ona robi w kodzie wykonywalnym, to trywialne rzutowanie Object->Object (po wymazaniu typu), więc zostanie ono w praktyce pominięte i z wywołania cast() nie zostanie zupełnie nic.

0

Czyli jest jakaś kolekcja w C#, która pozwala na trzymanie nulli i intów? Jak rozróżnić genericsami w C#, że jakaś kolekcja przyjmuje nulle albo nie, np chcę zrobić metodę dla kolekcji, które przyjmują nulle, co zrobić?

1
Wibowit napisał(a):

Czyli jest jakaś kolekcja w C#, która pozwala na trzymanie nulli i intów? Jak rozróżnić genericsami w C#, że jakaś kolekcja przyjmuje nulle albo nie, np chcę zrobić metodę dla kolekcji, które przyjmują nulle, co zrobić?

Użyć Nullable<int> - w skrócie składniowym: int?

0

Tak jak kolega @Olamagato napisał :

Typy generyczne zostały wprowadzone w Javie daleko po tym gdy język został zaprojektowany. Stąd konieczne stało się wymazywanie typów w czasie wykonywania kodu (dla zgodności z istniejącym kodem - w tym wszystkimi bibliotekami Javy) oraz współpraca tylko z typami obiektowymi. Tak więc generyki istnieją głównie w czasie kompilacji.

Bardzo lubię pisać w Javie i jak dla mnie osobiście jest to największe "kalectwo" Javy. Szkoda, że twórcy od początku nie dodali generyków, no i może przeładowania operatorów :P.... ehh marzenia :)
Natomiast na 2 miejscu stawiam ograniczenia definiowania i używania annotacji.

Swoją drogą ciekawe jak jest w C#. Słyszałem opinię, że twórcy tego języka wzorowali się na Javie i stworzyli taką "Jave bez tego co w javie jest nieudane" .

0

Przede wszystkim, gdyby stworzyli klona Javy, który byłby tak samo ułomny, to by rynku w ogóle nie zawojowali. Poza tym Java w momencie wejścia C# 2.0 na rynek (C# 1.x ZTCW nie miały wielu zalet nad Javą i nie były popularne) miała już ogromną ilość bibliotek i krowiastych systemów klasy enterprise. ZTCW C# 2.0 wniósł spore zmiany, tzn niekompatybilne genericsy, a twórcy Javy cały czas mają na uwadze kompatybilność wsteczną - nawet lambdy w Javie 8 mają być kompatybilne wstecznie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1