Szukaj…


Wprowadzenie

Chociaż nie jest to wymagane, konstruktory w Javie są metodami rozpoznawanymi przez kompilator do tworzenia określonych wartości dla klasy, które mogą być niezbędne do roli obiektu. W tym temacie pokazano prawidłowe użycie konstruktorów klas Java.

Uwagi

Specyfikacja języka Java mówi długo o dokładnej naturze semantyki konstruktora. Można je znaleźć w JLS §8.8

Domyślny konstruktor

„Domyślne” dla konstruktorów jest to, że nie mają one żadnych argumentów. Jeśli nie określisz żadnego konstruktora, kompilator wygeneruje dla ciebie domyślny konstruktor.
Oznacza to, że następujące dwa fragmenty są semantycznie równoważne:

public class TestClass {
    private String test;
}
public class TestClass {
    private String test;
    public TestClass() {

    }
}

Widoczność domyślnego konstruktora jest taka sama jak widoczność klasy. Zatem klasa zdefiniowana pakiet-prywatnie ma domyślnego konstruktora pakiet-prywatny

Jeśli jednak masz konstruktora innego niż domyślny, kompilator nie wygeneruje dla ciebie domyślnego konstruktora. Nie są one więc równoważne:

public class TestClass {
    private String test;
    public TestClass(String arg) {
    }
}
public class TestClass {
    private String test;
    public TestClass() {
    }
    public TestClass(String arg) {
    }
}

Uwaga: wygenerowany konstruktor nie wykonuje niestandardowej inicjalizacji. Oznacza to, że wszystkie pola twojej klasy będą miały swoją wartość domyślną, chyba że mają inicjalizator.

public class TestClass {

    private String testData;

    public TestClass() {
        testData = "Test"
    }
}

Konstruktory są nazywane w ten sposób:

TestClass testClass = new TestClass();

Konstruktor z argumentami

Konstruktory można tworzyć z dowolnymi argumentami.

public class TestClass {

    private String testData;

    public TestClass(String testData) {
        this.testData = testData;
    }
}

Nazywany tak:

TestClass testClass = new TestClass("Test Data");

Klasa może mieć wiele konstruktorów z różnymi podpisami. Aby połączyć wywołania konstruktora (podczas tworzenia instancji wywołaj innego konstruktora tej samej klasy), użyj this() .

public class TestClass {

    private String testData;

    public TestClass(String testData) {
        this.testData = testData;
    }

    public TestClass() {
        this("Test"); // testData defaults to "Test"
    }
}

Nazywany tak:

TestClass testClass1 = new TestClass("Test Data");
TestClass testClass2 = new TestClass();

Wywołaj konstruktora nadrzędnego

Załóżmy, że masz klasę dla rodziców i klasę dla dzieci. Aby zbudować instancję podrzędną, zawsze wymagany jest jakiś konstruktor nadrzędny, który musi być uruchamiany na samym początku konstruktora podrzędnego. Możemy wybrać żądany konstruktor nadrzędny, jawnie wywołując super(...) z odpowiednimi argumentami jako naszą pierwszą instrukcję konstruktora podrzędnego. Wykonanie tego pozwala zaoszczędzić nam czasu poprzez ponowne użycie konstruktora klas nadrzędnych zamiast przepisywania tego samego kodu w konstruktorze klas podrzędnych.

Bez metody super(...) :

(domyślnie wersja super() no-args jest wywoływana niewidocznie)

class Parent {
    private String name;
    private int age;
    
    public Parent() {} // necessary because we call super() without arguments
    
    public Parent(String tName, int tAge) {
        name = tName;
        age = tAge;
    }
}

// This does not even compile, because name and age are private,
// making them invisible even to the child class.
class Child extends Parent {
    public Child() {
        // compiler implicitly calls super() here
        name = "John";
        age = 42;
    }
}

Z super() metody:

class Parent {
    private String name;
    private int age;
    public Parent(String tName, int tAge) {
        name = tName;
        age = tAge;
    }
}

class Child extends Parent {
    public Child() {
        super("John", 42);   // explicit super-call
    }
}

Uwaga: Wywołania innego konstruktora (łańcuchowego) lub superkonstruktora MUSZĄ być pierwszą instrukcją wewnątrz konstruktora.

Jeśli jawnie wywołujesz konstruktor super(...) , musi istnieć zgodny konstruktor nadrzędny (to proste, prawda?).

Jeśli nie wywołujesz jawnie żadnego super(...) konstruktora, twoja klasa nadrzędna musi mieć konstruktor bez argumentów - i może to zostać zapisane jawnie lub utworzone domyślnie przez kompilator, jeśli klasa nadrzędna nie zapewnia dowolny konstruktor.

class Parent{
    public Parent(String tName, int tAge) {}
}

class Child extends Parent{
    public Child(){}
}

Klasa Parent nie ma domyślnego konstruktora, więc kompilator nie może dodać super w konstruktorze potomnym. Ten kod nie będzie się kompilował. Musisz zmienić konstruktory, aby pasowały do obu stron, lub napisać własne super wywołanie:

class Child extends Parent{
    public Child(){
          super("",0);
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow