Sinn von Konstruktorsyntax und finalize

WaterKnight

Neues Mitglied
Hi,
Bin neu bei Java, weniger aber allgemein bei Programmier- oder Skriptsprachen.

In Tutorials steht, man definiere Konstruktoren, indem man einer Methode denselben Namen gibt wie der Klasse. Also zum Beispiel

Java:
class Auto{
	public Auto(){...}
}

Wieso muss man das tun, warum gibt es nicht einfach ein Schlüsselwort für Konstruktorfunktionen? Zumal man zum Instanzieren dann nicht Auto.Auto() schreibt sondern new Auto(). Das hat zur Folge, dass ich den Namen aller Konstruktoren ändern muss, wenn ich den Klassennamen anpassen möchte und überhaupt Dinge mehrfach schreibe, was niemand gerne macht. (Ergänzend: Wenn ich nun ein zweites Objekt desselben Typs innerhalb der Klasse benötige, muss ich die Variable wieder als Auto deklarieren? Gibt es kein thistype?)

Daraus ergibt sich gleich meine zweite Frage. Wendet man wirklich new Auto() außerhalb der Klasse an? Erstens ist das irgendwie eine Extrasyntax, von der ich nicht weiß, warum sie nötig ist, zweitens sollten Klassen ja unabhängig sein, bei new wird aber zwangsweise ein neues Objekt allokiert. Es könnte doch auch sein, dass die Klasse mir stattdessen ein gecachetes Objekt zurückgeben will, um mit diesem zu arbeiten oder mir die Anfrage verweigern möchte.

3. Es wird ein Defaultkonstruktor angelegt, wenn man keine eigenen bestimmt. Auch hier verstehe ich den Sinn nicht. Wenn man ein Objekt anlegt, gibt es praktisch immer irgendetwas zu tun, um es zu registrieren und betriebsbereit zu machen. Man arbeitet nicht von außerhalb mit leeren Objekten. Deswegen sehe ich das nur als Fehlerquelle für sowas:

Java:
class Auto{
	public Autp(){...}
}

4. Als ich vom Destruktor finalize las und dass er vom Garbage Collector aufgerufen wird, dachte ich, das ist dann eigentlich nur zum Debugging gut, um zu schauen, ob Objekte wirklich freigegeben werden oder bei asynchronem Zeug, wo es nicht wirklich interessiert, wann die genau ins Gras beißen. Was passiert, wenn Objekte sich nur mehr gegenseitig referenzieren wie bei einer Linked List zum Beispiel, man aber auf keines der Objekte mehr zugreifen kann? Merkt der Collector das? Wobei ich eigene Destruktoren aber auch obligatorisch finde.

So, das wars erst einmal. Danke im Voraus für Antworten.
 

Noctarius

Top Contributor
In Java gibt es keinen Destruktor. finalize() darf der GC aufrufen, muss es aber nicht. Generell bekommt man in Java keine Information darüber wann das Objekt abgeräumt wird. Es kann sogar Stunden länger "leben" als es referenziert wurde, wenn der Speicher nicht voll läuft wird eventuell die gesamte Programmlaufzeit über nicht abgeräumt.
 
G

Gast2

Gast
Wieso muss man das tun, warum gibt es nicht einfach ein Schlüsselwort für Konstruktorfunktionen?
Keine Ahnung, hab ich mich aber auch noch nie gefragt um ehrlich zu sein :p

Das hat zur Folge, dass ich den Namen aller Konstruktoren ändern muss, wenn ich den Klassennamen anpassen möchte und überhaupt Dinge mehrfach schreibe, was niemand gerne macht.
Jede gute IDE kann refactorn, das ist dann nur ein Mausklick.

Wenn ich nun ein zweites Objekt desselben Typs innerhalb der Klasse benötige, muss ich die Variable wieder als Auto deklarieren? Gibt es kein thistype?
Nein, das gibts nicht.

Es könnte doch auch sein, dass die Klasse mir stattdessen ein gecachetes Objekt zurückgeben will, um mit diesem zu arbeiten oder mir die Anfrage verweigern möchte.
Dafür gibts dann bspw. Factories.

3. Es wird ein Defaultkonstruktor angelegt, wenn man keine eigenen bestimmt. Auch hier verstehe ich den Sinn nicht. Wenn man ein Objekt anlegt, gibt es praktisch immer irgendetwas zu tun, um es zu registrieren und betriebsbereit zu machen.
Nein, es gibt nicht zwangläufig immer was zu initialisieren.
Java:
public class Counter {
  private int counter;

  public void getAndIncrement()
    return counter++;
  }
}
Hier braucht man keinen Konstruktor.

Java:
class Auto{
    public Autp(){...}
}
Das kompiliert dir der Compiler nicht.

zu 4:
finalize braucht man nicht und sollte man vermeiden.
Und ja, der garbage collector merkts wenn sich Objekte gegenseitig referenzieren aber keine Verbindung mehr zu deiner Anwendung haben. Die werden dann trotzdem weggeräumt.
 

XHelp

Top Contributor
Wieso muss man das tun, warum gibt es nicht einfach ein Schlüsselwort für Konstruktorfunktionen?
Weil es so ist :bahnhof:
Das hat zur Folge, dass ich den Namen aller Konstruktoren ändern muss, wenn ich den Klassennamen anpassen möchte und überhaupt Dinge mehrfach schreibe, was niemand gerne macht.
Jede IDE kann vernünftig umbenennen.
(Ergänzend: Wenn ich nun ein zweites Objekt desselben Typs innerhalb der Klasse benötige, muss ich die Variable wieder als Auto deklarieren? Gibt es kein thistype?)
Ja, musst du.

Daraus ergibt sich gleich meine zweite Frage. Wendet man wirklich new Auto() außerhalb der Klasse an? Erstens ist das irgendwie eine Extrasyntax, von der ich nicht weiß, warum sie nötig ist, zweitens sollten Klassen ja unabhängig sein, bei new wird aber zwangsweise ein neues Objekt allokiert. Es könnte doch auch sein, dass die Klasse mir stattdessen ein gecachetes Objekt zurückgeben will, um mit diesem zu arbeiten oder mir die Anfrage verweigern möchte.
hä? Extrasyntax? Gecachtes Objekt bei
Code:
new
?

Wenn man ein Objekt anlegt, gibt es praktisch immer irgendetwas zu tun
Auch diese Aussage ergibt nur bedingt Sinn. Warum muss man im Konstruktor etwas machen? Du kannst ja eine Bean nur mit getter und setter haben o.ä.
Und dein Beispiel ist keine Fehlerquelle, sondern Unfähigkeit des Programmierers, ganz davon mal abgesehen, dass es nicht mal kompilieren wird

4. Als ich vom Destruktor finalize las...
finalize solltest du nicht verwenden, es gibt keine Garantie, dass es aufgerufen wird.
Was passiert, wenn Objekte sich nur mehr gegenseitig referenzieren...
Betrachte den GarbageCollector als eine BlackBox die schon weiß, was die macht. Die Funktionsweise ist recht abgefahren. Wenn du es wirklich wissen willst, dann gibt es auf der Oracle-Seite bestimmt genügend Dokumentation dazu.
 
A

asdasdasasd

Gast
Warum können Vögel fliegen?

Na wieso die Entwickler das so gemacht haben, wer weiß das schon?
Wieso schreibt man in php für eine Funktion
PHP:
function machwas{}
?
Es ist so wie es ist. Entweder man nimmt es hin oder man wird kein Programmierer.

Sorry du stellst fragen die fast Sinnfrei sind.
Bis auf die letzte frage, aber die wurde dir ja schon beantwortet ;)
 

schalentier

Gesperrter Benutzer
In Tutorials steht, man definiere Konstruktoren, indem man einer Methode denselben Namen gibt wie der Klasse.

Ich wuerd eher sagen, der Konstruktor bei Java ist eine Methode, die gar keinen Namen hat, sondern nur einen Rueckgabewert - vom Typ der Klasse selbst.

[c]new[/c] ist imho in der Tat keine besonders geschickte Entscheidung gewesen. In anderen Sprachen ist new meistens eine Methode der Klasse selbst, so dass man zum Erstellen einer einfachen Factory keine zusaetzliche Klasse braucht. Aber so ist es eben ;-)
 
G

Gast2

Gast
Es hindert dich doch nichts daran aus "new" eine Factory Methode zu machen, dann hast du doch was du brauchst oder nicht?

Java:
public class Counter  {
  private String name;
  private Counter(String name) {
    this.name = name;
  }

  // ...
  public static Counter newInstance(String name) {
    if (isCached(name)) return getCachedInstance(name));
    
    // build new Counter, cache it and return it
  }
}
Dafür brauchts ja keine extra Factory Klasse.
 

schalentier

Gesperrter Benutzer
Ja, natuerlich geht das ;-)

Aber wenn man einmal viele [c]new[/c] Aufrufe in seinem Code hat, isses schwierig sowas spaeter einzubauen.

Mir ist klar, das [c]new[/c] ansich schon ein Codesmell ist. Eben genau aus diesem Grund.
 
N

nillehammer

Gast
[OT]Ich habe hier jetzt zwei Mal die Aussage gelesen, dass man sich nicht sicher sein könne, ob finalize aufgerufen wird. Ich hatte da ein anderes Verständnis (kann natürlich falsch sein). Ich dachte, dass finalize beim Abräumen des Objektes durch den GC auf jeden Fall aufgerufen wird. Und dass die Unsicherheit nur darin besteht, dass man eben nicht weiß, wann der GC das Objekt abräumt und damit, wann finalize aufgerufen wird.

Oder waren die Aussagen so zu verstehen, dass man sich nicht sicher sein kann, ob ein Objekt überhaupt abgeräumt wird und damit ob finalize aufgerufen wird?[/OT]
Den Rest (finalize nur in Ausnahmefällen benutzen) kann ich so unterschreiben.
 

WaterKnight

Neues Mitglied
In Java gibt es keinen Destruktor. finalize() darf der GC aufrufen, muss es aber nicht. Generell bekommt man in Java keine Information darüber wann das Objekt abgeräumt wird. Es kann sogar Stunden länger "leben" als es referenziert wurde, wenn der Speicher nicht voll läuft wird eventuell die gesamte Programmlaufzeit über nicht abgeräumt.

Das habe ich schon verstanden. Wenn ich mein Auto nun verschrotten möchte, würde ich es aber trotzdem gerne abmelden und wenn ich nur eine Klassenvariable habe, die alle meine Autos zählt. Also auch wenn es keine native Destruktion ist, dann doch eine semantische. Sollte man dann natürlich aufpassen, dass man das Objekt nicht mehr als lebendig behandelt.

Jede gute IDE kann refactorn, das ist dann nur ein Mausklick.

Dafür gibts dann bspw. Factories.

factorn = macroen? Oder geht es nur um die Konstruktoren?

Arbeite zurzeit nur mit Notepad, um die Grundlagen zu verstehen und sie von dem unterscheiden zu können, was die Entwicklungsumgebungen machen.

Java:
public class Counter {
  private int counter;

  public void getAndIncrement()
    return counter++;
  }
}
Hier braucht man keinen Konstruktor.

Würde mich zumindest sicherer fühlen, die Variable zu initialisieren.

Java:
class Auto{
    public Autp(){...}
}
Das kompiliert dir der Compiler nicht.

Mit void schon, aber anderes Beispiel wäre

Java:
class Auto{
	public void Auto(int a){...}
}

und ich vergesse jetzt im Aufruf den Parameter. Na gut, versuche ich halt void zu vermeiden.

hä? Extrasyntax? Gecachtes Objekt bei
Code:
new
?

Man könnte stattdessen auch

Java:
class Auto{
	static public Auto Create(){
		Auto result = ...

		return result;
	}
}

Auto meinAuto = Auto.Create();

Dann kann ich in der Klasse beliebig einstellen, welches Objekt ich zurückgeben möchte oder vielleicht auch null, wurde schon als Factory mittlerweile betitelt. Dass man von außerhalb new anwendet, kann ich mir nur so erklären, dass das aufrufende Skript explizit wissen soll, ob es ein gänzlich neues Objekt bekommt.

asdasdasasd hat gesagt.:
Warum können Vögel fliegen?

[...]

Sorry du stellst fragen die fast Sinnfrei sind.

Ähm nein. Ich habe nach Alternativen gefragt, wie es in der Praxis aussieht und ob es wirklich Gründe gibt, weil es mich interessiert. Schlechte Programmierer sind die, die sich nicht fragen, wie die Dinge funktionieren, wie man Dinge verbessern könnte oder die sich nicht weiterentwickeln wollen. Außerdem gibt es viele Sprachen. Da darf man sich doch über Vor- und Nachteile informieren.

Ich sehe schon. Das Forum ist sehr aktiv. Danke für die Antworten.
 
Zuletzt bearbeitet:

schalentier

Gesperrter Benutzer
Dann darf man sich aber auch an die eigene Nase packen und den Mist ausbaden ;)

Zweifellos hast du Recht, allerdings darf man dann schon mal die Frage stellen, weshalb es ueberhaupt [c]new[/c] in dieser Form gibt, wenn man es ja eh nicht einsetzen sollte...

[c]finalize[/c] ist auch ne ziemlich gefaehrliche Sache, da (wie bereits gesagt) unklar ist, wann und ob es aufgerufen wird und der Zustand des Objektes nicht definiert ist. Es kann z.B. sein, dass einige Felder bereits vom GC aufgeraeumt wurden, andere nicht. Zu viel mehr als zu Debugging-/Loggingzwecken wuerde ich es nicht verwenden.
 
N

nillehammer

Gast
WaterKnight hat gesagt.:
factorn = macroen? Oder geht es nur um die Konstruktoren?
Ist ein eingedeutschtes Wort. Kommt vom englischen "to refactor" und bezeichnet die Umstrukturierung von Code durch Umbenennung/Verschieben von Klassen, Methoden etc. Im Notepad macht sowas keinen Spaß. IDEs unterstützen einen dabei sehr gut (bspw. Umbenennung aller Referenzen auf einen Klassennamen, Anpassen von import-Statements etc.)
WaterKnight hat gesagt.:
Würde mich zumindest sicherer fühlen, die Variable zu initialisieren.
Implizit wird jede Instanz-/und auch Klassenvariable initialisiert. Primitive Zahltypen mit 0/0.0, Unterklassen von Object (also alles andere) mit null. Nur innerhalb von Methoden muss man explizit initialisieren.
WaterKnight hat gesagt.:
Dann kann ich in der Klasse beliebig einstellen, welches Objekt ich zurückgeben möchte oder vielleicht auch null, wurde schon als Factory mittlerweile betitelt. Dass man von außerhalb new anwendet, kann ich mir nur so erklären, dass das aufrufende Skript explizit wissen soll, ob es ein gänzlich neues Objekt bekommt.
Das ist der Entwicklergemeinde auch schon aufgefallen und es haben sich dafür Patterns wie Factories oder Verfahren wie Dependency-Injection etabliert. Ein umsichtiger Klassendesigner sollte also nur in Ausnahmefällen seine Konstruktoren public machen. Diese Ausnahmefälle sind aber relativ häufig, weil es viele Frameworks gibt, die bei bestimmten Klassen die Einhaltung der sog. Bean-Konvention erfordern. Diese besagt u.a., dass es einen parameterlosen public Konstruktor geben muss. Die Sprache Java und auch die Bean-Konvention sind ja nun schon auch etwas älter. Vielleicht kannst Du damit leben, dass es eben noch eine Art Altlast ist.
 
Zuletzt bearbeitet von einem Moderator:

Noctarius

Top Contributor
[OT]Ich habe hier jetzt zwei Mal die Aussage gelesen, dass man sich nicht sicher sein könne, ob finalize aufgerufen wird. Ich hatte da ein anderes Verständnis (kann natürlich falsch sein). Ich dachte, dass finalize beim Abräumen des Objektes durch den GC auf jeden Fall aufgerufen wird. Und dass die Unsicherheit nur darin besteht, dass man eben nicht weiß, wann der GC das Objekt abräumt und damit, wann finalize aufgerufen wird.

Es kann sein, dass beim Beenden der GC einen "Finalizer" noch nicht aufgerufen hat. Dieser wird dann auch nicht mehr aufgerufen und die entsprechenden Methoden welche dies erzwingen sollen sind explizit als "pfui" deklariert.
Daher ist es zum Aufräumen nur bedingt zu gebrauchen und generell nur noch zu nutzen wenn man unbedingt noch nativen Code ausführen muss (und auch hier bleibt vorher stehendes Problem bestehen).

Es gibt allerdings eine Methode (PhantomReferences) sich vom GC sagen zu lassen welche Objekte abgeräumt wurden. Ich hatte aber bisher genau einen Fall (ein Framework) wo ich dies gebraucht habe, Finalizer habe ich noch nie benutzt.

Generell ist in Java die Nutzung von solchen Dingen auch vielleicht 0,1% aller Fälle beschränkt. Mit dem neuen (in Java 7 eingeführten) try-with-resource kann man übrigens automatisch "aufräumen" sobald man ein Objekt nicht mehr benötigt. Dazu muss das Objekt lediglich das Interface AutoCloseable implementieren und dann kann man mit nachfolgendem Konstrukt arbeiten:
Java:
try (AutoCloseableImpl foo = getSomething()) {
    // do some stuff with foo
} // at this point foo.close() will automatically be called

Dies ist die implzierte Form von folgendem:
Java:
AutoCloseableImpl foo = null;
try {
    foo = getSomething();
    // do some stuff with foo
} finally {
    if (foo != null)
        foo.close(); // at this point foo.close() will be called
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Interfaces von Interfaces macht das noch Sinn? Java Basics - Anfänger-Themen 21
F Hat es noch einen Sinn, alte Versionen zu lernen Java Basics - Anfänger-Themen 45
berserkerdq2 Wo ist der SInn, dass man den Stream, den ich zum Schreiben nutze, outputstream nenne? Java Basics - Anfänger-Themen 5
H Sinn von Interfaces Java Basics - Anfänger-Themen 21
W Sinn eines Singleton ? Java Basics - Anfänger-Themen 14
R getUserProperties() macht für mich keinen Sinn Java Basics - Anfänger-Themen 8
E Sinn: final in Parameterliste verwenden Java Basics - Anfänger-Themen 2
B Sinn von Lambdas? Java Basics - Anfänger-Themen 16
5 Welchen Sinn hat ein Runnable Java Basics - Anfänger-Themen 6
P OOP Sinn von abstrakten Klassen Java Basics - Anfänger-Themen 2
M Kapselung Datenkapselung Sinn direkter Zugriff? Java Basics - Anfänger-Themen 1
B Der Sinn von Arrays Java Basics - Anfänger-Themen 2
Q Container sinn? Java Basics - Anfänger-Themen 3
S string index out of range - es ergibt keinen Sinn Java Basics - Anfänger-Themen 6
C Sinn eines Interfaces? Java Basics - Anfänger-Themen 4
J Sinn/Nutzen von Scanner Java Basics - Anfänger-Themen 23
B Sinn von Reflections Java Basics - Anfänger-Themen 10
H Vererbung Prinzip der Ersetzbarkeit-Sinn? Java Basics - Anfänger-Themen 9
F Sinn der SuppressWarnings("unused")-Annotation Java Basics - Anfänger-Themen 5
R Sinn des programmes Java Basics - Anfänger-Themen 10
J Worin besteht der Sinn und Anwendungsbereich von Dreidimensionalen Arrays? Java Basics - Anfänger-Themen 11
J Datentypen Was ist der Sinn vom Datentyp "char" ? Java Basics - Anfänger-Themen 11
T Sinn von finally? Java Basics - Anfänger-Themen 3
M Variablen Zinseszinsberechnung - Variable ergibt keinen Sinn Java Basics - Anfänger-Themen 15
A Klassen Sinn des Konstruktors Java Basics - Anfänger-Themen 12
P Sinn des Security Managers Java Basics - Anfänger-Themen 2
J Welchen Sinn haben abstrakte Methoden? Java Basics - Anfänger-Themen 4
D Sinn von Jar Dateien Java Basics - Anfänger-Themen 5
D Sinn von Interfaces - Wozu? Java Basics - Anfänger-Themen 9
K Sinn eigener Exceptions Java Basics - Anfänger-Themen 11
Luk10 Sinn von Instanzierung ohne Referenz Java Basics - Anfänger-Themen 7
hdi Sinn von RuntimeExceptions? Java Basics - Anfänger-Themen 90
Developer_X NullPointer Exception ohne Sinn Java Basics - Anfänger-Themen 19
L Sinn hinter Generic? Java Basics - Anfänger-Themen 5
M Der Java Schlüsselwort null; ?Welche Anweisung und Sinn? Java Basics - Anfänger-Themen 12
A Macht es Sinn Arraylisten mit Gettern zu übergeben? Java Basics - Anfänger-Themen 19
M Variable überwachen und Sinn eines Threads Java Basics - Anfänger-Themen 7
G Sinn vo OOP Java Basics - Anfänger-Themen 5
P Unterschied zwischen Interface und Vererbung und Sinn? Java Basics - Anfänger-Themen 5
G sinn von JList Java Basics - Anfänger-Themen 6
K Sinn von Interfaces Java Basics - Anfänger-Themen 10
K finalize() Problem Java Basics - Anfänger-Themen 9
H Finalize Block blockiert Programmablauf Java Basics - Anfänger-Themen 15
U Frage zu finalize() Java Basics - Anfänger-Themen 8
D finalize()-Methode wird nicht aufgerufen Java Basics - Anfänger-Themen 3
N Wann und wie oft finalize Methode verwenden( überschreiben ) Java Basics - Anfänger-Themen 6
G Frage zu Finalize - Methode Java Basics - Anfänger-Themen 4

Ähnliche Java Themen

Neue Themen


Oben