Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > de.comp.lang.java > #13346 > unrolled thread
| Started by | "Peter Heitzer" <peter.heitzer@rz.uni-regensburg.de> |
|---|---|
| First post | 2020-07-30 07:58 +0000 |
| Last post | 2021-04-09 03:12 +0200 |
| Articles | 9 — 4 participants |
Back to article view | Back to de.comp.lang.java
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Was ist an dieser Klasse falsch? "Peter Heitzer" <peter.heitzer@rz.uni-regensburg.de> - 2020-07-30 07:58 +0000
Re: Was ist an dieser Klasse falsch? Michael Paap <feunews@mpaap.de> - 2020-07-30 10:40 +0200
Re: Was ist an dieser Klasse falsch? "Peter Heitzer" <peter.heitzer@rz.uni-regensburg.de> - 2020-07-30 09:10 +0000
Re: Was ist an dieser Klasse falsch? Michael Paap <feunews@mpaap.de> - 2020-07-30 13:05 +0200
Re: Was ist an dieser Klasse falsch? Patrick Roemer <sangamon@netcologne.de> - 2020-07-30 14:22 +0200
Re: Was ist an dieser Klasse falsch? "Peter Heitzer" <peter.heitzer@rz.uni-regensburg.de> - 2020-07-30 13:24 +0000
Re: Was ist an dieser Klasse falsch? Johannes Freiberger <nomail@space.invalid> - 2021-04-09 01:53 +0200
Re: Was ist an dieser Klasse falsch? Johannes Freiberger <nomail@space.invalid> - 2021-04-09 03:04 +0200
Re: Was ist an dieser Klasse falsch? Johannes Freiberger <nomail@space.invalid> - 2021-04-09 03:12 +0200
| From | "Peter Heitzer" <peter.heitzer@rz.uni-regensburg.de> |
|---|---|
| Date | 2020-07-30 07:58 +0000 |
| Subject | Re: Was ist an dieser Klasse falsch? |
| Message-ID | <hofcsgFk3c6U2@mid.individual.net> |
Peter Heitzer <peter.heitzer@rz.uni-regensburg.de> wrote:
>Ich habe ein Verständnisproblem mit folgendem kleinen Stück Javacode:
>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, peter.heitzer@rz.uni-regensburg.de
[toc] | [next] | [standalone]
| From | Michael Paap <feunews@mpaap.de> |
|---|---|
| Date | 2020-07-30 10:40 +0200 |
| Message-ID | <rfu129$1lif$1@news-cypress.fernuni-hagen.de> |
| In reply to | #13346 |
Am 30.07.2020 um 09:58 schrieb Peter Heitzer:
> Peter Heitzer <peter.heitzer@rz.uni-regensburg.de> wrote:
>> Ich habe ein Verständnisproblem mit folgendem kleinen Stück Javacode:
>
>> 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
[toc] | [prev] | [next] | [standalone]
| From | "Peter Heitzer" <peter.heitzer@rz.uni-regensburg.de> |
|---|---|
| Date | 2020-07-30 09:10 +0000 |
| Message-ID | <hofh3rFkljtU2@mid.individual.net> |
| In reply to | #13347 |
Michael Paap <feunews@mpaap.de> wrote:
>Am 30.07.2020 um 09:58 schrieb Peter Heitzer:
>> Peter Heitzer <peter.heitzer@rz.uni-regensburg.de> wrote:
>>> Ich habe ein Verständnisproblem mit folgendem kleinen Stück Javacode:
>>
>>> 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.
>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, peter.heitzer@rz.uni-regensburg.de
[toc] | [prev] | [next] | [standalone]
| From | Michael Paap <feunews@mpaap.de> |
|---|---|
| Date | 2020-07-30 13:05 +0200 |
| Message-ID | <rfu9i1$1sdt$1@news-cypress.fernuni-hagen.de> |
| In reply to | #13348 |
Am 30.07.2020 um 11:10 schrieb 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. > 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
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2020-07-30 14:22 +0200 |
| Message-ID | <rfue1v$lc0$1@newsreader4.netcologne.de> |
| In reply to | #13348 |
Responding to 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
[toc] | [prev] | [next] | [standalone]
| From | "Peter Heitzer" <peter.heitzer@rz.uni-regensburg.de> |
|---|---|
| Date | 2020-07-30 13:24 +0000 |
| Message-ID | <hog00pFn44bU2@mid.individual.net> |
| In reply to | #13350 |
Patrick Roemer <sangamon@netcologne.de> wrote: >Responding to 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, peter.heitzer@rz.uni-regensburg.de
[toc] | [prev] | [next] | [standalone]
| From | Johannes Freiberger <nomail@space.invalid> |
|---|---|
| Date | 2021-04-09 01:53 +0200 |
| Message-ID | <h85v6gtsaasp53fth710kht3lgi46m4vsb@4ax.com> |
| In reply to | #13348 |
>>> Peter Heitzer <peter.heitzer@rz.uni-regensburg.de> wrote:
>>>> Ich habe ein Verständnisproblem mit folgendem kleinen Stück Javacode:
>>>
>>>> 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.
[toc] | [prev] | [next] | [standalone]
| From | Johannes Freiberger <nomail@space.invalid> |
|---|---|
| Date | 2021-04-09 03:04 +0200 |
| Message-ID | <sq9v6g5njnp17ktmle5akoti4vmujdonal@4ax.com> |
| In reply to | #13375 |
On Fri, 09 Apr 2021 01:53:25 +0200, Johannes Freiberger <nomail@space.invalid> wrote:
>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.
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.
>
>Ciao.
[toc] | [prev] | [next] | [standalone]
| From | Johannes Freiberger <nomail@space.invalid> |
|---|---|
| Date | 2021-04-09 03:12 +0200 |
| Message-ID | <8eav6g9opsombg5puml2be8gr9d03dk6ou@4ax.com> |
| In reply to | #13376 |
On Fri, 09 Apr 2021 03:04:30 +0200, Johannes Freiberger <nomail@space.invalid> wrote:
>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.
----------------------------------------
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);
}
}
----------------------------------------
>
>>
>>Ciao.
[toc] | [prev] | [standalone]
Back to top | Article view | de.comp.lang.java
csiph-web