3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
1/12
Typy generyczne w języku Java
Dzień dobry! Nadszedł czas na poznanie typów generycznych. Dowiesz się o
“szablonach” w języku Java, które pozwalają na tworzenie bardziej uniwersalnych
typów. Jest to wstęp, który pozwoli Ci dobrze zrozumieć kluczowy aspekt
standardowych kolekcji (“tablic na sterydach”) w języku Java. Każdy programista Javy
musi znać typy generyczne :) Zapraszam do artykułu!
(https://www.flickr.com/photos/huntingglee/2222875354)
(http://www.samouczekprogramisty.pl/)
/ Typy generyczne w języku Java
Samouczkowy newsletter
To jest jeden z artykułów w ramach
darmowego kursu programowania w Javie
(http://www.samouczekprogramisty.pl/kurs-programowania-java)
. Proszę zapoznaj się z pozostałymi częściami,
mogą one być pomocne w zrozumieniu materiału z tego artykułu.
Czym są typy generyczne
W uproszczeniu można powiedzieć, że typy generyczne są “szablonami”. Dzięki typom generycznym możemy uniknąć niepotrzebnego
rzutowania. Ponadto przy ich pomocy kompilator jest w stanie sprawdzić poprawność typów na etapie kompilacji, oznacza to więcej błędów
wykrytych w jej trakcie .
Poza tym dzięki typom generycznym możemy konstruować bardziej złożone klasy, które możemy używać w wielu kontekstach, łatwiej
będzie Ci to zrozumieć na przykładzie.
Porównanie typów generycznych i standardowych
Znasz już zwykłe klasy i interfejsy, zostały one omówione we wcześniejszych artykułach. Klasy mają swoje atrybuty, których typy znasz
pisząc program.
1 znajomy lubi to
1481 polubienia
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
2/12
W przykładzie powyżej klasa
AppleBox
“wie” jakiego typu obiekt może przechowywać, jest to obiekt typu
Apple
. A co jeśli chcielibyśmy
zrobić analogiczną klasę dla owoców innego rodzaju? Oczywiście możemy stworzyć podobne pudełko jak w przykładzie poniżej:
Oba przykłady są jak najbardziej poprawne jednak występuje w nich duplikacja. Te same elementy, konstrukcje powielane są wielokrotnie.
Duplikacja w kodzie generalnie jest złą praktyką, należy jej unikać. Możemy zatem stworzyć kolejną klasę:
Z racji tego, że atrybut
fruit
jest typu
Object
możemy do niego przypisać zarówno instancję klasy
Orange
jak i
Apple
. Pojawia się jednak
pewien problem. Mianowicie jeśli chcemy pobrać atrybut
fruit
i przypisać go do zmiennej odpowiedniego typu musimy rzutować. Tego
typu konstrukcja może powodować błędy podczas wykonania programu i warto jej unikać. Z pomocą przychodzą typy generyczne. Proszę
spójrz na przykład poniżej.
public
class
Apple
{
}
public
class
AppleBox
{
private
Apple apple
;
public
AppleBox
(
Apple apple
)
{
this
.
apple
=
apple
;
}
public
Apple
getApple
()
{
return
apple
;
}
}
public
class
Orange
{
}
public
class
OrangeBox
{
private
Orange orange
;
public
OrangeBox
(
Orange orange
)
{
this
.
orange
=
orange
;
}
public
Orange
getOrange
()
{
return
orange
;
}
}
public
class
FruitBox
{
private
Object fruit
;
public
FruitBox
(
Object fruit
)
{
this
.
fruit
=
fruit
;
}
public
Object
getFruit
()
{
return
fruit
;
}
}
public
class
Main
{
public
static
void
main
(
String
[]
args
)
{
FruitBox fruitBox
=
new
FruitBox
(
new
Orange
());
Orange fruit1
=
(
Orange
)
fruitBox
.
getFruit
();
}
}
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
3/12
public class BoxOnSteroids<T>
to nic innego jak pierwsza linijka definicji klasy. Nowa tutaj jest konstrukcja z nawiasami. Oznacza ona
właśnie typ generyczny, który możemy parametryzować innym typem. Typ ten dostaje tymczasową nazwę, w tym przypadku
T
, której
używamy dalej w ciele klasy.
W trakcie tworzenia instancji obiektu
BoxOnSteroids
podajemy informację o typie, który chcielibyśmy wstawić w miejsce
T
. W naszym
przykładzie są to klasy
Apple
lub
Orange
. Dzięki takiej konstrukcji kompilator dokładnie wie jakiego typu obiekt zostanie zwrócony przez
metodę
getFruit
w związku z tym rzutowanie nie jest konieczne .
Klasy generyczne i parametryzowanie
Wspomniałem wcześniej, że klasy generyczne są szablonami dla nowych klas. W uproszczeniu można powiedzieć, że parametry klasy
generycznej są elementami uzupełnianymi w szablonie.
Spróbuję opisać to bardziej obrazowo. Szablon to foremka do wycinania ciastek. Tej foremki możemy użyć do wycięcia wielu ciastek. Każde
z nich możemy ozdobić w inny sposób. To w jaki sposób ciastko jest ozdobione jest parametrem tego szablonu:
Definicja klasy generycznej
Klasę generyczną definiujemy w następujący sposób
Zauważ, że w nawiasach
<>
możemy umieścić więcej niż jeden parametr. Chociaż zgodnie ze specyfikacją języka Java możesz użyć
dowolnej nazwy która nadaje się na nazwę zmiennej istnieje konwencja nazewnicza sugerująca nazwy parametrów. Zwyczajowo do tego
celu używa się wielkich liter
T
,
K
,
U
,
V
,
E
.
W miejsce parametrów możemy wstawić dowolny obiekt, nie może to jednak być typ prosty. Innymi słowy
Integer
jest w porządku,
int
powoduje błąd.
Instancja klasy generycznej
Skoro już wiemy jak zdefiniować klasę generyczną przydałoby się stworzyć jej instancję, żeby w końcu jej użyć :). Linijka poniżej tworzy
instancję klasy generycznej
BoxOnSteroids
, która parametryzowana jest typem
Orange
.
public
class
BoxOnSteroids
<
T
>
{
public
T fruit
;
public
BoxOnSteroids
(
T fruit
)
{
this
.
fruit
=
fruit
;
}
public
T
getFruit
()
{
return
fruit
;
}
}
public
class
Main
{
public
static
void
main
(
String
[]
args
)
{
BoxOnSteroids
<
Apple
>
appleBox
=
new
BoxOnSteroids
<
Apple
>(
new
Apple
());
BoxOnSteroids
<
Orange
>
orangeBox
=
new
BoxOnSteroids
<
Orange
>(
new
Orange
());
Orange fruit
=
orangeBox
.
getFruit
();
}
}
public
class
CookieCutter
<
T
>
{
private
T glaze
;
}
class
Name
<
T1
,
T2
,
...,
Tn
>
{
/* body */
}
BoxOnSteroids
<
Orange
>
orangeBox
=
new
BoxOnSteroids
<
Orange
>(
new
Orange
());
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
4/12
Zauważ, że i tutaj występuje pewna duplikacja. Zarówno przy określaniu typu zmiennej jak i przy wywołaniu konstruktora powtarzamy klasę
Orange
. Nie jest to konieczne. Jeśli kompilator jest w stanie “wywnioskować” jaki typ powinien być użyty możemy go pominąć przy
konstruktorze.
Zagnieżdżone typy generyczne
Możesz też tworzyć instancje typów generycznych, które są bardziej skomplikowane. Przykład poniżej pokazuje klasę
Pair
, która
parametryzowana jest dwoma innymi typami.
Java pozwala na to aby tworząc instancję typu generycznego parametryzować go innym typem generycznym. Brzmi to skomplikowanie,
mam nadzieję, że przykład pomoże Ci to zrozumieć:
W przykładzie tym tworzony jest obiekt klasy
Pair
, który parametryzowany jest klasami
BoxOnSteroids<Orange>
i
BoxOnSteroids<Apple>
.
Typy generyczne nie rozwiązują wszystkich problemów
Typy generyczne zostały wprowadzone w wersji Javy 1.5. Nie były dostępne od początku jej istnienia. Zatem istnieją sytuacje, w których
nawet ich stosowanie może prowadzić do wystąpienia błędów w trakcie wykonywania programu. Proszę spójrz na przykład poniżej:
W przykładzie tym tworzona jest instancja klasy generycznej
BoxOnSteroids
bez wyspecyfikowania klasy, która znajduje się “w środku”.
Następnie tę instancję przypisujemy do zmiennych typu
BoxOnSteroids<Apple>
i
BoxOnSteroids<Orange>
. O ile w pierwszym przypadku typ
owocu trzymanego w środku się zgadza to ostatnia linia nie jest poprawna – generuje błąd typu
ClassCastException
. Obiekt typu
Apple
jest
rzutowany przez kompilator do typu
.
Słowo kluczowe
extends
To słowo kluczowe ma zastosowanie także w przypadku typów generycznych. Dzięki niemu możemy ograniczyć zestaw klas którymi
możemy parametryzować nasz typ generyczny. Omówmy to na przykładzie:
BoxOnSteroids
<
Orange
>
orangeBox
=
new
BoxOnSteroids
<>(
new
Orange
());
public
class
Pair
<
T
,
S
>
{
private
T first
;
private
S second
;
public
Pair
(
T first
,
S second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
T
getFirst
()
{
return
first
;
}
public
S
getSecond
()
{
return
second
;
}
}
Pair
<
BoxOnSteroids
<
Orange
>,
BoxOnSteroids
<
Apple
>>
pairOfBoxes
=
new
Pair
<>(
new
BoxOnSteroids
<>(
new
Orange
()),
new
BoxOnSteroids
<>(
new
Apple
())
);
BoxOnSteroids boxWithoutType
=
new
BoxOnSteroids
(
new
Apple
());
BoxOnSteroids
<
Apple
>
boxWithApple
=
boxWithoutType
;
BoxOnSteroids
<
Orange
>
boxWithOrange
=
boxWithoutType
;
Apple apple
=
boxWithApple
.
getFruit
();
Orange orange
=
boxWithOrange
.
getFruit
();
// ClassCastException
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
5/12
Jak widzisz przykład definiuje prosty interfejs
Figure
i klasę
Circle
, która go implementuje. Następnie definiujemy klasę
BoxForFigures
,
która jest generyczna i może być parametryzowana przez typy dziedziczące/implementujące
Figure
.
Dzięki takiemu zapisowi kompilator pozwoli nam stworzyć instancję
BoxForFigures<Circle> circleBox
jednak zacznie się buntować przy
BoxForFigures<Apple> appleBox
(
Apple
nie implementuje interfejsu
Figure
).
Kolejną zaletą używania tego słowa kluczowego jest możliwość wywoływania metod na obiekcie typu parametryzowanego. W przykładzie
powyżej wiemy że
T
jest czymś co implementuje
Figure
więc musi mieć metody dostępne w tym interfejsie. Właśnie z tego powodu w
metodzie
getElementName
możemy wywołać metodę
getName
z tego interfejsu.
Dziedziczenie typów generycznych
Tutaj należy się dodatkowe zdanie wyjaśnienia poparte prostym przykładem. Proszę spójrz na początek na klasy
Rectangle
i
Square
poniżej:
Jak wiesz każda klasa w języku Java dziedziczy po klasie
Object
(bezpośrednio, bądź pośrednio). W naszym przykładzie bezpośrednio po
klasie
Object
dziedziczą klasy
Rectangle
,
BoxForFigures<Rectangle>
i
. Natomiast
Square
dziedziczy po
Rectangle
.
public
interface
Figure
{
String
getName
();
}
public
class
Circle
implements
Figure
{
public
String
getName
()
{
return
"circle"
;
}
}
public
class
BoxForFigures
<
T
extends
Figure
>
{
private
T element
;
public
BoxForFigures
(
T element
)
{
this
.
element
=
element
;
}
public
T
getElement
()
{
return
element
;
}
public
String
getElementName
()
{
return
element
.
getName
();
}
}
BoxForFigures
<
Circle
>
circleBox
=
new
BoxForFigures
<>(
new
Circle
());
BoxForFigures
<
Apple
>
appleBox
;
// complilation error
public
class
Rectangle
implements
Figure
{
public
String
getName
()
{
return
"rectangle"
;
}
}
public
class
Square
extends
Rectangle
{
public
String
getName
()
{
return
"square"
;
}
}
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
6/12
Dziedziczenie typów generycznych.
Ma to swoje konsekwencje widoczne w przykładzie poniżej:
Dzięki takiemu schematowi dziedziczenia do referencji typu
Rectangle
możemy przypisać obiekt
Square
. Jednak próba przypisania obiektu
BoxForFigures<Square>
do referencji
BoxForFigures<Rectangle>
powoduje błąd kompilacji.
Jednak podobnie jak w przypadku zwykłych klas, klasy generyczne także mogą dziedziczyć po innych klasach. W szczególności mogą
także dziedziczyć po klasach generycznych.
W naszym przykładzie klasa
FancyBox
dziedziczy po
StandardBox
, widoczne jest to na diagramie poniżej.
Rectangle rectangle
=
new
Square
();
BoxForFigures
<
Rectangle
>
rectangleBox
=
new
BoxForFigures
<
Square
>(
new
Square
());
// compilation error
class
StandardBox
<
T
>
{
public
T object
;
public
StandardBox
(
T object
)
{
this
.
object
=
object
;
}
}
public
class
FancyBox
<
T
>
extends
StandardBox
<
T
>
{
public
FancyBox
(
T object
)
{
super
(
object
);
}
public
void
saySomethingFancy
()
{
System
.
out
.
println
(
"our "
+
object
+
" is cool!"
);
}
}
public
class
Main
{
public
static
void
main
(
String
[]
args
)
{
FancyBox
<
String
>
box
=
new
FancyBox
<>(
"something"
);
box
.
saySomethingFancy
();
}
}
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
7/12
Dziedziczenie typów generycznych
Metody z generycznymi argumentami – wildcard
FancyBox<?>
Pisząc metody, które jako argumenty przyjmują typy generyczne nie zawsze chcesz dokładnie specyfikować typ. W takim wypadku z
pomocą przychodzi znak
?
, który może akceptować różne typy.
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
8/12
Jak widzisz w przykładzie powyżej metoda method1 może akceptować różne klasę
FancyBox
parametryzowaną dowolnym typem.
Przypisanie wartości
Ma to jednak swoje konsekwencje. Klasa, która parametryzowana jest
?
nie przyjmie żadnych obiektów poza
null
. Przykład poniżej
zakończy się błędem kompilacji:
FancyBox<? extends Figure> “upper bound”
Znak
?
może występować także w połączeniu ze słówkiem kluczowym
extends
. W takim przypadku możesz ograniczyć akceptowane typy
“z góry”. W przykładzie poniżej metoda akceptuje jedynie instancje
FancyBox
, które parametryzowane są klasami dziedziczącymi po
Figure
.
W przykładzie tym możesz także zobaczyć, że typ
FancyBox<Figure>
jest bardziej restrykcyjny niż
FancyBox<? extends Figure>
. W
konsekwencji próba wywołania
method3
z argumentem innego typu niż
FancyBox<Figure>
skutkuje błędem kompilacji.
Przypisanie wartości
Podobnie jak w przypadku
?
tutaj także są ograniczenia dotyczące przypisywania wartości. Spójrz jeszcze raz na przykład:
Skoro wewnątrz metody parametr
box
może mieć zarówno typ
FancyBox<Square>
jak i
FancyBox<Circle>
(jak i wiele innych) kompilator nie
może pozwolić na wstawienie tam obiektu innego niż
null
. Nie może tego zrobić bo nie wie jakiego typu obiekty przechowywane są w
box
.
private
static
void
method1
(
FancyBox
<?>
box
)
{
Object object
=
box
.
object
;
System
.
out
.
println
(
object
);
}
private
static
void
plainWildcard
()
{
method1
(
new
FancyBox
<>(
new
Object
()));
method1
(
new
FancyBox
<>(
new
Square
()));
method1
(
new
FancyBox
<>(
new
Apple
()));
}
FancyBox
<?>
box
=
new
FancyBox
<>(
"object"
);
box
.
object
=
null
;
// box.object = "xxx"; // compilation error
private
static
void
method2
(
FancyBox
<?
extends
Figure
>
box
)
{
Figure figure
=
box
.
object
;
System
.
out
.
println
(
figure
);
}
private
static
void
method3
(
FancyBox
<
Figure
>
box
)
{
Figure figure
=
box
.
object
;
System
.
out
.
println
(
figure
);
}
private
static
void
upperBoundWildcard
()
{
FancyBox
<
Figure
>
fancyFigureBox
=
new
FancyBox
<>(
new
Circle
());
FancyBox
<
Circle
>
fancyCircleBox
=
new
FancyBox
<>(
new
Circle
());
FancyBox
<
Square
>
fancySquareBox
=
new
FancyBox
<>(
new
Square
());
method2
(
fancyFigureBox
);
method2
(
fancyCircleBox
);
method2
(
fancySquareBox
);
// method3(fancySquareBox); // compilation error
}
private
static
void
method2
(
FancyBox
<?
extends
Figure
>
box
)
{
Figure figure
=
box
.
object
;
System
.
out
.
println
(
figure
);
// box.object = null;
// box.object = new Square(); // compilation error
}
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
9/12
FancyBox<? super Rectangle> “lower bound”
Poza ograniczeniem “z góry” możesz także ograniczyć akceptowalne typy “z dołu”. W przykładzie poniżej metoda akceptuje wyłącznie
argumenty typu
FancyBox<Object>
,
FancyBox<Figure>
i
FancyBox<Rectangle>
.
Zauważ, ze w niektórych miejscach nie ma potrzeby podawania typu generycznego. Samo
<>
wystarczy, kompilator jest w stanie
wywnioskować jakiego typu może się tam spodziewać. Typy generyczne są skomplikowane. Jeśli aktualnie masz mętlik w głowie nie
przejmuj się, przeczytaj artykuł jeszcze raz, przejrzyj przykłady. Zrozumienie przyjdzie z doświadczeniem.
Przypisanie wartości
Wyżej wspomniałem, że przy ograniczeniu z dołu kompilator wie czego może się spodziewać. W przykładzie:
Parametr
box
może być typu
FancyBox<Object>
,
FancyBox<Square>
i
FancyBox<Rectangle>
. Zatem w tym przypadku do pola
box.object
można przypisać
null
i każdy obiekt, który dziedziczy po
Rectangle
.
Typy generyczne są skomplikowane
Nie zostały one dodane do Javy od samego początku. W związku z tym, że twórcy chcieli zachować kompatybilność wstecz istnieje wiele
kruczków, które nie są trywialne. Pominąłem w artykule np. “type erasure” czy generyczne metody, które nie są istotne na początku. Jeśli
jesteś nimi zainteresowany odsyłam do materiałów dodatkowych.
Materiały dodatkowe
Wszystkie przykłady użyte w tym artykule dostępne są na githubie
Ciebie zestaw dodatkowy materiałów, jeśli chciałbyś poszerzyć swoją wiedzę na temat typów generycznych w języku Java.
https://docs.oracle.com/javase/tutorial/java/generics/index.html
(https://docs.oracle.com/javase/tutorial/java/generics/index.html)
https://docs.oracle.com/javase/tutorial/extra/generics/index.html
(https://docs.oracle.com/javase/tutorial/extra/generics/index.html)
https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5
(https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5)
https://pl.wikipedia.org/wiki/Programowanie_uog%C3%B3lnione
(https://pl.wikipedia.org/wiki/Programowanie_uog%C3%B3lnione)
Podsumowanie
Nie jest to oczywiście kompletny artykuł dotyczący typów generycznych w Javie. Pominięte zostały aspekty wymazywania typów czy
bardziej szczegółowe informacje dotyczące użycia ?. Jeśli któryś fragment jest dla Ciebie nie do końca zrozumiały daj znać, postaram się
rozszerzyć artykuł o dodatkowe przykłady i opisy.
private
static
void
method4
(
FancyBox
<?
super
Rectangle
>
box
)
{
box
.
object
=
new
Square
();
// box.object = new Circle(); // compilation error
}
private
static
void
lowerBoundWildcard
()
{
FancyBox
<
Rectangle
>
fancyRectangleBox
=
new
FancyBox
<>(
new
Rectangle
());
FancyBox
<
Figure
>
fancyFiguraBox
=
new
FancyBox
<>(
new
Rectangle
());
FancyBox
<
Object
>
fancyObjectBox
=
new
FancyBox
<>(
new
Object
());
method4
(
fancyRectangleBox
);
method4
(
fancyFiguraBox
);
method4
(
fancyObjectBox
);
// FancyBox<Square> fancySquareBox = new FancyBox<>(new Square());
// method4(fancySquareBox); // compilation error
}
private
static
void
method4
(
FancyBox
<?
super
Rectangle
>
box
)
{
box
.
object
=
null
;
box
.
object
=
new
Rectangle
();
box
.
object
=
new
Square
();
// box.object = new Object(); // compilation error
}
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
10/12
ZOSTAW KOMENTARZ
18 Komentarzy
Zaloguj
Udostępnij
⤤
Sortuj według najlepszych
ZALOGUJ SIĘ ZA POMOCĄ
ALBO ZAREJESTRUJ W DISQUS
Nazwa
Dołącz do dyskusji...
?
•
Odpowiedz
•
•
Znalazłem kilka zadań na typy generyczne. Prośba o analizę i uwagi (zwłaszcza zadania 4-6), bo mam tam błędy i nie bardzo wiem czemu
tak jest. Link:
https://github.com/lukasz-c...
△ ▽
•
Odpowiedz
•
•
samouczek
Pamiętaj, że liczby całkowite mogą być reprezentowane przez wiele typów, na przykład
Integer
,
Byte
czy
Long
.
Przeczytaj artykuł jeszcze raz. Uzupełniłem go o fragmenty, które powinny odpowiedzieć na Twoje pytania dotyczące zadań 4-6.
△ ▽
•
Odpowiedz
•
•
Poprawione i działa. Poprawki scommitowane w linku w poprzedniej wiadomości
△ ▽
•
W jaki sposób pisać kod z przykładów, czy wszystkie przedstawione klasy mają być w jednym pliku tak jak są prezentowane, czy każda w
osobnym. Bo jeśli umieszczam klasy w jednym pliku, to muszę zagnieździć w klasie pliku i nadać parametr static. Jak to pisać i gdzie jest
mój błąd.
public class FruitBox {
private Object fruit;
public FruitBox(Object fruit) {
this.fruit = fruit;
}
public Object getFruit() {
return fruit;
}
}
public class Main {
public static void main(String[] args) {
FruitBox fruitBox = new FruitBox(new Orange());
Poleć
Udostępnij ›
Udostępnij ›
Udostępnij ›
Na koniec mam do Ciebie prośbę. Proszę podziel się artykułem ze swoimi znajomymi, którzy mogą być zainteresowani tematem
programowania. Zależy mi na dotarciu do jak największej liczby czytelników. Jeśli nie chcesz ominąć żadnego kolejnego artykułu polub nas
na Facebooku :) Do następnego razu!
1. Mała dygresja. Każdy błąd w kodzie kosztuje. Ktoś w końcu płaci za pracę testerów, programistów, administratorów. Im wcześniej wykryjemy błąd tym tańsze jest jego naprawienie.
Poprawienie programu działającego na środowisku produkcyjnym może być bardzo drogie. Wykrywanie błędów w trakcie kompilacji, chociaż może być frustrujące dla programisty
jest najtańszym rozwiązaniem :)
3. Tu właśnie objawia się to automatyczne rzutowanie generowane przez kompilator
4. W rzeczywistości, po skompilowaniu powstanie jeden plik class z klasą
BoxForFigures
.
5. Twórcom zależało na tym aby programy napisane w starej wersji Javy mogły być uruchamiane na najnowszych wersjach maszyny wirtualnej.
Dodaj mnie do newslettera
Kategorie:
Ostatnia aktualizacja: March 26, 2016
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
11/12
•
Odpowiedz
•
(
g ());
Orange fruit1 = (Orange) fruitBox.getFruit();
}
}
△ ▽
•
Odpowiedz
•
•
samouczek
W języku Java jażdy z plików
java
może zawierać wyłącznie jedną publiczą klasę (pomijam
pliku musi odpowiadać nazwie klasy.
Polecam Ci zacząć od wcześniejszych artykułów, jak opanujesz podstawy zabierz się za bardziej zaawansowane elementy.
△ ▽
•
Odpowiedz
•
•
Wkleiłem kod specjalnie, bo sugeruje że wszystko jest w jednym pliku. Odczytuje z kodu, że nazwą pliku i klasą główną jest
Main i jego metoda statyczna. Jednak reszta kodu z klasami z przykładu jest umieszczona poza tą klasa. Dlatwgo się pytam
gdzie te klasy umieszczać, nowa klasa nowy plik, czy jako klasę wewnetrzna z parametrem static?
△ ▽
•
Odpowiedz
•
•
samouczek
Odpowiadając najprościej, bez wdawania się w dyskusję - podzieliłbym to na osobne pliki. Dokładnie tak jak w
zrobiłem to w kodzie na
.
△ ▽
•
Odpowiedz
•
•
Dzięki, nie mogłem znaleźć nigdzie linku do do github, teraz mogę podejrzeć kod i znaleźć błędy. Dzięki. Ja zrobiłem
to na klasach wewnętrznych statycznych. Pozdrawiam
△ ▽
•
Odpowiedz
•
•
samouczek
Na tym etapie kursu przykłady w artykule zakładają, że pierwsze etapy są już zrobione. W tych pierwszych etapach
dowiedziałbyś się o tym co napisałem wyżej :).
△ ▽
•
Odpowiedz
•
•
Oczywiście, wrócę do poprzednich zagadnień, bo nie wszystko pamiętam, jednak mi chodziło o konwencję pisania
kodu z przykładów, nie widząc całości nie wiedziałem które klasy są w osobnym pliku, a które są wewnętrzne.
△ ▽
•
Odpowiedz
•
•
Proszę wyjaśnij co to znaczy parametryzować czyli nabywać wszystkie cechy wskazane przez TYP określony w <> (zmienne, metody etc.)
?
△ ▽
•
Odpowiedz
•
•
samouczek
Hmm, nie mogę znaleźć takiego określenia w artykule. Możesz wskazać akapit, o który Ci chodzi? Możliwe, że napisałem coś
niejasno i będę musiał to przepisać.
△ ▽
•
Odpowiedz
•
•
Może inaczej zapytam. Co oznacza w przypadku generyków parametryzowanie ? Czy jeżeli podam jakąś klasę/obiekt jako
parametr w klasie generycznej to czy oznacza to że przekazuje też dostęp do jej pól, metod, konstruktorów etc.? Jeżeli tak to
jaka jest różnica czy ja będę dziedziczył czy zrobię generyka ? Rozumiem, że jest to pewna forma poliformizmu, ale nie
jestem tego wszystkiego pewny.
△ ▽
•
Odpowiedz
•
•
samouczek
Dodałem krótki akapit o
.
To, że utworzysz klasę, która jest parametryzowana typem nie ma nic wspólnego z dziedziczeniem. Dziedziczenie
typów generycznych opisałem w
Główna różnica jest taka, że przy dziedziczeniu niektóre
pozwalają na dostęp do danego pola
klasom pochodnym.
△ ▽
•
Odpowiedz
•
•
Super wyjaśnione , najbardziej podobał mi się odcinek z rzutowaniem i zdjęciem w tle... (IF == YOU ) System.out.println("KNOW WHAT I
MEAN");
△ ▽
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
Udostępnij ›
3.06.2018
Typy generyczne w języku Java - Samouczek Programisty
http://www.samouczekprogramisty.pl/typy-generyczne-w-jezyku-java/
12/12
Referencja, sterta i garbage collector – obiektów w Javie ciąg
dalszy
— Dzięki bardzo za kurs! Co prawda miałem już
Konwersja i rzutowanie w języku Java
— Proszę przeczytaj artykuł o typach prostych.
— Nie było specjalnie trudno. Zrobione. Efekt:
https://github.com/lukasz-c...
Podstawy złożoności obliczeniowej - Samouczek Programisty
— Szczerze mówiąc nie wiem co masz na myśli
TAKŻE NA
SAMOUCZEKPROGRAMISTY
•
Odpowiedz
•
•
samouczek
Cięszę się, że artykuły Ci się podobają. Jeśli jakiegoś tematu brakuje Ci na blogu, daj znać - postaram się pomóc.
△ ▽
•
Odpowiedz
•
•
hmm ... no Marcin mi dużo pomogła twoja strona. Na pewno oszczędziłem sporo czasu . Czego brakuje? hm...
mi przede wszystkim brakuje zadań z przykładowymi rozwiązaniami. Mogłbyś zrobic na koniec jakiś test w postaci 10 zadań :)
... a jeśli chodzi o tematy to zamiesciłeś dużo konkretow
△ ▽
•
Odpowiedz
•
•
samouczek
Pomyślę nad takim testem, może rzeczywiście jest to dobry pomysł. Jeśli chodzi o same zadania z rozwiązaniami to
na blogu jest ich całkiem sporo :). Zadania mają różny stopień trudności, na pewno znajdziesz coś dla siebie. Poza
zadaniami pod większością artykułów zebrałem inne na tych stronach:
http://www.samouczekprogram...
http://www.samouczekprogram...
△ ▽
Dodaj Disqus do swojej strony Dodaj DisqusDodaj
Disqus' Privacy Policypolityką prywatnościPrywatność
Udostępnij ›
Udostępnij ›
Udostępnij ›