JavaRush /Blog Java /Random-PL /Konstruktorzy klas. Java JDK 1.5
articles
Poziom 15

Konstruktorzy klas. Java JDK 1.5

Opublikowano w grupie Random-PL
Konstruktorzy klas.  Java JDK 1.5 - 1

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, privatelub bez modyfikatora.
  • Konstruktor nie może mieć modyfikatorów abstract, final, lub ;nativestaticsynchronized
  • Słowo kluczowe thisodnosi się do innego konstruktora w tej samej klasie. Jeśli jest używany, wywołanie musi być pierwszą linią konstruktora;
  • Słowo kluczowe superwywoł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 superklasy 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ę, Objectdlatego 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. PlikDefaultDemo.java
class DefaultDemo
{
 DefaultDemo(String s)
 {
  System.out.print("DefaultDemo(String)");
 }
 /*
 DefaultDemo(int ... v)
 {
  System.out.println("DefaultDemo(int ...)");
 }
 */

 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. PlikVoidDemo.java
class VoidDemo
{
 /**
  * Это конструктор
  */
 VoidDemo()
 {
  System.out.println("Constructor");
 }

 /**
  * А это уже обычный метод, даже не смотря на сходство с
  * именем класса, поскольку имеется возвращаемый тип void
  */
 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, privatelub protected. Przykład będzie teraz wyglądał następująco: FileVoidDemo2.java
class VoidDemo2
{
 /**
  * Это конструктор
  */
 public VoidDemo2()
 {
  System.out.println("Constructor");
 }

 /**
  * А это уже обычный метод, даже не смотря на сходство с
  * именем класса, поскольку имеется возвращаемый тип void
  */
 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. PlikReturnDemo.java
class ReturnDemo
{
 /**
  * В конструкторе допускается использование оператора
  * return без параметров.
  */
 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 Checkingze 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. PlikEmpoyee.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 name1i w tym przykładzie name2. Konstruktor w rzeczywistości nie zamieni odwołań do obiektów przechowywanych w zmiennych name1i 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 name1w dalszym ciągu name2odnoszą 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: FileSalary1.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 valuepozostaje równa 1000. Zasadniczo zachodzą trzy rzeczy:
  1. Zmienna xjest inicjowana kopią wartości parametru value(tj. liczby 1000).
  2. Wartość zmiennej xzostała potrojona – teraz wynosi 3000. Jednakże wartość zmiennej valuepozostaje równa 1000.
  3. Konstruktor kończy działanie i zmienna xnie 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. PlikSalary2.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 s1i 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: PlikPrimitive.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 Primitivenie posiada konstruktora posiadającego parametr typu int, zadziała konstruktor z parametrem wejściowym double. Przed wywołaniem konstruktora zmienna izostanie rozwinięta z typu intna typ double. Opcja odwrotna, gdy zmienna ibył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: PlikSalary3.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.valueprzechowywałyby s3.valuetę samą wartość 1000. Właściwie w linii Salary3 s2 = new Salary3(s1); zostanie utworzony nowy obiekt dla zmiennej, s2a stan obiektu dla zmiennej zmieni się s1poprzez 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 s3i 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:
  1. Wszystkie pola danych są inicjowane do wartości domyślnych (0, false lub null).
  2. Wszystkie inicjatory pól i bloki inicjujące są wykonywane w kolejności, w jakiej są wymienione w deklaracji klasy.
  3. Jeśli w pierwszej linii konstruktora zostanie wywołany inny konstruktor, wówczas wywołany konstruktor zostanie wykonany.
  4. 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 xz ywartościami domyślnymi. Następnie wykonywany jest blok inicjalizacji statycznej. Następnie zmienna jest inicjowana ido 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 SubClassautomatycznie 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 thisw konstruktorach

Konstruktorów używa się thisdo 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: PlikThisDemo.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 superw konstruktorach

Konstruktory służą superdo 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: PlikSuperClassDemo.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. PlikSuperClassDemoChildsupersuper()Call.java
//Создать суперкласс A
class A
{
 A()
 {
  System.out.println("Inside A constructor.");
 }
}

//Создать подкласс B, расширяющий класс A
class B extends A
{
 B()
 {
  System.out.println("Inside B constructor.");
 }
}

//Создать класс (C), расширяющий класс В
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. ObjectPodczas 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 GenConstructorokreśla niestandardowy parametr typu, który musi być klasą pochodną z class Number, można go wywołać z dowolnego
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION