Zoeken…


Invoering

Deze documentatie pagina is voor het tonen van informatie met bijvoorbeeld over Java-klasse constructeurs en ongeveer Object Klasse Methoden die automatisch worden overgenomen van de superklasse Object van alle nieuw gecreëerde klasse.

Syntaxis

  • openbare finale native Class <?> getClass ()
  • openbare finale native ongeldige kennisgeving ()
  • openbare finale native ongeldig kennisgevingAll ()
  • openbare finale native nietig wachten (lange time-out) gooit InterruptedException
  • openbare finale ongeldig wait () gooit InterruptedException
  • openbare finale ongeldige wachttijd (lange time-out, int nanos) gooit InterruptedException
  • openbare native int hashCode ()
  • public boolean is gelijk aan (Object obj)
  • public String toString ()
  • beschermde native Object clone () gooit CloneNotSupportedException
  • beschermde nietig finalize () gooit Throwable

toString () methode

De methode toString() wordt gebruikt om een String weergave van een object te maken met behulp van de inhoud van het object. Deze methode moet worden genegeerd bij het schrijven van je klas. toString() wordt impliciet aangeroepen wanneer een object wordt samengevoegd tot een tekenreeks zoals in "hello " + anObject .

Stel je de volgende situatie voor:

public class User {
    private String firstName;
    private String lastName;
    
    public User(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    @Override
    public String toString() {
        return firstName + " " + lastName;
    }
    
    public static void main(String[] args) {
        User user = new User("John", "Doe");
        System.out.println(user.toString()); // Prints "John Doe"
    }   
}

Hier wordt toString() van Object klasse Object overschreven door de klasse User om betekenisvolle gegevens over het object te geven bij het afdrukken.

Bij gebruik van println() wordt de methode toString() het object impliciet aangeroepen. Daarom doen deze uitspraken hetzelfde:

System.out.println(user); // toString() is implicitly called on `user`
System.out.println(user.toString());

Als de toString() niet wordt overschreven in de bovengenoemde User , kan System.out.println(user) User@659e0bfd of een vergelijkbare tekenreeks retourneren met vrijwel geen nuttige informatie behalve de User@659e0bfd . Dit zal zijn omdat de oproep van het zal gebruiken toString() de uitvoering van de basis Java Object klasse die niets over het weet User structuur of business rules klasse. Als u deze functionaliteit in uw klas wilt wijzigen, overschrijft u eenvoudig de methode.

is gelijk aan () methode

TL; DR

== tests voor referentie-gelijkheid (of ze hetzelfde object zijn )

.equals() testen voor waarde gelijkheid (of ze logisch "gelijk" zijn )


equals() is een methode die wordt gebruikt om twee objecten te vergelijken voor gelijkheid. De standaardimplementatie van de methode equals() in de klasse Object retourneert true als en alleen als beide verwijzingen naar dezelfde instantie wijzen. Het gedraagt zich daarom hetzelfde als vergelijking met == .

public class Foo {
    int field1, field2;
    String field3;

    public Foo(int i, int j, String k) {
        field1 = i;
        field2 = j;
        field3 = k;
    }

    public static void main(String[] args) {
        Foo foo1 = new Foo(0, 0, "bar");
        Foo foo2 = new Foo(0, 0, "bar");

        System.out.println(foo1.equals(foo2)); // prints false
    }
}

Hoewel foo1 en foo2 met dezelfde velden zijn gemaakt, wijzen ze naar twee verschillende objecten in het geheugen. De standaardimplementatie equals() wordt daarom als false geëvalueerd.

Als u de inhoud van een object wilt vergelijken voor gelijkheid, moet equals() worden genegeerd.

public class Foo {
    int field1, field2;
    String field3;

    public Foo(int i, int j, String k) {
        field1 = i;
        field2 = j;
        field3 = k;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }

        Foo f = (Foo) obj;
        return field1 == f.field1 &&
               field2 == f.field2 &&
               (field3 == null ? f.field3 == null : field3.equals(f.field3));
    }

    @Override
    public int hashCode() {
        int hash = 1;
        hash = 31 * hash + this.field1;
        hash = 31 * hash + this.field2;
        hash = 31 * hash + (field3 == null ? 0 : field3.hashCode());
        return hash;
    }

    public static void main(String[] args) {
        Foo foo1 = new Foo(0, 0, "bar");
        Foo foo2 = new Foo(0, 0, "bar");

        System.out.println(foo1.equals(foo2)); // prints true
    }
}

Hier bepaalt de overschreven equals() methode dat de objecten gelijk zijn als hun velden hetzelfde zijn.

Merk op dat de methode hashCode() ook is overschreven. Het contract voor die methode stelt dat wanneer twee objecten gelijk zijn, hun hash-waarden ook hetzelfde moeten zijn. Daarom moet men bijna altijd hashCode() en is equals() samen negeren.

Besteed speciale aandacht aan het argumenttype van de methode is equals . Het is Object obj , niet Foo obj . Als u deze laatste in uw methode opneemt, is dat geen opheffing van de methode is equals .

Wanneer u uw eigen klasse schrijft, moet u vergelijkbare logica schrijven bij het overschrijven van equals() en hashCode() . De meeste IDE's kunnen dit automatisch voor u genereren.

Een voorbeeld van een equals() -implementatie is te vinden in de klasse String , die deel uitmaakt van de kern-Java API. In plaats van pointers te vergelijken, vergelijkt de String klasse de inhoud van de String .

Java SE 7

Java 1.7 introduceerde de java.util.Objects klasse die een java.util.Objects biedt, is equals , die twee mogelijk null vergelijkt, zodat het kan worden gebruikt om implementaties van de equals methode te vereenvoudigen.

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
        return false;
    }

    Foo f = (Foo) obj;
    return field1 == f.field1 && field2 == f.field2 && Objects.equals(field3, f.field3);
}

Klasse vergelijking

Omdat de methode is gelijk aan elk object kan worden uitgevoerd, is een van de eerste dingen die de methode vaak doet (na controle op null ) te controleren of de klasse van het te vergelijken object overeenkomt met de huidige klasse.

@Override
public boolean equals(Object obj) {
    //...check for null
    if (getClass() != obj.getClass()) {
        return false;
    }
    //...compare fields
}

Dit wordt meestal gedaan zoals hierboven beschreven door de klasseobjecten te vergelijken. Dat kan echter in enkele speciale gevallen mislukken, wat misschien niet vanzelfsprekend is. Sommige frameworks genereren bijvoorbeeld dynamische proxy's van klassen en deze dynamische proxy's zijn eigenlijk een andere klasse. Hier is een voorbeeld met JPA.

Foo detachedInstance = ...
Foo mergedInstance = entityManager.merge(detachedInstance);
if (mergedInstance.equals(detachedInstance)) {
    //Can never get here if equality is tested with getClass()
    //as mergedInstance is a proxy (subclass) of Foo
}

Een mechanisme om die beperking te omzeilen is om klassen te vergelijken met behulp van instanceof

@Override
public final boolean equals(Object obj) {
    if (!(obj instanceof Foo)) {
        return false;
    }
    //...compare fields
}

Er zijn echter een paar valkuilen die moeten worden vermeden bij het gebruik van instanceof . Aangezien Foo mogelijk andere subklassen kan hebben en die subklassen equals() kunnen overschrijven equals() kunt u in een geval FooSubclass waarin een Foo gelijk is aan een FooSubclass maar de FooSubclass niet gelijk is aan Foo .

Foo foo = new Foo(7);
FooSubclass fooSubclass = new FooSubclass(7, false);
foo.equals(fooSubclass) //true
fooSubclass.equals(foo) //false

Dit is in strijd met de eigenschappen van symmetrie en transitiviteit en is dus een ongeldige implementatie van de methode equals() . Het is daarom een goede gewoonte om bij het gebruik van instanceof de methode equals() final (zoals in het bovenstaande voorbeeld). Dit zorgt ervoor dat geen subklasse overschrijft equals() en belangrijke veronderstellingen schendt.

hashCode () -methode

Wanneer een Java-klasse de methode equals overschrijft, moet deze ook de methode hashCode overschrijven. Zoals gedefinieerd in het contract van de methode :

  • Wanneer het meer dan eens op hetzelfde object wordt aangeroepen tijdens een uitvoering van een Java-toepassing, moet de hashCode methode consistent hetzelfde gehele getal retourneren, op voorwaarde dat er geen informatie wordt gebruikt die wordt gebruikt in vergelijkingen over het object. Dit gehele getal hoeft niet consistent te blijven van de ene uitvoering van een toepassing naar een andere uitvoering van dezelfde toepassing.
  • Als twee objecten gelijk zijn volgens de methode is gelijk equals(Object) , moet het aanroepen van de methode hashCode op elk van de twee objecten hetzelfde resultaat met gehele getallen produceren.
  • Het is niet vereist dat als twee objecten ongelijk zijn volgens de methode equals(Object) , het aanroepen van de methode hashCode op elk van de twee objecten duidelijke resultaten met gehele getallen moet produceren. De programmeur moet er echter rekening mee houden dat het produceren van afzonderlijke integer-resultaten voor ongelijke objecten de prestaties van hashtabellen kan verbeteren.

Hash-codes worden gebruikt in hash-implementaties zoals HashMap , HashTable en HashSet . Het resultaat van de hashCode functie bepaalt de bucket waarin een object wordt geplaatst. Deze hash-implementaties zijn efficiënter als de geleverde hashCode implementatie goed is. Een belangrijke eigenschap van een goede hashCode implementatie is dat de distributie van de hashCode waarden uniform is. Met andere woorden, er is een kleine kans dat meerdere exemplaren in dezelfde bucket worden opgeslagen.

Een algoritme voor het berekenen van een hashcodewaarde kan vergelijkbaar zijn met het volgende:

public class Foo {
    private int field1, field2;
    private String field3;

    public Foo(int field1, int field2, String field3) {
        this.field1 = field1;
        this.field2 = field2;
        this.field3 = field3;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }

        Foo f = (Foo) obj;
        return field1 == f.field1 &&
               field2 == f.field2 &&
               (field3 == null ? f.field3 == null : field3.equals(f.field3);
    }

    @Override
    public int hashCode() {
        int hash = 1;
        hash = 31 * hash + field1;
        hash = 31 * hash + field2;
        hash = 31 * hash + (field3 == null ? 0 : field3.hashCode());
        return hash;
    }
}

Arrays.hashCode () gebruiken als snelkoppeling

Java SE 1.2

In Java 1.2 en hoger, kan in plaats van een algoritme te ontwikkelen om een hash-code te berekenen, er een worden gegenereerd met java.util.Arrays#hashCode door een object- of primitievenmatrix te leveren die de veldwaarden bevat:

@Override
public int hashCode() {
    return Arrays.hashCode(new Object[] {field1, field2, field3});
}
Java SE 7

Java 1.7 introduceerde de java.util.Objects klasse die een java.util.Objects biedt, hash(Object... objects) , die een hash-code berekent op basis van de waarden van de objecten die eraan worden geleverd. Deze methode werkt net als java.util.Arrays#hashCode .

@Override
public int hashCode() {
    return Objects.hash(field1, field2, field3);
}

Opmerking: deze benadering is inefficiënt en produceert hashCode() objecten elke keer dat uw aangepaste hashCode() -methode wordt genoemd:

  • Er wordt een tijdelijk Object[] gemaakt. (In de versie Objects.hash() wordt de array gemaakt door het "varargs" -mechanisme.)
  • Als een van de velden primitieve typen zijn, moeten ze in een vak worden geplaatst en dat kan meer tijdelijke objecten maken.
  • De array moet worden ingevuld.
  • De array moet worden herhaald door de methode Arrays.hashCode of Objects.hash .
  • De aanroepen van Object.hashCode() die Arrays.hashCode of Objects.hash moet maken (waarschijnlijk) kunnen niet worden onderstreept.

Intern cachen van hashcodes

Omdat de berekening van de hash-code van een object duur kan zijn, kan het aantrekkelijk zijn om de hash-codewaarde in het object te cachen bij de eerste keer dat deze wordt berekend. Bijvoorbeeld

public final class ImmutableArray {
    private int[] array;
    private volatile int hash = 0;

    public ImmutableArray(int[] initial) {
        array = initial.clone();
    }

    // Other methods

    @Override
    public boolean equals(Object obj) {
         // ...
    }

    @Override
    public int hashCode() {
        int h = hash;
        if (h == 0) {
            h = Arrays.hashCode(array);
            hash = h;
        }
        return h;
    }
}

Deze benadering verrekent de kosten van het (herhaaldelijk) berekenen van de hash-code tegen de overhead van een extra veld om de hash-code in de cache te plaatsen. Of dit loont als prestatieoptimalisatie, hangt af van hoe vaak een bepaald object wordt gehasht (opgezocht) en andere factoren.

Je zult ook merken dat als de ware hashcode van een ImmutableArray toevallig nul is (één kans in 2 32 ), de cache niet effectief is.

Ten slotte is deze aanpak veel moeilijker correct te implementeren als het object dat we hashen veranderlijk is. Er zijn echter grotere zorgen als hash-codes veranderen; zie bovenstaand contract.

wacht () en meld () methoden

wait() en notify() werken samen - wanneer een thread oproepen wait() op een object, zal deze draad blokkeert totdat een andere thread oproepen notify() of notifyAll() op hetzelfde object.

(Zie ook: wachten () / melden () )

package com.example.examples.object;

import java.util.concurrent.atomic.AtomicBoolean;

public class WaitAndNotify {

    public static void main(String[] args) throws InterruptedException {
        final Object obj = new Object();
        AtomicBoolean aHasFinishedWaiting = new AtomicBoolean(false);
    
        Thread threadA = new Thread("Thread A") {
            public void run() {
                System.out.println("A1: Could print before or after B1");
                System.out.println("A2: Thread A is about to start waiting...");
                try {
                    synchronized (obj) { // wait() must be in a synchronized block
                        // execution of thread A stops until obj.notify() is called
                        obj.wait();
                    }
                    System.out.println("A3: Thread A has finished waiting. "
                            + "Guaranteed to happen after B3");
                } catch (InterruptedException e) {
                    System.out.println("Thread A was interrupted while waiting");
                } finally {
                    aHasFinishedWaiting.set(true);
                }
            }
        };
    
        Thread threadB = new Thread("Thread B") {
            public void run() {
                System.out.println("B1: Could print before or after A1");

                System.out.println("B2: Thread B is about to wait for 10 seconds");
                for (int i = 0; i < 10; i++) {
                    try {                        
                        Thread.sleep(1000); // sleep for 1 second 
                    } catch (InterruptedException e) {
                        System.err.println("Thread B was interrupted from waiting");
                    }
                }
            
                System.out.println("B3: Will ALWAYS print before A3 since "
                        + "A3 can only happen after obj.notify() is called.");
            
                while (!aHasFinishedWaiting.get()) {
                    synchronized (obj) {
                        // notify ONE thread which has called obj.wait()
                        obj.notify();
                    }
                }
            }
        };
    
        threadA.start();
        threadB.start();
    
        threadA.join();
        threadB.join();
    
        System.out.println("Finished!");
    }
}

Enkele voorbeelduitvoer:

A1: Could print before or after B1
B1: Could print before or after A1
A2: Thread A is about to start waiting...
B2: Thread B is about to wait for 10 seconds
B3: Will ALWAYS print before A3 since A3 can only happen after obj.notify() is called.
A3: Thread A has finished waiting. Guaranteed to happen after B3
Finished!

B1: Could print before or after A1
B2: Thread B is about to wait for 10 seconds
A1: Could print before or after B1
A2: Thread A is about to start waiting...
B3: Will ALWAYS print before A3 since A3 can only happen after obj.notify() is called.
A3: Thread A has finished waiting. Guaranteed to happen after B3
Finished!

A1: Could print before or after B1
A2: Thread A is about to start waiting...
B1: Could print before or after A1
B2: Thread B is about to wait for 10 seconds
B3: Will ALWAYS print before A3 since A3 can only happen after obj.notify() is called.
A3: Thread A has finished waiting. Guaranteed to happen after B3
Finished!

methode getClass ()

De methode getClass() kan worden gebruikt om het runtime- getClass() van een object te vinden. Zie onderstaand voorbeeld:

public class User {
   
    private long userID;
    private String name;

    public User(long userID, String name) {
        this.userID = userID;
        this.name = name;
    }
}

public class SpecificUser extends User {
    private String specificUserID;

    public SpecificUser(String specificUserID, long userID, String name) {
        super(userID, name);
        this.specificUserID = specificUserID;
    }
}

public static void main(String[] args){
    User user = new User(879745, "John");
    SpecificUser specificUser = new SpecificUser("1AAAA", 877777, "Jim");
    User anotherSpecificUser = new SpecificUser("1BBBB", 812345, "Jenny");

    System.out.println(user.getClass()); //Prints "class User"
    System.out.println(specificUser.getClass()); //Prints "class SpecificUser"
    System.out.println(anotherSpecificUser.getClass()); //Prints "class SpecificUser"
}

De methode getClass() retourneert het meest specifieke getClass() Daarom is de waarde bij terugkeer van getClass() op een anotherSpecificUser class SpecificUser omdat die lager is in de overervingsboom dan User .


Het is opmerkelijk dat, terwijl de getClass methode wordt verklaard als:

public final native Class<?> getClass();

Het werkelijke statische type dat wordt geretourneerd door een aanroep van getClass is Class<? extends T> waarbij T het statische type is van het object waarop getClass wordt aangeroepen.

dat wil zeggen het volgende zal compileren:

Class<? extends String> cls = "".getClass();

clone () methode

De methode clone() wordt gebruikt om een kopie van een object te maken en terug te sturen. Deze betwistbare methode moet worden vermeden omdat deze problematisch is en een kopieerconstructor of een andere kopieeraanpak moet worden gebruikt ten gunste van clone() .

Voor het gebruik van de methode moeten alle klassen die de methode aanroepen de Cloneable interface implementeren.

De Cloneable interface zelf is slechts een tag-interface die wordt gebruikt om het gedrag van de native clone() -methode te wijzigen, die controleert of de aanroepende objecten-klasse Cloneable implementeert. Als de beller deze interface niet implementeert, wordt een CloneNotSupportedException gegenereerd.

De klasse Object zelf implementeert deze interface niet, dus een CloneNotSupportedException wordt gegenereerd als het aanroepende object van de klasse Object .

Om een kloon correct te laten zijn, moet deze onafhankelijk zijn van het object waaruit wordt gekloond, daarom kan het nodig zijn om het object te wijzigen voordat het wordt teruggestuurd. Dit betekent in wezen een "diepe kopie" maken door ook een van de veranderlijke objecten te kopiëren die de interne structuur vormen van het object dat wordt gekloond. Als dit niet correct wordt geïmplementeerd, zal het gekloonde object niet onafhankelijk zijn en dezelfde verwijzingen naar de veranderlijke objecten hebben als het object waaruit het is gekloond. Dit zou tot inconsistent gedrag leiden, omdat wijzigingen in de ene de andere zouden beïnvloeden.

class Foo implements Cloneable {
    int w;
    String x;
    float[] y;
    Date z;
    
    public Foo clone() {
        try {
            Foo result = new Foo();
            // copy primitives by value
            result.w = this.w;
            // immutable objects like String can be copied by reference
            result.x = this.x;
            
            // The fields y and z refer to a mutable objects; clone them recursively.
            if (this.y != null) {
              result.y = this.y.clone();
            }
            if (this.z != null) {
              result.z = this.z.clone();
            }
            
            // Done, return the new object
            return result;
            
        } catch (CloneNotSupportedException e) {
            // in case any of the cloned mutable fields do not implement Cloneable
            throw new AssertionError(e);
        }
    }
}

finalize () methode

Dit is een beveiligde en niet-statische methode van de klasse Object . Deze methode wordt gebruikt om enkele laatste bewerkingen uit te voeren of bewerkingen op een object uit te voeren voordat het uit het geheugen wordt verwijderd.

Volgens de doc wordt deze methode door de afvalverzamelaar op een object aangeroepen wanneer de afvalinzameling bepaalt dat er geen verwijzingen meer zijn naar het object.

Er zijn echter geen garanties dat de methode finalize() wordt aangeroepen als het object nog steeds bereikbaar is of als Garbage Collectors worden uitgevoerd wanneer het object in aanmerking komt. Daarom is het beter om niet op deze methode te vertrouwen .

In Java-kernbibliotheken waren enkele gebruiksvoorbeelden te vinden, bijvoorbeeld in FileInputStream.java :

protected void finalize() throws IOException {
    if ((fd != null) &&  (fd != FileDescriptor.in)) {
        /* if fd is shared, the references in FileDescriptor
         * will ensure that finalizer is only called when
         * safe to do so. All references using the fd have
         * become unreachable. We can call close()
         */
        close();
    }
}

In dit geval is dit de laatste kans om de bron te sluiten als die bron nog niet eerder is gesloten.

Over het algemeen wordt het als een slechte gewoonte beschouwd om de methode finalize() in allerlei soorten toepassingen te gebruiken en moet dit worden vermeden.

Finalizers zijn niet bedoeld om bronnen vrij te maken (bijv. Bestanden sluiten). De vuilnisman wordt gebeld wanneer (als!) Het systeem weinig opslagruimte heeft. U kunt er niet op vertrouwen dat het wordt aangeroepen wanneer het systeem bijna geen bestandshandles heeft of om een andere reden.

De beoogde use-case voor finalisten is voor een object dat op het punt staat te worden teruggewonnen om een ander object op de hoogte te stellen van het naderende onheil. Voor dat doel bestaat er nu een beter mechanisme --- de klasse java.lang.ref.WeakReference<T> . Als u denkt dat u een methode finalize() moet schrijven, moet u onderzoeken of u in plaats daarvan hetzelfde probleem kunt oplossen met WeakReference . Als dat uw probleem niet oplost, moet u misschien uw ontwerp op een dieper niveau heroverwegen.

Voor meer informatie is hier een item over de methode finalize() uit het boek "Effective Java" van Joshua Bloch.

Object constructor

Alle constructeurs in Java moet een oproep aan het maken Object constructeur. Dit wordt gedaan met de aanroep super() . Dit moet de eerste regel in een constructor zijn. De reden hiervoor is dat het object daadwerkelijk op de heap kan worden gemaakt voordat aanvullende initialisatie wordt uitgevoerd.

Als u de aanroep van super() niet opgeeft in een constructor, wordt deze door de compiler voor u ingevoerd.

Dus alle drie deze voorbeelden zijn functioneel identiek

met expliciete aanroep van super() constructor

public class MyClass {

    public MyClass() {
        super();
    }
}

met impliciete aanroep naar super() constructor

public class MyClass {

    public MyClass() {
        // empty
    }
}

met impliciete constructor

public class MyClass {

}

Hoe zit het met Constructor-Chaining?

Het is mogelijk om andere constructors aan te roepen als de eerste instructie van een constructor. Omdat zowel de expliciete aanroep naar een superconstructor als de aanroep naar een andere constructor beide eerste instructies moeten zijn, sluiten ze elkaar uit.

public class MyClass {

    public MyClass(int size) {

        doSomethingWith(size);

    }

    public MyClass(Collection<?> initialValues) {

        this(initialValues.size());
        addInitialValues(initialValues);
    }
}

Het aanroepen van nieuwe MyClass(Arrays.asList("a", "b", "c")) zal de tweede constructor aanroepen met het List-argument, dat op zijn beurt zal delegeren aan de eerste constructor (die impliciet zal delegeren aan super() ) en roep vervolgens addInitialValues(int size) met de tweede grootte van de lijst. Dit wordt gebruikt om codeduplicaties te verminderen wanneer meerdere constructeurs hetzelfde werk moeten doen.

Hoe noem ik een specifieke constructeur?

Gegeven het bovenstaande voorbeeld kan men ofwel new MyClass("argument") of new MyClass("argument", 0) . Met andere woorden, net als bij overbelasting van methoden , roept u de constructor gewoon aan met de parameters die nodig zijn voor de door u gekozen constructor.

Wat gebeurt er in de objectklasseconstructor?

Niets meer dan zou gebeuren in een subklasse met een standaard lege constructor (minus de aanroep naar super() ).

De standaard lege constructor kan expliciet worden gedefinieerd, maar als dit niet het geval is, zal de compiler deze voor u invoeren zolang er nog geen andere constructors zijn gedefinieerd.

Hoe wordt een object vervolgens gemaakt van de constructor in Object?

De daadwerkelijke creatie van objecten is te danken aan de JVM. Elke constructor in Java verschijnt als een speciale methode met de naam <init> die verantwoordelijk is voor bijvoorbeeld initialisatie. Deze <init> -methode wordt geleverd door de compiler en omdat <init> geen geldig ID is in Java, kan deze niet rechtstreeks in de taal worden gebruikt.

Hoe roept de JVM deze <init> -methode op?

De JVM zal de <init> -methode gebruiken met behulp van de invokespecial instructie en kan alleen worden opgeroepen in niet-geïnitialiseerde klasseninstanties.

Bekijk voor meer informatie de JVM-specificatie en de Java Language Specification:



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow