Ogólne informacje o konstruktorach
Конструктор
to struktura przypominająca metodę, której celem jest utworzenie instancji klasy. Charakterystyka projektanta:
- Nazwa konstruktora musi odpowiadać nazwie klasy (zgodnie z konwencją pierwsza litera jest wielka, zwykle jest to rzeczownik);
- W każdej klasie istnieje konstruktor. Nawet jeśli go nie napiszesz, kompilator Java utworzy domyślny konstruktor, który będzie pusty i nie zrobi nic poza wywołaniem konstruktora nadklasy.
- Konstruktor jest podobny do metody, ale nie jest metodą, nie jest nawet uważany za członka klasy. Dlatego nie można jej dziedziczyć ani zastępować w podklasie;
- Konstruktory nie są dziedziczone;
- W klasie może być kilku konstruktorów. W tym przypadku mówi się, że konstruktory są przeciążone;
- Jeśli klasa nie definiuje konstruktora, kompilator automatycznie dodaje do kodu konstruktora bez parametrów;
- Konstruktor nie ma typu zwracanego; nie może nawet być typem
void
; jeśli zostanie zwrócony typ void
, to nie jest już konstruktorem, ale metodą, pomimo zbieżności z nazwą klasy.
- Operator jest dozwolony w konstruktorze
return
, ale tylko pusty, bez wartości zwracanej;
- Konstruktor pozwala na użycie modyfikatorów dostępu, można ustawić jeden z modyfikatorów:
public
, protected
, private
lub bez modyfikatora.
- Konstruktor nie może mieć modyfikatorów
abstract
, final
, lub ;native
static
synchronized
- Słowo kluczowe
this
odnosi się do innego konstruktora w tej samej klasie. Jeśli jest używany, wywołanie musi być pierwszą linią konstruktora;
- Słowo kluczowe
super
wywołuje konstruktor klasy nadrzędnej. Jeśli jest używany, odniesienie do niego musi być pierwszą linią konstruktora;
- Jeśli konstruktor nie wywoła konstruktora
super
klasy przodka (z argumentami lub bez), kompilator automatycznie dodaje kod wywołujący konstruktor klasy przodka bez argumentów;
Domyślny konstruktor
W każdej klasie istnieje konstruktor. Nawet jeśli go nie napiszesz, kompilator Java utworzy konstruktor domyślny. Ten konstruktor jest pusty i nie robi nic innego, jak tylko wywołuje konstruktor nadklasy. Te. jeśli napiszesz:
public class Example {}
to jest to równoznaczne z napisaniem:
public class Example
{
Example()
{
super;
}
}
W tym przypadku klasa przodka nie jest jawnie określona i domyślnie wszystkie klasy Java dziedziczą tę klasę,
Object
dlatego wywoływany jest konstruktor klasy
Object
. Jeśli klasa definiuje konstruktor z parametrami, ale nie ma przeciążonego konstruktora bez parametrów, to wywołanie konstruktora bez parametrów jest błędem. Jednakże w Javie od wersji 1.5 możliwe jest używanie konstruktorów z argumentami o zmiennej długości. A jeśli istnieje konstruktor posiadający argument o zmiennej długości, wówczas wywołanie konstruktora domyślnego nie będzie błędem. Nie będzie, ponieważ argument o zmiennej długości może być pusty. Na przykład poniższy przykład nie zostanie skompilowany, ale jeśli odkomentujesz konstruktora argumentem o zmiennej długości, zostanie on pomyślnie skompilowany i uruchomiony, w wyniku czego zostanie uruchomiony wiersz kodu
DefaultDemo dd = new DefaultDemo()
; konstruktor zostanie wywołany
DefaultDemo(int ... v)
. Naturalnie w tym przypadku konieczne jest użycie JSDK 1.5. Plik
DefaultDemo.java
class DefaultDemo
{
DefaultDemo(String s)
{
System.out.print("DefaultDemo(String)");
}
public static void main(String args[])
{
DefaultDemo dd = new DefaultDemo();
}
}
Wynik wyjścia programu z konstruktorem bez komentarza:
DefaultDemo(int ...)
Jednakże w typowym przypadku, gdy klasa w ogóle nie definiuje żadnego konstruktora, konieczne będzie wywołanie konstruktora domyślnego (bez parametrów), ponieważ podstawienie konstruktora domyślnego następuje automatycznie.
Tworzenie obiektów i konstruktorzy
Podczas tworzenia obiektu wykonywane są kolejno następujące czynności:
- Klasa obiektu jest przeszukiwana wśród klas już używanych w programie. Jeżeli go nie ma, to jest on przeszukiwany we wszystkich katalogach i bibliotekach dostępnych dla programu. Po wykryciu klasy w katalogu lub bibliotece tworzone i inicjowane są pola statyczne klasy. Te. Dla każdej klasy pola statyczne są inicjowane tylko raz.
- Pamięć jest przydzielana obiektowi.
- Pola klasy są inicjowane.
- Konstruktor klasy jest wykonywany.
- Tworzone jest łącze do utworzonego i zainicjowanego obiektu. To odwołanie jest wartością wyrażenia tworzącego obiekt. Obiekt można także utworzyć wywołując metodę
newInstance()
klasy java.lang.Class
. W tym przypadku używany jest konstruktor bez listy parametrów.
Przeciążanie konstruktorów
Konstruktory tej samej klasy mogą mieć tę samą nazwę i inny podpis. Ta właściwość nazywa się kombinacją lub przeciążeniem. Jeśli klasa ma wiele konstruktorów, występuje przeciążenie konstruktora.
Konstruktory parametryczne
Sygnaturą konstruktora jest liczba i typy parametrów oraz kolejność ich typów na liście parametrów konstruktora. Typ zwrotu nie jest brany pod uwagę. Konstruktor nie zwraca żadnych parametrów. Ta instrukcja wyjaśnia w pewnym sensie, w jaki sposób Java rozróżnia przeciążone konstruktory lub metody. Java rozróżnia przeciążone metody nie na podstawie typu zwracanego, ale na podstawie liczby, typów i kolejności typów parametrów wejściowych. Konstruktor nie może nawet zwrócić typu
void
, w przeciwnym razie zamieni się w zwykłą metodę, mimo że jest podobna do nazwy klasy. Poniższy przykład to demonstruje. Plik
VoidDemo.java
class VoidDemo
{
VoidDemo()
{
System.out.println("Constructor");
}
void VoidDemo()
{
System.out.println("Method");
}
public static void main(String s[])
{
VoidDemo m = new VoidDemo();
}
}
W rezultacie program wyświetli:
Constructor
To po raz kolejny udowadnia, że konstruktor jest metodą bez parametrów zwracanych. Jednakże konstruktorowi można nadać jeden z trzech modyfikatorów
public
,
private
lub
protected
. Przykład będzie teraz wyglądał następująco: File
VoidDemo2.java
class VoidDemo2
{
public VoidDemo2()
{
System.out.println("Constructor");
}
private void VoidDemo2()
{
System.out.println("Method");
}
public static void main(String s[])
{
VoidDemo2 m = new VoidDemo2();
}
}
W konstruktorze można zapisać operator
return
, ale tylko pusty, bez wartości zwracanej. Plik
ReturnDemo.java
class ReturnDemo
{
public ReturnDemo()
{
System.out.println("Constructor");
return;
}
public static void main(String s[])
{
ReturnDemo r = new ReturnDemo();
}
}
Konstruktory sparametryzowane argumentami o zmiennej długości
Java SDK 1.5 wprowadziło długo oczekiwane narzędzie - argumenty o zmiennej długości dla konstruktorów i metod. Wcześniej zmienna liczba dokumentów była przetwarzana na dwa niewygodne sposoby. Pierwsza z nich miała na celu zapewnienie, że maksymalna liczba argumentów będzie ograniczona do niewielkiej liczby i znana z góry. W tym przypadku udało się stworzyć przeciążone wersje metody, po jednej dla każdej wersji listy argumentów przekazanych do metody. Druga metoda jest przeznaczona dla czegoś nieznanego z góry i dużej liczby argumentów. W tym przypadku argumenty zostały umieszczone w tablicy, a tablica ta została przekazana do metody. Argumenty o zmiennej długości są najczęściej używane w kolejnych manipulacjach przy zmiennych inicjacjach. Wygodnie jest zastąpić brak niektórych oczekiwanych argumentów konstruktora lub metody wartościami domyślnymi. Argument o zmiennej długości jest tablicą i jest traktowany jako tablica. Na przykład konstruktor klasy
Checking
ze zmienną liczbą argumentów będzie wyglądał następująco:
class Checking
{
public Checking(int ... n)
{
}
}
Kombinacja znaków ... mówi kompilatorowi, że zostanie użyta zmienna liczba argumentów i że argumenty te będą przechowywane w tablicy, której wartość referencyjna jest zawarta w zmiennej n. Konstruktor można wywołać z różną liczbą argumentów, w tym bez żadnych argumentów. Argumenty są automatycznie umieszczane w tablicy i przekazywane przez n. Jeżeli nie ma argumentów, długość tablicy wynosi 0. Lista parametrów wraz z argumentami o zmiennej długości może zawierać także parametry obowiązkowe. W tym przypadku parametr zawierający zmienną liczbę argumentów musi znajdować się na końcu listy parametrów. Na przykład:
class Checking
{
public Checking(String s, int ... n)
{
}
}
Bardzo oczywiste ograniczenie dotyczy liczby parametrów o zmiennej długości. Na liście parametrów może znajdować się tylko jeden parametr o zmiennej długości. Biorąc pod uwagę dwa parametry o zmiennej długości, kompilator nie jest w stanie określić, gdzie kończy się jeden parametr, a zaczyna drugi. Na przykład:
class Checking
{
public Checking(String s, int ... n, double ... d)
{
}
}
Plik
Checking.java
Przykładowo istnieje sprzęt zdolny do rozpoznawania tablic rejestracyjnych samochodów i zapamiętywania numerów kwadratów obszaru, na którym w ciągu dnia odwiedzał każdy z samochodów. Z łącznej masy zarejestrowanych samochodów należy wybrać te, które w ciągu dnia odwiedziły dwa dane kwadraty, powiedzmy 22 i 15, zgodnie z mapą obszaru. To zupełnie naturalne, że samochód może w ciągu dnia odwiedzić wiele placów, a może i tylko jeden. Oczywiście liczba odwiedzanych placów jest ograniczona fizyczną prędkością samochodu. Stwórzmy mały program, w którym konstruktor klasy przyjmie jako argumenty numer samochodu jako parametr obowiązkowy oraz liczbę odwiedzanych kwadratów obszaru, których liczba może być zmienna. Konstruktor sprawdzi, czy w dwóch kwadratach pojawił się samochód, a jeśli tak, wyświetli jego numer na ekranie.
Przekazywanie parametrów do konstruktora
W językach programowania występują głównie dwa typy parametrów:
- typy podstawowe (prymitywy);
- odniesienia do obiektów.
Termin wywołanie przez wartość oznacza, że konstruktor otrzymuje wartość przekazaną mu przez moduł wywołujący. Natomiast wywołanie przez referencję oznacza, że konstruktor otrzymuje adres zmiennej od osoby wywołującej. Java używa tylko wywołań według wartości. Według wartości parametru i wartości łącza parametru. Java nie używa wywołań przez referencje dla obiektów (chociaż twierdzi tak wielu programistów i autorów niektórych książek). Podczas przekazywania obiektów do Javy parametry przekazywane są
nie przez referencję , ale
przez wartość referencji do obiektu ! W obu przypadkach konstruktor otrzymuje kopie wartości wszystkich parametrów. Konstruktor nie może zrobić ze swoimi parametrami wejściowymi:
- konstruktor nie może zmieniać wartości parametrów wejściowych typów głównych (prymitywnych);
- konstruktor nie może zmienić odwołań do parametrów wejściowych;
- konstruktor nie może ponownie przypisać odwołań do parametrów wejściowych do nowych obiektów.
Konstruktor może wykorzystać swoje parametry wejściowe:
- zmienić stan obiektu przekazanego jako parametr wejściowy.
Poniższy przykład pokazuje, że w Javie parametry wejściowe do konstruktora przekazywane są poprzez wartość referencyjną obiektu. Ten przykład odzwierciedla również, że konstruktor nie może zmieniać odwołań do parametrów wejściowych, ale w rzeczywistości zmienia odniesienia do kopii parametrów wejściowych. Plik
Empoyee.java
class Employee
{
Employee(String x, String y)
{
String temp = x;
x = y;
y = temp;
}
public static void main(String args[])
{
String name1 = new String("Alice");
String name2 = new String("Mary");
Employee a = new Employee(name1, name2);
System.out.println("name1="+name1);
System.out.println("name2="+name2);
}
}
Dane wyjściowe programu to:
name1=Alice
name2=Mary
Jeśli Java użyłaby wywołania przez referencję do przekazania obiektów jako parametrów, konstruktor zamieniłby
name1
i w tym przykładzie
name2
. Konstruktor w rzeczywistości nie zamieni odwołań do obiektów przechowywanych w zmiennych
name1
i
name2
. Sugeruje to, że parametry konstruktora są inicjowane kopiami tych odniesień. Następnie konstruktor zamienia kopie. Kiedy konstruktor zakończy swoją pracę, zmienne x i y zostają zniszczone, a oryginalne zmienne
name1
w dalszym ciągu
name2
odnoszą się do poprzednich obiektów.
Zmiana parametrów przekazanych do konstruktora.
Konstruktor nie może modyfikować przekazanych parametrów typów podstawowych. Konstruktor może jednak modyfikować stan obiektu przekazanego jako parametr. Rozważmy na przykład następujący program: File
Salary1.java
class Salary1
{
Salary1(int x)
{
x = x * 3;
System.out.println("x="+x);
}
public static void main(String args[])
{
int value = 1000;
Salary1 s1 = new Salary1(value);
System.out.println("value="+value);
}
}
Dane wyjściowe programu to:
x=3000
value=1000
Oczywiście ta metoda nie zmieni głównego parametru typu. Dlatego po wywołaniu konstruktora wartość zmiennej
value
pozostaje równa
1000
. Zasadniczo zachodzą trzy rzeczy:
- Zmienna
x
jest inicjowana kopią wartości parametru value
(tj. liczby 1000
).
- Wartość zmiennej
x
została potrojona – teraz wynosi 3000
. Jednakże wartość zmiennej value
pozostaje równa 1000
.
- Konstruktor kończy działanie i zmienna
x
nie jest już używana.
W poniższym przykładzie wynagrodzenie pracownika zostało pomyślnie potrojone, ponieważ wartość referencji do obiektu została przekazana jako parametr do metody. Plik
Salary2.java
class Salary2
{
int value = 1000;
Salary2()
{
}
Salary2(Salary2 x)
{
x.value = x.value * 3;
}
public static void main(String args[])
{
Salary2 s1 = new Salary2();
Salary2 s2 = new Salary2(s1);
System.out.println("s1.value=" +s1.value);
System.out.println("s2.value="+s2.value);
}
}
Dane wyjściowe programu to:
s1.value=3000
s2.value=1000
Jako parametr używana jest wartość odniesienia do obiektu. Podczas wykonywania linii
Salary2 s2 = new Salary2(s1)
; konstruktorowi
Salary2(Salary x)
zostanie przekazana wartość referencji do obiektu zmiennego
s1
i konstruktor faktycznie potroi wynagrodzenie za ten obiekt
s1.value
, ponieważ nawet kopia
(Salary x)
utworzona wewnątrz konstruktora wskazuje na obiekt zmienny
s1
.
Konstruktory sparametryzowane przez prymitywy.
Jeżeli w parametrach przeciążonego konstruktora zastosowano prymityw, który można zawęzić (np.
int <- double
), to możliwe jest wywołanie metody z zawężoną wartością, mimo że nie ma metody przeciążonej takim parametrem. Na przykład: Plik
Primitive.java
class Primitive
{
Primitive(double d)
{
d = d + 10;
System.out.println("d="+d);
}
public static void main(String args[])
{
int i = 20;
Primitive s1 = new Primitive(i);
}
}
Dane wyjściowe programu to:
d=30.0
Pomimo tego, że klasa
Primitive
nie posiada konstruktora posiadającego parametr typu
int
, zadziała konstruktor z parametrem wejściowym
double
. Przed wywołaniem konstruktora zmienna
i
zostanie rozwinięta z typu
int
na typ
double
. Opcja odwrotna, gdy zmienna
i
byłaby typu
double
, a konstruktor miałby tylko parametr
int
, w tej sytuacji doprowadziłaby do błędu kompilacji.
Wywołanie konstruktora i operatornew
Konstruktor jest zawsze wywoływany przez operatora
new
. Kiedy konstruktor jest wywoływany z operatorem
new
, konstruktor zawsze generuje odwołanie do nowego obiektu. Nie można zmusić konstruktora do utworzenia referencji do już istniejącego obiektu zamiast referencji do nowego obiektu, chyba że poprzez podstawienie deserializacji obiektu. A za pomocą operatora new zamiast odniesienia do nowego obiektu nie da się utworzyć odniesienia do już istniejącego obiektu. Na przykład: Plik
Salary3.java
class Salary3
{
int value = 1000;
Salary3()
{
}
Salary3(Salary3 x)
{
x.value = x.value * 3;
}
public static void main(String args[])
{
Salary3 s1 = new Salary3();
System.out.println("First object creation: "+s1.value);
Salary3 s2 = new Salary3(s1);
System.out.println("Second object creation: "+s2.value);
System.out.println("What's happend with first object?:"+s1.value);
Salary3 s3 = new Salary3(s1);
System.out.println("Third object creation: "+s3.value);
System.out.println("What's happend with first object?:"+s1.value);
}
}
Dane wyjściowe programu to:
First object creation: 1000
Second object creation: 1000
What's happend with first object?: 3000
Third object creation: 1000
What's happend with first object?: 9000
Najpierw użyj linii
Salary3 s1 = new Salary3()
; tworzony jest nowy obiekt. Następnie, jeśli używasz linii
Salary3 s2 = new Salary3(s1)
; lub ciągi znaków
Salary3 s3 = new Salary3(s1)
; możliwe byłoby utworzenie linku do już istniejącego obiektu, wówczas
s1.value s2.value
przechowywałyby
s3.value
tę samą wartość
1000
. Właściwie w linii
Salary3 s2 = new Salary3(s1)
; zostanie utworzony nowy obiekt dla zmiennej,
s2
a stan obiektu dla zmiennej zmieni się
s1
poprzez przekazanie jego wartości referencyjnej do obiektu w parametrze konstruktora. Można to sprawdzić na podstawie wyników wyjściowych. A podczas wykonywania linii
Salary3 s3 = new Salary3(s1)
; zostanie utworzony NOWY obiekt dla zmiennej
s3
i stan obiektu dla zmiennej ponownie się zmieni
s1
.
Konstruktory i bloki inicjujące, kolejność działań przy wywołaniu konstruktora
Sekcja
Tworzenie obiektu i Konstruktorzy zawiera listę ogólnych akcji wykonywanych podczas tworzenia obiektu. Należą do nich procesy inicjowania pól klas i opracowywania konstruktora klas, które z kolei również mają porządek wewnętrzny:
- Wszystkie pola danych są inicjowane do wartości domyślnych (0, false lub null).
- Wszystkie inicjatory pól i bloki inicjujące są wykonywane w kolejności, w jakiej są wymienione w deklaracji klasy.
- Jeśli w pierwszej linii konstruktora zostanie wywołany inny konstruktor, wówczas wywołany konstruktor zostanie wykonany.
- Wykonywane jest ciało konstruktora.
Konstruktor jest powiązany z inicjalizacją, ponieważ w Javie istnieją trzy sposoby inicjalizacji pola w klasie:
- przypisz wartość w deklaracji;
- przypisz wartości w bloku inicjującym;
- ustaw jego wartość w konstruktorze.
Naturalnie musisz zorganizować kod inicjujący tak, aby był łatwy do zrozumienia. Jako przykład podano następującą klasę:
class Initialization
{
int i;
short z = 10;
static int x;
static float y;
static
{
x = 2000;
y = 3.141;
}
Initialization()
{
System.out.println("i="+i);
System.out.println("z="+z);
z = 20;
System.out.println("z="+z);
}
}
W powyższym przykładzie zmienne są inicjowane w następującej kolejności: zmienne statyczne są inicjowane jako pierwsze
x
z
y
wartościami domyślnymi. Następnie wykonywany jest blok inicjalizacji statycznej. Następnie zmienna jest inicjowana
i
do wartości domyślnej i zmienna jest inicjowana
z
. Następnie projektant zabiera się do pracy. Wywoływanie konstruktorów klas nie powinno zależeć od kolejności deklarowania pól. Może to prowadzić do błędów.
Konstruktory i dziedziczenie
Konstruktory nie są dziedziczone. Na przykład:
public class Example
{
Example()
{
}
public void sayHi()
{
system.out.println("Hi");
}
}
public class SubClass extends Example
{
}
Klasa
SubClass
automatycznie dziedziczy metodę
sayHi()
zdefiniowaną w klasie nadrzędnej. Jednocześnie konstruktor
Example()
klasy nadrzędnej nie jest dziedziczony przez jej potomka
SubClass
.
Słowo kluczowe this
w konstruktorach
Konstruktorów używa się
this
do odwoływania się do innego konstruktora w tej samej klasie, ale z inną listą parametrów. Jeśli konstruktor użyje słowa kluczowego
this
, to musi ono znajdować się w pierwszej linii; zignorowanie tej reguły spowoduje błąd kompilatora. Na przykład: Plik
ThisDemo.java
public class ThisDemo
{
String name;
ThisDemo(String s)
{
name = s;
System.out.println(name);
}
ThisDemo()
{
this("John");
}
public static void main(String args[])
{
ThisDemo td1 = new ThisDemo("Mary");
ThisDemo td2 = new ThisDemo();
}
}
Dane wyjściowe programu to:
Mary
John
W tym przykładzie są dwa konstruktory. Pierwszy otrzymuje argument typu string. Drugi nie otrzymuje żadnych argumentów, po prostu wywołuje pierwszy konstruktor, używając domyślnej nazwy „John”. Dzięki temu można używać konstruktorów do jawnej i domyślnej inicjalizacji wartości pól, co często jest konieczne w programach.
Słowo kluczowe super
w konstruktorach
Konstruktory służą
super
do wywoływania konstruktora nadklasy. Jeśli konstruktor używa
super
, to wywołanie to musi znajdować się w pierwszej linii, w przeciwnym razie kompilator zgłosi błąd. Poniżej przykład: Plik
SuperClassDemo.java
public class SuperClassDemo
{
SuperClassDemo()
{
}
}
class Child extends SuperClassDemo
{
Child()
{
super();
}
}
W tym prostym przykładzie konstruktor
Child()
zawiera wywołanie , które oprócz klasy
super()
tworzy instancję klasy . Ponieważ musi to być pierwsza instrukcja wykonywana w konstruktorze podklasy, kolejność ta jest zawsze taka sama i nie zależy od tego, czy . Jeżeli nie zostanie ona użyta, to jako pierwszy zostanie wykonany domyślny (bez parametrów) konstruktor każdej nadklasy, zaczynając od klasy bazowej. Poniższy program demonstruje, kiedy wykonywane są konstruktory. Plik
SuperClassDemo
Child
super
super()
Call.java
class A
{
A()
{
System.out.println("Inside A constructor.");
}
}
class B extends A
{
B()
{
System.out.println("Inside B constructor.");
}
}
class C extends B
{
C()
{
System.out.println("Inside C constructor.");
}
}
class Call
{
public static void main(String args[])
{
C c = new C();
}
}
Dane wyjściowe z tego programu:
Inside A constructor.
Inside B constructor.
Inside C constructor.
Konstruktory wywoływane są w kolejności podporządkowania klas. To ma pewien sens. Ponieważ nadklasa nie ma wiedzy o żadnej podklasie, każda inicjalizacja, którą musi wykonać, jest oddzielna. Jeśli to możliwe, powinien poprzedzać jakąkolwiek inicjalizację wykonywaną przez podklasę. Dlatego należy to zrobić w pierwszej kolejności.
Konfigurowalni konstruktorzy
Mechanizm identyfikacji typów w czasie wykonywania jest jedną z potężnych podstawowych zasad języka Java, która implementuje polimorfizm. Jednak w niektórych przypadkach taki mechanizm nie chroni programisty przed niezgodnym rzutowaniem typów. Najczęstszym przypadkiem jest manipulacja grupą obiektów, których rodzaje nie są z góry znane i są określane w czasie wykonywania. Ponieważ błędy związane z niezgodnością typów mogą pojawić się dopiero na etapie wykonywania, utrudnia to ich znalezienie i wyeliminowanie. Wprowadzenie typów niestandardowych w Javie 2 5.0 przenosi niektóre z tych błędów ze środowiska wykonawczego do czasu kompilacji i zapewnia część bezpieczeństwa brakujących typów.
Object
Podczas przechodzenia z typu do typu konkretnego nie ma potrzeby jawnego rzutowania typu . Należy pamiętać, że narzędzia dostosowywania typów działają tylko z obiektami i nie mają zastosowania do prymitywnych typów danych, które znajdują się poza drzewem dziedziczenia klas. W przypadku typów niestandardowych wszystkie rzuty są wykonywane automatycznie i za kulisami. Pozwala to zabezpieczyć się przed niezgodnością typów i znacznie częściej wykorzystywać kod. Typy niestandardowe mogą być używane w konstruktorach. Konstruktory mogą być niestandardowe, nawet jeśli ich klasa nie jest typem niestandardowym. Na przykład:
class GenConstructor
{
private double val;
<T extends Number> GenConstructor(T arg)
{
val = arg.doubleValue();
}
void printValue()
{
System.out.println("val: "+val);
}
}
class GenConstructorDemo
{
public static void main(String args[])
{
GenConstructor gc1 = new GenConstructor(100);
GenConstructor gc2 = new GenConstructor(123.5F);
gc1.printValue();
gc2.printValue();
}
}
Ponieważ konstruktor
GenConstructor
określa niestandardowy parametr typu, który musi być klasą pochodną z class
Number
, można go wywołać z dowolnego
GO TO FULL VERSION