Discussion:
Was ist an dieser Klasse falsch?
Add Reply
Peter Heitzer
2020-07-30 07:58:08 UTC
Antworten
Permalink
import java.util.*;
public class P extends Properties {
public String getProperty(String p) {
return super.getProperty(p,"de");
}
public static void main(String[] args) {
P x=new P();
x.setProperty("a","b");
System.out.println(x.getProperty(args[0]));
}
}
Es wird ohne Fehler übersetzt. Wenn man es aber startet bricht es mit
Stackoverflow ab. Ich kann mir nicht erklären, was hier passiert.
Die abgeleitete Klasse P überschreibt die Methode getProperty(String) und
ruft darin die Originalmethode getProperty(String,String) auf.
Das Laufzeitverhalten mit Stackoverflow schaut aber für mich so aus, als
ob die überschriebene Methode sich selbst aufruft.
Wer kann mir das Verhalten erklären?
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Michael Paap
2020-07-30 08:40:39 UTC
Antworten
Permalink
import java.util.*;
public class P extends Properties {
public String getProperty(String p) {
return super.getProperty(p,"de");
}
public static void main(String[] args) {
P x=new P();
x.setProperty("a","b");
System.out.println(x.getProperty(args[0]));
}
}
Es wird ohne Fehler übersetzt. Wenn man es aber startet bricht es mit
Stackoverflow ab. Ich kann mir nicht erklären, was hier passiert.
Die abgeleitete Klasse P überschreibt die Methode getProperty(String) und
ruft darin die Originalmethode getProperty(String,String) auf.
Das Laufzeitverhalten mit Stackoverflow schaut aber für mich so aus, als
ob die überschriebene Methode sich selbst aufruft.
Wer kann mir das Verhalten erklären?
Vorab: Es wäre sinnvoll, wenn du dein Posting nicht schon als Zitat
beginnen würdest. Wenn man dann z.B. den Code rauskopieren will, muss
man erst noch Zitatzeichen entfernen...

Zur Frage: Du rufst in deiner Methode getProperty() eine Methode der
Superklasse auf. Das könntest du übrigens auch ohne "super", weil es ja
nicht die Methode ist, die du überschrieben hast (unterschiedliche
Parameterzahl). Aber das ist nicht das Problem.

Das Problem besteht darin, dass die Methode, die du da aufrufst,
ihrerseits wieder die Methode getProperty() aufruft, die einen Parameter
mit Deklarationstyp String hat. Und das ist aufgrund dynamischer Bindung
dann wieder "deine" Methode getProperty(), womit du eine nette kleine
Endlosschleife gebaut hast.

Gruß
Michael
Peter Heitzer
2020-07-30 09:10:19 UTC
Antworten
Permalink
Post by Michael Paap
import java.util.*;
public class P extends Properties {
public String getProperty(String p) {
return super.getProperty(p,"de");
}
public static void main(String[] args) {
P x=new P();
x.setProperty("a","b");
System.out.println(x.getProperty(args[0]));
}
}
Es wird ohne Fehler übersetzt. Wenn man es aber startet bricht es mit
Stackoverflow ab. Ich kann mir nicht erklären, was hier passiert.
Die abgeleitete Klasse P überschreibt die Methode getProperty(String) und
ruft darin die Originalmethode getProperty(String,String) auf.
Das Laufzeitverhalten mit Stackoverflow schaut aber für mich so aus, als
ob die überschriebene Methode sich selbst aufruft.
Wer kann mir das Verhalten erklären?
Vorab: Es wäre sinnvoll, wenn du dein Posting nicht schon als Zitat
beginnen würdest. Wenn man dann z.B. den Code rauskopieren will, muss
man erst noch Zitatzeichen entfernen...
Ich hatte es ursprünglich in die falsche Gruppe gepostet und der Einfachheit (meiner
Faulheit geschuldet) hierhin als Following gepostet. Sorry dafür.
Post by Michael Paap
Zur Frage: Du rufst in deiner Methode getProperty() eine Methode der
Superklasse auf. Das könntest du übrigens auch ohne "super", weil es ja
nicht die Methode ist, die du überschrieben hast (unterschiedliche
Parameterzahl). Aber das ist nicht das Problem.
Das Problem besteht darin, dass die Methode, die du da aufrufst,
ihrerseits wieder die Methode getProperty() aufruft, die einen Parameter
mit Deklarationstyp String hat. Und das ist aufgrund dynamischer Bindung
dann wieder "deine" Methode getProperty(), womit du eine nette kleine
Endlosschleife gebaut hast.
Zu der Erkenntnis hat mit ein Kollege mittlerweile auch gebracht. Ich habe nicht
überrissen, daß in der Superklasse die originale einparametrige nicht mehr sichtbar
ist, sondern nur die überschriebene.

Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.

Danke auf jeden Fall für die prompte Hilfe.
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Michael Paap
2020-07-30 11:05:36 UTC
Antworten
Permalink
Post by Peter Heitzer
Zu der Erkenntnis hat mit ein Kollege mittlerweile auch gebracht. Ich habe nicht
überrissen, daß in der Superklasse die originale einparametrige nicht mehr sichtbar
ist, sondern nur die überschriebene.
Das Problem ist nicht Sichtbarkeit, sondern, dass "this", das Objekt,
auf dem du hantierst, ja ein P ist. Und dann wird eben auch die Methode
von P gewählt.
Post by Peter Heitzer
Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.
Dann wäre mein Tipp, eben keine Subklasse zu bilden und irgendwas zu
überschreiben, sondern in P ein Properties zu /verwenden/.

Gruß
Michael Paap
Patrick Roemer
2020-07-30 12:22:23 UTC
Antworten
Permalink
Post by Peter Heitzer
Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.
Warum nicht einfach zwei verschiedene Dateien, von denen je nach Wert
der Umgebungsvariablen die passende geladen wird?

Alternativ eine Bibliothek verwenden, die unterschiedliche
Konfigurationsblöcke bzw. -hierarchien innerhalb einer Datei explizit
unterstützt, z.B.

https://github.com/lightbend/config

Falls man doch lieber selber basteln will: Das Design der
Properties-Klasse ist eh schon fritte, alleine dadurch, dass sie von
Hashtable ableitet. Wenn man nur #getProperty() überschreibt, macht man
sich recht sicher irgendwo den Contract noch weiter kaputt - zusätzlich
zu klassischen Problemen beim Ableiten von konkreten Klassen wie im OP.
Besser also eine Wrapperklasse mit einer minimalen API, die auf die
konkreten Anforderungen zugeschnitten ist, wie von Michael vorgeschlagen.

Grundsätzlich sowieso: Favor composition over inheritance. [1]

Viele Grüße
Patrick

[1] https://en.wikipedia.org/wiki/Composition_over_inheritance
Peter Heitzer
2020-07-30 13:24:41 UTC
Antworten
Permalink
Post by Patrick Roemer
Post by Peter Heitzer
Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.
Warum nicht einfach zwei verschiedene Dateien, von denen je nach Wert
der Umgebungsvariablen die passende geladen wird?
Weil nicht alle Properties unterschiedliche Namen haben. Es gibt auch Properties, die
in beiden Fällen gleich sind. In einer Datei ist es IMO übersichtlicher.
Wenn z.B. steht
ServerPort=12345
TestServerPort=56789

sehe ich das eher als in zwei Dateien.

Ich habe es jetzt so gelöst:
Ich leite Properties ab, aber ich definiere get(String) und get(String,String),
welche getProperties aus der Basisklasse verwenden.
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Johannes Freiberger
2021-04-08 23:53:25 UTC
Antworten
Permalink
import java.util.*;
public class P extends Properties {
public String getProperty(String p) {
return super.getProperty(p,"de");
}
public static void main(String[] args) {
P x=new P();
x.setProperty("a","b");
System.out.println(x.getProperty(args[0]));
}
}
Es wird ohne Fehler übersetzt. Wenn man es aber startet bricht es mit
Stackoverflow ab. Ich kann mir nicht erklären, was hier passiert.
Die abgeleitete Klasse P überschreibt die Methode getProperty(String) und
ruft darin die Originalmethode getProperty(String,String) auf.
Das Laufzeitverhalten mit Stackoverflow schaut aber für mich so aus, als
ob die überschriebene Methode sich selbst aufruft.
Wer kann mir das Verhalten erklären?
Der Stacktrace sagt folgendes:
---------------------------
Exception in thread "main" java.lang.StackOverflowError
at java.base/java.util.Properties.getProperty(Properties.java:1142)
at MyClass.getProperty(MyClass.java:5)
at java.base/java.util.Properties.getProperty(Properties.java:1142)
at MyClass.getProperty(MyClass.java:5)
[...]
---------------------------

Die Codestelle 'java.util.Properties:1142' sieht so aus:
---------------------------
public String getProperty(String key, String defaultValue) {
!--> String val = getProperty(key);
return (val == null) ? defaultValue : val;
}
---------------------------

In der markierten Zeile wird die Methode 'getProperty' des Objektvariablentyps
aufgerufen. Und das ist deine Klasse P. Der Code springt also endlos zwischen
deiner Klasse und Properties hin und her, bis der Stack voll ist.

Wollte man dieses Verhalten beheben, so sähe der Fix wie folgt aus:

---------------------------
public String getProperty(String key, String defaultValue) {
!--> String val = this.getProperty(key);
return (val == null) ? defaultValue : val;
}
---------------------------

Mit 'this.getProperty(String)' würde die Methode derselben Klasse aufgerufen
und gäbe keine endlose Rekursion.

Ciao.
Johannes Freiberger
2021-04-09 01:04:30 UTC
Antworten
Permalink
Post by Johannes Freiberger
---------------------------
public String getProperty(String key, String defaultValue) {
!--> String val = this.getProperty(key);
return (val == null) ? defaultValue : val;
}
---------------------------
Mit 'this.getProperty(String)' würde die Methode derselben Klasse aufgerufen
und gäbe keine endlose Rekursion.
Vergiss es.
Habe es ausprobiert.
'this.getProperty()' verhält sich wie 'getProperty()'.

Du musst in Klasse P beide getProperty Methoden überschreiben:


P.getProperty(String)
P.getProperty(String, String)


und die Methode mit zwei Parametern ruft dann 'super.getProperty(String, String)'.
und die Methode mit einem Parameter ruft dann 'super.getProperty(String)'.

dann klappt es.
Post by Johannes Freiberger
Ciao.
Johannes Freiberger
2021-04-09 01:12:02 UTC
Antworten
Permalink
Post by Johannes Freiberger
Vergiss es.
Habe es ausprobiert.
'this.getProperty()' verhält sich wie 'getProperty()'.
P.getProperty(String)
P.getProperty(String, String)
und die Methode mit zwei Parametern ruft dann 'super.getProperty(String, String)'.
und die Methode mit einem Parameter ruft dann 'super.getProperty(String)'.
dann klappt es.
----------------------------------------
import java.util.Properties;

public class B extends Properties {

public String getProperty(String a)
{
return super.getProperty(a);
}
public String getProperty(String a, String b)
{
return super.getProperty(a, b);
}

public static void main(String[] args)
{
B b = new B();
b.setProperty("bb", "deHulk");
String x = b.getProperty("bb", "fallback");

System.out.println("X = " + x);
}
}
----------------------------------------
Post by Johannes Freiberger
Ciao.
Lesen Sie weiter auf narkive:
Suchergebnisse für 'Was ist an dieser Klasse falsch?' (Newsgroups und Mailinglisten)
91
Antworten
eigene Klasse (doppelt) zerstören
gestartet 2011-04-01 06:19:32 UTC
de.comp.lang.delphi.misc
44
Antworten
Falsches Pattern?
gestartet 2008-05-16 11:02:01 UTC
de.comp.lang.java
5
Antworten
MFC:Zugriff auf Variable in andere Klasse
gestartet 2005-01-11 23:19:03 UTC
microsoft.public.de.vc
30
Antworten
Freisprecheinrichtung bei DB E-Klasse.
gestartet 2007-11-24 11:42:14 UTC
de.comm.geraete.mobil.misc
Suchergebnisse für 'Was ist an dieser Klasse falsch?' (Fragen und Antworten)
11
Antworten
Was ist die beste Klasse für Anfänger in Dark Souls?
gestartet 2011-11-13 00:52:05 UTC
gaming
4
Antworten
Was ist falsch an diesem Sicherungssetup?
gestartet 2019-03-22 20:24:29 UTC
draußen
5
Antworten
Songstruktur: Was ist los mit Vers / Chorus / Vers 2 / Chorus / Vers 3 / Bridge / Chorus?
gestartet 2014-07-11 21:48:04 UTC
musik
2
Antworten
Was ist Höflichkeit in einem Fitnessstudio?
gestartet 2013-03-14 14:13:49 UTC
fitness
4
Antworten
Was ist der Unterschied zwischen einer hierarchischen linearen Regression und einer gewöhnlichen Regression der kleinsten Quadrate (OLS)?
gestartet 2013-07-08 13:44:40 UTC
statistiken
Nicht verwandte, aber interessante Themen
6
Antworten
Ist Arduino als humanoider Roboter-Controller geeignet?
gestartet 2010-08-26 13:52:43 UTC
6
Antworten
Was ist die Ursache für den Spannungsabfall an einem Widerstand?
gestartet 2016-01-21 22:29:37 UTC
5
Antworten
Eingangsspannung für 7805 auswählen
gestartet 2015-01-11 15:00:42 UTC
6
Antworten
Was ist der Zweck eines Mikrocontroller-Bootloaders?
gestartet 2016-04-15 14:45:28 UTC
6
Antworten
Was ist die maximale Anzahl von Ausgängen, die Sie von einem Mikrocontroller mit n Ausgängen steuern können?
gestartet 2014-07-08 13:24:24 UTC
Loading...