Java-Dau-Anfängerproblem...
Geizhals » Forum » Programmierung » Java-Dau-Anfängerproblem... (63 Beiträge, 241 Mal gelesen) Top-100 | Fresh-100
Du bist nicht angemeldet. [ Login/Registrieren ]
Java-Dau-Anfängerproblem...
11.07.2005, 13:50:53
Hi, Folks !

Habe mich in letzter Zeit wieder besseren Wissens in Java eingearbeitet...
Und hab' grad ein Micky-Maus-Prob:


public class Vater {

protected Vater() {}

public static boolean add ( int x ) {
return true;
}
}

public class Sohn extends Vater {

public static void main(String[] args) {
Sohn s = new Sohn();
Sohn.add(2);
}

public static int add ( int x ) {
return x;
}
}

---> Das ist nicht erlaubt - er motzt, weil die Methode add bei gleichen Parameter in Vater einen anderen Rückgabewert liefert als in Sohn...

Also in c++ wäre das erlaubt ;-).

Wozu braucht ma des ?

Also als Java-Laie dachte ich mir das wie folgt (und mußte daher schon viel umschreiben):
Es gibt eine Klasse Person - mit private-Gschichtln wie Zuname, Vorname, Gebdatum, ...
Person habe einen protected-Constructor - damit niemand selbst eine Person anlegen kann. Stattdessen gibt es eine Klassenmethode
> public static Person add(String Zuname, String Vorname, GregorianCal... GebDatum) - die zuerst mal nachsieht (in einem HashSet), ob es die Person schon gibt. wenn es sie gibt, liefert sie die bekannte Person zurück - wenn nicht, legt sie eine neue an und liefert die zurück. Grund: Auf diese Art will ich doppelte Personen vermeiden.

von Person gibt es eine abgeleitete Klasse Personal: sie hat dieselben Gschichtln wie Person - plus Job/Funktion, ...
Sie hat wieder einen protected Konstruktor - gleicher Grund wie bei Person.
Personal habe eine Reihe von Klassenmethoden "add"  -
so auch ein
> public static Personal add(String Zuname, String Vorname, GregorianCal... GebDatum)
---> Und genau da fetzt diese "$&%"!! Java-VM - eben wegen dem Rückgabewert von add().

Mir ist das ja komplett unklar...
Erstens sprech' ich hier von Klassenmethoden - also nix mit VMT. Irgendeine ominöse Forderung, warum das verboten sei in sauberen Design will noch nicht in meinen kleinen Schädel.
Zweitens ist mir der Workaround unklar...
Person::add() private machen nutzt auch nix - wieso net ???
Drittens scheint ein Object zurückliefern zwar als möglich aber bescheiden - denn jeder Aufrufende muß dann casten bzw. ein instanceOf scheint problematisch...
EDIT:
Viertens bin ich jetzt auf ein addPerson(), addPersonal(), ... ausgewichen - nur das ist ja auch besch*en... denn wozu sollte jede Klasse dann Trilliarden vererbter Methoden mitführen müssen ?

Ach ja, das bequeme Äquivalent in C++, das funktioniert:
class vater {
        public:
        static int add(int x);
};

int vater::add(int x)
{
        return 2;
}

class sohn: public vater
{
        public:
        static float add(int x);
};

float sohn::add(int x)
{
        return 2.3f;
}

int main() {
        sohn *s = new sohn();
        float f = s->add(2);
}



So oder so - ich denke wahrscheinlich zu C++-lastig...
wie macht man das sauber in Java ? Und /was/ ist der Hintergedanke von dieser IMHO stupiden, sinnlosen Limitierung ???

cu
ein frustrierter gepeinigter

11.07.2005, 14:10 Uhr - Editiert von gepeinigter_aon_neukunde, alte Version: hier
Antworten PM Übersicht Chronologisch
 
Melden nicht möglich
.
Re: Java-Dau-Anfängerproblem...
11.07.2005, 17:13:42
1.) C++ war schon immer sehr lax, deshalb strotzen die Programme meist vor Fehlern. Ich weiß, wovon ich spreche. Ich bin Softwareentwickler ;-)
Bei deinem C++Beispiel gibt's im Übrigen auch einen gewaltigen Pferdefuss.

sohn *s = new sohn();
vater *v = dynamic_cast< Vater * > (s); // ein legaler upcast
if (v->add(2) != s->add(2))
  cout << "ungleich"; // Diese Zeile sollte eigentlich nie erreicht werden, oder?
else
  cout << "gleich";

Obwohl ich technisch gesehen, dieselbe Methode am gleichen Objekt aufrufe, verhält sie sich dennoch unterschiedlich. Warum? Weil einmal add von Vater und einmal von Sohn aufgerufen wird!
Meistens sind das Programmierfehler, die nur äußerst schwer zu finden sind...

2.) Java ist da glücklicherweise strikter. Grund dafür ist der strenge Polymorphismus, den Java forciert. Ein Objekt vom Typ einer Subklasse kann immer wie ein Objekt vom Typ der Elternklasse gesehen werden (upcast). Das gilt in Java auch für Klassenmethoden.
Warum die Regel so streng gehandhabt wird liegt sozusagen im Design von Java. Gefährliche Konstrukte sollen von Haus aus vermieden werden. Von diesem Standpunkt her ist es unsinnig, einen anderen Rückgabewert als in der Elternklasse zu erlauben, auch WENN es sich nur um eine statische Methode handelt. Es besteht ja Verwechslungsgefahr mit der Methode der Elternklasse.

3.) Die Methode add halte ich deshalb für eine Fehlkonstruktion. Wenn ich eine Methode überschreibe, so soll sie sich ja gleich verhalten, wie jene der Elternklasse (nur angepasst auf die neue Klasse). Das tut sie aber in deinem konkreten Beispiel überhaupt nicht. In Vater erzeugt add ein Objekt vom Typ Vater usw. In Sohn tut sie etwas ganz anderes. Sie erzeugt keinen Vater sondern einen Sohn.
Daher würde ich hier nicht überschreiben, sondern in jeder Klasse eigene Methoden machen. z.B. addVater in Vater und addSohn in Sohn.
IMHO sieht man damit auch auf den ersten Blick, was die Methode tut.

11.07.2005, 18:02 Uhr - Editiert von DeaconFrost, alte Version: hier
Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
......
Re(3): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 14:04:42
Deiner Wortwahl "delegieren", entnehme ich, dass du mit dem Stichwort interface noch nicht vertraut bist? (Verzeih, wenn ich falsch liege!)

Ein Interface ist wie eine abstrakte Basisklasse in C++. Methoden werden dort nur deklariert, aber nicht implementiert. Das sieht ungefähr so aus:

interface MeineSchnittstelle (extends ElternInterface) {
  void Methode1(void);
  ...
}

(public) class MeineKlasse implements MeineSchnittstelle(,WeitereSchnittstellen,...) {
  ...
  void Methode1(void) {
    ...
  }
  ...
}

Die Dinge in Klammern sind optional.

Natürlich kannst du deine Klassen auch public belassen. Vorsicht ist aber trotzdem angebracht. Denn sind deine Klassen public, so dürfen sie natürlich auch von ausserhalb des Pakets abgeleitet werden. Willst du dann deine Klassenstruktur innerhalb des Pakets einmal umstellen, bist du an die Schnittstellen deiner öffentlichen Klassen gebunden. Die kannst du dann nicht mehr ändern. Mit Interfaces musst du nur diese einhalten.
Wegen der Möglichkeit der Ableitung sind dann auch deine protected Felder & Methoden Teil deiner Schnittstelle, die du dann nachträglich nicht mehr ändern kannst. Auch das ersparst du dir mit Schnittstellen.

Factories werden in Java häufiger verwendet als in C++, weil es ja die Möglichkeit gibt auf Schnittstellen einzuschränken. Da macht es mehr Sinn, dass ich eine Factory baue, die mir entsprechdende Objekte erzeugt, denn nur dann brauchen mich die Interna der Klasse nicht zu interessieren (wenn ich Objekte mit new erzeuge muss ich ja zumindest den Klassennamen kennen).

Was ich noch nicht verstanden habe ist, warum du mehr als eine Factory brauchst?

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.......
Re(4): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 14:23:44
Delegate, Interfaces,...

Hmm... Ich meinte das Design-Pattern "delegate" - wo natürlich Interfaces zum Einsatz kommen...

Den Interface-Ansatz unter Java finde ich derzeit sowieso irgendwo zwischen broken und crude... Denn einerseits definiere ich via Interface ja nur, was die das Interface implementierenden Klassen anbieten müssen - andererseits brauche ich zu jedem Interface [fast zwingend] eine Referenzimplementierung - eben weil mir Macros, ... fehlen und man bei n das Interface implementierenden Klassen net n-mal teilweise denselben Code schreiben will/soll.

IMHO sind Interfaces nix anderes als der "letzte Ausweg", wenn man mit Brachialgewalt auf die Vielfachvererbung von mehreren Objekten verzichten will... Sie sind ein Umgehungsweg, der funktioniert - nur IMHO zu einem hohen Preis. [Wie gesagt, alles Java-Anfängergedanken].


(wenn ich Objekte mit new erzeuge muss ich ja zumindest den Klassennamen kennen).

Naja, im Anderen fall muß ich den Namen der Factory plus den Namen der aufrufenden Methode kennen ;-)... Also den Vorteil seh' ich nicht.
Ich verstehe aber, daß einem nichts anderes übrig bleibt als viele Factories zu bauen... warum viele ?


Also ich dachte mir das so:
Ein package "person" - mit Klassen "Person", "Personal", "PersonFactory".
Person und Personal implementiert alle Konstructoren als protected. Nur PersonFactory nutzt sie - und die add()-Methoden wandern von Person und Personal zur Factory - als "addPerson" bzw. "addPersonal".
Nun gibt's bei mir eine andere Klassen-"Gschicht" mit "Job".
Also ein Package "job" mit den Klassen "Job", "AußendienstJob", "InnendienstJob", "ManagerJob", ... - und... *tusch* eine JobFactory. Dort wäre ja wieder alles analog zum Personen-Package zu lösen.

Es scheint für mich also derzeit zu sein, als würden alle Klassen eines Themenbereichs nach einem Package zu rufen... Und es scheint außerdem, daß jedes Package nach zumindest einer Factory ruft ;-)

EDIT: Danke auf jeden Fall für deine Unterstützung - lehrreich für mich.
zu meinem Wissensstand: Rd. 2000 Seiten an Java-Doku bin ich durch. Ich komm' klar mit Interfaces, Klassen, Applets (naja, JApplet ist mir unklar - ich dachte, in Browsern klappt swing net), Swing, Netzwerkprogrammierung, JDBC wird nächstes Thema... RMI wollt' ich mir ansehen, versteh' aber inzwischen den Sinn nicht mehr... Insbesondere erkenn' ich keinerlei Vorteil gegenüber Corba... Außer, daß man andere Sprachen aussperrt ;-)
Kurzum: Ich profitier IMHO von mehr als 20 erlernten Sprachen (mit Dialekten weit mehr)... Also ich fange net ganz bei Null an.

12.07.2005, 14:28 Uhr - Editiert von gepeinigter_aon_neukunde, alte Version: hier
Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
........
Re(5): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 14:49:51
"andererseits brauche ich zu jedem Interface [fast zwingend] eine Referenzimplementierung - eben weil mir Macros, ... fehlen und man bei n das Interface implementierenden Klassen net n-mal teilweise denselben Code schreiben will/soll."

Ich denke, genau da liegt das Problem. Ein Vorteil von Objektorientierung soll ja sein, dass man Code eben nicht mehrfach schreiben muss. Daher sind ja Makros auch so eine Sache.
Aber meine Idee dazu wäre, dass du gemeinsame Tätigkeiten in Methoden auslagerst.
Wohin hängt jetzt vom konkreten Beispiel ab. Möglich wäre:

*) in private Methoden der Factory (Tätigkeiten innerhalb der Factory nur 1-mal implementieren)
*) in eine gemeinsame Basisklasse der erzeugten Objekte (Tätigkeiten die allen Subklassen gemein sind)
*) in eine Hilfsklasse innerhalb des Pakets

Vielfachvererbung bietet zwar mehr Freiheiten, aber der Preis ist auch hoch. Unsicherheiten bei casts, Komplexität, usw. Also alles immer ein zweischneidiges Schwert. In den meisten C++-Anwendungen die ich kenne, wurde Mehrfachvererbung aber ohnehin immer nur für Interfaces benutzt (COM-Objekte).

"Naja, im Anderen fall muß ich den Namen der Factory plus den Namen der aufrufenden Methode kennen ;-)... Also den Vorteil seh' ich nicht."

Schon klar ;-) Der Vorteil ist ja nicht bei der Tipparbeit. Die wird ja sogar mehr :-) Der Vorteil ist, dass ich die Implementierung beliebig austauschen kann OHNE den benutzenden Code (den ich vielleicht gar nicht habe, weil extern, etc) auch nur anfassen zu müssen.
Daher ist die Implementierung gegen Interfaces auch so beliebt. Das komplette Collection-Framework in Java ist ein gutes Beispiel für diese strikte Trennung. Die Benutzung erfolgt über Interfaces (Set, Map, List usw.), die jeweils geeignetste Implementierung kann dann frei gewählt und auch später verändert werden (HashSet, TreeSet, usw.). Oder ich kann eine eigene Implementierung machen und bleibe trotzdem zu fremdem benutzenden Code kompatibel. usw.

Das ruft tatsächlich nach mehreren Packages inkl. Factories. Allerdings spricht auch nichts dagegen, gemeinsame Funktionalitäten in Basisklassen, usw. auszulagern (siehe oben).
Ich denke, da gibt es sicher einen Weg. In jedem Fall ist deine Lösung nur dann optimal, wenn ein Codesegment NICHT (Copy & Paste) nicht mehrfach vorkommt.

Wenn du das im Vergleich zu C++ mühsam findest, kann ich das gut verstehen. Allerdings bin ich überzeugt, dass dein Design dann wesentlich erweiterbarer und flexibler wird, als ein entsprechender Wurf in C++.
Warum? Weil Java einen (leider ;-)) oft zu (besseren) Designentscheidungen zwingt...

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.........
Re(6): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 15:16:43
Implementierung austauschen...
Aber genau das könnte ich ja bequemer via Vielfachvererbung.
Anstatt eines Interfaces hätte ich eine Abstrakte Basisklasse (das ist ja wirklich ähnlich) - nur wäre ich eben nicht zu abstrakten Basisklassen gezwungen - sondern könnte stattdessen eine konkrete Klasse mit referenzimplementierung bauen.

Genauso wie ich via Interfaces verschiedene Implementationsvarianten definieren kann und die passende wählen kann, könnte ich das ja via Kindobjekte...

Die Verfügbarkeit des Codes und so macht da keinen Unterschied...

Gemeinsame Basisklassen... wären dann total fein, wenn es vielfachvererbung gäbe ;-).
Aber so wird's ja strange... zB (kann da aber Falsch liegen): Applet.
Ein Applet muß kind von Applet sein - also darf es direkt nur noch Sachen verwenden, die via Interface implementierbar sind. Noch kenn ich keine andere so harte Vorgabe - ich vermute aber stark, daß es da Probleme geben kann - oder alles über Umweg-Delegationen gelöst werden muß, was wieder net nach einfachem Code aussieht...

Ich nehm' aus unserem Dialog mal mit, daß man i.d.R. viele packages in der App hat, dort seine logische Trennung macht und tendenziell je mindestens eine Factory implementiert...

Echt, wenn Java net auf vielen Plattformen (ab Handy) laufen würde bzw. net auch Graphik in der Sprache hätte.... Es wäre mir nicht eine einzige Überlegung wert ;-)



Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
..........
Re(7): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 15:46:50
Ich gebe dir Recht. Dafür gibt's die Mehrfachvererbung in C++ auch. Nur bringt Mehrfachvererbung auch viele Designprobleme und Komplexität mit sich (gleiche Felder- & Methodennamen, unterschiedliche Bedeutungen; Mehrfacheinerbung gemeinsamer Toplevelklassen, etc). Zudem gäbe es in Java ja immer eine Mehrfacheinerbung von Object. All das wollte man für Java vermeiden und auch die strenge Trennung von Schnittstelle und Implementierung hat ihre Vorteile.

Beispielsweise Sicherheit. Gerade Applets, die ja im Browser ausgeführt werden, sollen auf dem Zielrechner keinen Unsinn anstellen können. Diese strenge Reglementierung hilft dabei. Ein Applet darf sich eben nur wie ein Applet verhalten (mit zusätzlichen Möglichkeiten), aber nicht anders.

"Ich nehm' aus unserem Dialog mal mit, daß man i.d.R. viele packages in der App hat, dort seine logische Trennung macht und tendenziell je mindestens eine Factory implementiert..."

Bis auf die Factory geb ich dir Recht. Eine Factory pro Package ist nicht zwingend. Es gibt viele packages, die ganz ohne Factory auskommen. Nur in deinem Beispiel scheint es notwendig zu sein. Du willst ja Duplikate vermeiden, daher ist die Erzeugung eines Objektes komplex und eine Factory notwendig.

Wenn dir C++ mehr liegt, dann will ich dir auch gar nicht dagegen reden. Ich kann auch deinen Frust verstehen! Aber Java hat genauso wie C++ auch eine "innere Schönheit". Ich denke, du hast schon gemerkt, dass Java eben nicht nur ein plattformunabhängiges C++ ist, sondern eine komplett andere Sprache mit teilweise komplett konträren Konzepten. Das ist natürlich sehr gewöhnungsbedürftig, aber ich kann dir aus eigener Erfahrung nur sagen: Beschäftige dich intensiver damit, dann wirst du auch viel Schönes entdecken...

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
...........
Re(8): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 16:19:09
Trotz allem finde ich das gerade bei Applet's unschön - abgesehen davon, daß sie de facto eh' tot sind ;-).

Ich meinte das Problem nicht aus Security-Sicht (darum kümmert sich ja [hoffentlich] der Security-Manager der Ziel-VM), sondern aus Instanz-Sicht:

So ziemlich jedes Trum kannst du ja scheinbar entweder direkt instanzieren, davon ableiten oder als Interface implementieren. Soweit sogut.

Applet kannst aber AFAIK net als Interface implementieren, sondern du muß direkt ein Kindobjekt schaffen. Du kannst also nicht sagen
public Class xyz extends JFRAME implements Applet
Das ist solange wurscht, solange Applet das einzige Trum ist, das so rennt.

Angenommen, es gäbe eine zweite Klasse, die sagt "wer mich verwendet, muß ein Kind von mir sein - nix Interface"... dann wird's stressig ;-) - und zwar unnötig stressig.

Will sagen, für den DAU sieht es unschön aus, einerseits zu sagen "Vielfachvererbung brauch ma net - haben eh' Interfaces"... und gleichzeitig zu sagen "Was willst ? Ein Interface für XYZ - das geht nicht" ;-).

Ich habe keine Ahnung, ob Applet das einzige Teil ist, das sich so verhält (in Wirklichkeit hätt ich anfangs thread auch dort vermutet und war dann aber über das Interface runnable erstaunt) - ich finde es aber so oder so eine unelegante Umgehung...

Denn Applikationen, die wahlweise als Applet oder als "normale" App laufen sollen, müssen dann schon umständlich konstruiert werden (zumindest hab' ich sie dann umständlich gebaut, keine Ahnung, ob das einfach ginge ;-) )

EDIT:
Und wie gesagt - evtl. sind alles nur die Anfängerhürden...
Die ich persönlich bei Java aber als weit höher halte als kommuniziert... Und der Fallen-Ideenreichtum der Sprachdesigner gehört ja schon besungen ;-).

Egal ob synchronized-Streß, yield()-Aufruf-Notwendigkeiten, ... Inzwischen keimt bei mir der Verdacht auf, daß portables Schreiben unter C/C++ mit autoconf/libtool weit schneller und einfacher geht als in J ;-)

12.07.2005, 16:22 Uhr - Editiert von gepeinigter_aon_neukunde, alte Version: hier
Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.............
Re(10): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 17:34:34
Ging mir ja net um Java-Beschimpfung... Naja, eigentlich schon auch um Frustabladen ;-)

Das thread-modell halt ich hingegen für eine Riesen-Lüge... Genauso wie den Pointer-Verzicht.

Möglicherweise blick' ich noch zu eingeschränkt/vorbelastet auf die Themen, aber meine Hinweise waren:

Aus dem Javabuch:
"Dieses Beispiel wurde auf Linux-2.4 entwickelt, wo es in der VM keine preemptiven Threads gibt - daher ist ein dauernder Aufruf von yield() notwendig, damit der andere überhaupt drankommt"...
Sorry, aber das ist krank. Denn das bedeutet, daß ich portablen Code nur schreiben kann, indem ich dauernd manuell die Kontrolle an andere threads übergebe - nur dann brauch ich keine mehr...

Von der Idee her ist es ja super, wenn man eine portable Sprache schafft, die sogar die Typen portabel hat (anders als in C, wo ja zB int verschiedenste Wertebereiche annehmen kann) - nur ist die Literatur voll von "Unter Win95 klappte x.y.z nicht, da ist stattdessen a.b.c zu nehmen", "Unter Linux a.b.c wird die Thread-Priority nicht ausgewertet, unter a.b.d braucht man yield()", ...

Kurzum:
Es scheint so, als bin ihc in ähnlichen Problemen wie bei der HTML-Webseitenerstellung: Ich brauche [zumindest alle verbreiteten] Plattformen zur Verfügung, um zu testen. Gerade bei massiv parallelen Anwendungen mit extremer Userlast wird es vermutlich tausende Situationen geben, die kaum auszutesten sind - und man wird mit unterschiedlichsten nicht nachstellbaren Problemen konfrontiert sein [alles nur meine Gedanken dazu -- muß net so sein].

Pointer-Verzicht:
Sorry, entweder ich bin zu dämlich, oder in Wirklichkeit wurden Pointer in Referenzen umbenannt, die Arithmetik entfernt und voila waren die viel besseren Referenzen da.

Typsicherheit:
Sorry, aber Array-Überlauf, ... Da gibt's genug seeehr gute Bibliotheken dafür, die Dir das abnehmen. Nur via Bibliothek hab ich die Variante, in der Entwicklung alle Checks aufzudrehen und beim Ausliefern zu entfernen - um Früh Fehler zu finden und später performanter zu sein... Es scheint also wieder wie ein Verzicht.

Ich vermute echt, daß Java voll von tollen Ideen steckt, die sich mir natürlich noch nicht erschließen - allerdings die Umsetzung teilweise extrem schlampig ist (siehe obiges mit yield(), wobei das IMHO inzwischen deprecated ist und ich deswegen in einigem Source schon sleep(1) als quasi-Äquivalent gefunden habe [was IMHO auch seeehr zum kranken neigt].

Kann aber durchaus sein, daß ich bisher [fast] nur bescheidene Codebeispiele von bescheidenen Autoren gesehen habe... Nur weil ein paar Bücher schreibt, muß er sich damit ja nicht auskennen ;-)

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
..............
Re(11): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 18:10:37
Frustabladen find ich voll ok. Nur weiter so. ;-)
Außerdem find ich es toll, deine konträre Sichtweise kennenzulernen. z.B. die Lösung mit Thread bzw. Runnable, als notwendiger Kompromiss, deckt ja auch die Schwächen des Konzepts auf. Fand ich gut und hab daraus gelernt.

Threads:
Das Problem ist, dass Java nur garantieren kann, dass es verschiedene Threads gibt. Wann und in welcher Reihenfolge die drankommen liegt an der Implementierung der virtuellen Maschine. Deswegen dürfen Implementierungen sich auch nicht darauf verlassen.
Das unter Linux derartiges notwendig war ist wirklich absolut KRANK. Volle Zustimmung. Ich bin mir aber zu 90% sicher, dass das nicht mehr notwendig ist.
Das Plattformunabhängigkeit aber auch Probleme mit sich bringt ist leider so :-(

Pointer-Verzicht:
Nicht nur. Referenzen sind auch typsicher. Versuche ich einen illegalen cast, gibt's eine ClassCastException. Außerdem sind Referenzen GARANTIERT null oder gültig. Wenn ich mich in C++ darauf verlasse, bin ich verlassen...

Array-Überlauf:
Das ginge in Java gar nicht, weil Arrays dort anders organisiert sind. Arrays sind dort auch Objekte, deren Länge dynamisch (beim Erzeugen) frei gewählt werden kann. Daher kann ich nicht vorher testen und dann die Checks entfernen.

Performanz:
Durch das dynamische Übersetzen zur Laufzeit kommt im Endeffekt auch Maschinencode raus. Also kein Vorteil für C++. Die virtuelle Maschine kann aber die momentane Situation berücksichtigen und dadurch Vorteile herausschlagen (Beispiel habe ich schon genannt).
Das gilt auch für die Checks. Ist garantiert, dass die Länge des Arrays nicht überschritten werden kann, dann erfolgt auch kein Check. Die Sicherheit geht im Zweifel aber vor.
Alles in allem bezweifle ich schwer, dass C++ performantere Applikationen erzeugt als Java. Das war einmal.



Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
...............
Re(12): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 18:47:20
Plattformunabhängigkeit...
Da hat Java am offensichtlichsten Merkmal (dem UI) doch Beispiele gesetzt:
AWT: Kleinster gemeinsamer Nenner...
Swing: Wir versuchen mehr - allerdings viel Code in Java und unportabel.
Denn gerade hier wurde der Ansatz halbherzig verfolgt:
Einerseits manche Sachen umständlich gelöst bzw. bewußter Verzicht (um unabhängig zu sein), andererseits unterschiedliche setLookAndFeel-Möglichkeiten je nach Plattform..
In Swing haben sie es trotzdem recht gut geschafft, brauchbar unabhängige Apps zu bauen... Allerdings zu einem hohen Performance-preis. Denn ich /befürchte/, daß viel von den routinen zum Nachbilden in Java geschrieben ist - und das einfach schlechtestens performt. Rein Subjektiv verhält sich Swing oder gar SWT auf meinem PentiumIV mit 3GHz und 512MB Ram definitiv träger als Delphi3 auf meinem Pentium-133MHz mit 64MB -
Also ich bezweifel, daß die Java-Apps flotter oder nur gleich schnell sind ;-)
C++ profitiert davon, daß es sich für den Compiler-Optimizerlauf /viel/ Zeit nehmen darf... Net umsonst dauert das voll optimierte Compilieren von zB einer aktuellen KDE durchaus mal > 12h.... einem JIT-Compiler gesteht man derart umfangreiche Optimierungen halt naturgemäß kaum zu ;-)

Ad "Ist garantiert"... Das impliziert mindestens einen Check - nämlich im besten Fall nur das Abfragen eines "Ist_garantiert"-Boolean ;-). Das macht per se wenig aus - summiert sich aber...

Array-Überlauf:
Das meinte ich mit Bibliotheken...
Es gibt genug Array-Bibliotheken für C und C++, die genauso wie in Java arbeiten... Ich bilde mir dunkel ein, daß ich beim Qt-Designen darüber stolperte - wo das echt auch so gelöst ist..
Nur wie gesagt - sobald's in einer Bibliothek ist (die's ja genauso für sichere Strings, ...) gibt - gibt's oft einen Schalter "verhindere Checks" bzw. andere Zugriffsvarianten....

Performance abschließend:
Ich vermute, daß mal alle Programmierer (mich eingeschlossen) faule Schweine sind. Dementsprechend überlegt sich keiner, wie O() seiner Funktionen aussieht - und muß nachher tunen... Wenn man postuliert, daß die zur Verfügung gestellten Klassen in Java sauber optimiert sind - was ich tue - so ist es durchaus möglich, daß C++-Programme ungefähr gleich performen wie in Java... eben wenn man annimmt, daß alles vom Programmierer geschriebene gleich schlecht ist.
ABER... Es gibt weitaus mehr vorgefertigtes in C/C++ - was sich auch in den Programmen äußert... Ich schreib seit 10 Jahren kommerziell in C - und lerne noch immer jedes Monat über Bibliotheken, ... dazu. Man sieht's auch am Source.. Er wird immer effizienter, sauberer... und kürzer, weil man mehr und mehr stöpselt ;-). Wenn man annimmt, daß das in Java ähnlich ist... Gewinnt die Sprache mit mehr fertigen Bibliotheken.. Also C ;-)

Illegale Casts... Nun ja, ich mag das Vertraue-dem-Programmierer-Prinzip. Wobei die Cast-Fehler IMHO nur Anfängerfehler sind...
Und Tools wie splint/lclint weit mehr Sicherheit garantieren [zB "illegales" modifizieren referenzierter Werte], als in Java derzeit umgesetzt ist... man muß sie nur verwenden ;-)

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.................
Re(14): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 19:28:48
Naja, gerade die Möglichkeit, versehentliche Modifikationen übergebener Objekte zu verhindern finde ich seeehr toll im splint - rettete mich schon öfter [u.a. auch bei Fehlerhafter Zeigerarithmetik - zugegeben ;-)]

Was mich sonst noch ein bißchen störte ist der Garbage-Collector...
Der Grundgedanke ist zwar fein "Kümmer Dich nicht - mach ma scho'" - nur:
- bin ich zu mißtrauisch.
- hätt ich gerne die Möglichkeit, den gc fix sofort zu starten... Wenn ich es richtig verstanden habe, markiert ein gc() ihn aber nur als runnable... Und natürlich kann ich viel feiner arbeiten, wenn ich zuerst mal viel Speicher für Objekt A brauche, später für Objekt B... Denn dann kann ich bewußt dazwischen disposen.. mit dem gc... nunja...
- Destruktoren werden wertlos.
Ich benutzte die gerne in der Entwicklung um mitzuloggen "X terminierte jetzt"... Das kam dann schön in der Reihenfolge, uU mit Timestamps je nach Bedarf... Kann aber sein, daß man das unter Java gar net so braucht.

Wie auch immer, die Hürden finde ich stärker als unter C/C++ - wie gesagt, uU bin ich schlicht schön langsam zu Alt ;-) - aber riskieren muß' man's mal. Denn schließlich motzt man ja gerne... Aber motzen kann man erst, wenn man was gut kennt *gg*

Auf jeden Fall Danke für deine Tipps.
zZt sehe ich die Chance, daß ich jemals von Java begeistert bin als komplett gering an... Allerdings war ich am Anfang beim Umstieg von Pascal/Delphi auf C auf extrem schockiert über diese grottenschlechte Sprache voller Limitierungen und Unwägbarkeiten - und heut' lieb ich sie heiß ;-)

cu
gepeinigter

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
..................
Re(15): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 19:58:46
Tja. Übergebene Objekte in Java können immer modifiziert werden. Gerade das ist etwas, was mir auch nicht so schmeckt (ein const wäre schön gewesen). Aber naja. Man hat sich wahrscheinlich die Komplexität ersparen wollen und es geht ja auch anders.

In den Garbage Collector kannst du ruhig vertrauen haben.
- Der ist elendslang und -oft getestet worden und daher in jedem Fall besser und zuverlässer, als jeder selbstgeschriebene Code. Ich lernte ihn heiss lieben, als ich mal eine komplexe Datenstruktur in Java und in C++ aufbauen musste (mit Zirkelverweisen, etc).
In C++ musste ich viel Hirnschmalz investieren, wie ich alle Objekte zuverlässig freigebe, ohne wegen dangling pointers zu crashen, usw. In Java Referenz(en) auf null gesetzt... und tschüss.
- Der GC lässt sich nicht beeinflussen und das ist, denke ich, gut so. Das einzige das garantiert ist, dass er bei Bedarf in Aktion tritt.
- Destruktoren gibt's in Java gar nicht, weil obsolet. Die finalize()-Methode ist auch kein Ersatz dafür, denn sie wird möglicherweise NIE aufgerufen. Um andere Ressourcen als Speicher freizugeben, muss man entsprechende close()-Methoden implementieren und testen.

Zu alt kann man doch nie sein ;-) Ich kann nachvollziehen, dass du dir schwer tust. Ich denke aber, du wirst auch Java heiss lieben lernen, weil es ist eine tolle Sache. Und motzen ist ja absolut in Ordnung. So lernen du und ich etwas ;-)

Cu
Deacon

P.S.: Alles Liebe und Viel Glück bei deinen weiteren Java-Erfahrungen!

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
...................
Re(16): Scheinbar sieht die Lösung echt so aus...
13.07.2005, 11:02:34
Ich seh' beim gc (Angenommen, ich vertrau im Mal) folgendes Problem:

Sagen wir
eine Objektgruppe A mit 1.5 GB
eine Objektgruppe B mit 1.5 GB

Steps:
[1] Benutze Gruppe A
[2] Beende Gruppe A und mach kurz was anderes
[3] Benutze Gruppe B
Und das ganze auf einer 32Bit-Architektur, wo ein Prozeß (die JavaVM) max. 2GB Ram bekommen darf ;-)

Überall, wo du selbst den Speicher freigibst, ist das kein Problem...
Unter Java muß ich sowas erst mal konstruieren, wittere aber Gefahr...
Wenn [2] so kurz rennt, daß der gc noch nicht dran war - dann ist [1] noch allokiert und es fetzt ihn vermutlich wegen OutOfMemory... Ich vermute mal, daß sowas auch nicht catchbar(sagt man so?) ist... Zumindest habe ich noch nie in Source gesehen "try { machwas() } catch (OutOfMemoryException ome) { }" - vermutlich, weil du in dem catch() eh nix machen kannst (zumindest net den gc erzwingen ;-) ). Oder ist Java so clever, bei jedem OOM-Verdacht den gc anzuwerfen ? Oder ist das so akademisch, daß das eh nicht passiert ?

Freund von mir arbeitet in einem Projekt, wo sie gerade mit dem 2GB-Limit Streß haben... Drum dachte ich, daß ein Verzicht auf gc-Kontrolle schlimm sein kann...

Anyway, ich probier's weiter. Echt danke für's Müll-abladen-dürfen und deine Erläuterungen... Hat mir sehr gefallen und mir sehr geholfen... Sowohl das Frust abladen - was man ja immer braucht - als auch beim Erläutern von Konzepten.... 1000 Dank und *noch ein Bier spendier*

gepeinigter.




Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
....................
Re(17): Scheinbar sieht die Lösung echt so aus...
13.07.2005, 11:36:40
Ich kann dich beruhigen. Es besteht in diesem Fall keine Gefahr. Wenn die virtuelle Maschine einmal nicht genug Speicher zum Allokieren ihrer Objekte hat, wird zwingend der GC angeworfen. Erst wenn der es nach allen Versuchen auch nicht schafft genug Speicher zu allokieren wird ein OutOfMemoryError geworfen.

Errors sind im Übrigen Ausnahmen, die üblicherweise nicht abgefangen werden, weil es sich um besonders schwere Fehler handelt (Fehler in der virtuellen Maschine selbst, usw.), deren Behebung meist ohnehin nicht möglich ist.
Errors sind von der Klasse Error abgeleitet und die wiederum von Throwable. Exception ist ebenfalls von Throwable abgeleitet. Exceptions sind also sozusagen "Brüder" von Errors.
Exceptions MÜSSEN im übrigen abgefangen werden. Ausnahme sind die RuntimeExceptions (RuntimeException ist eine Subklasse von Exception), weil die eigentlich ständig auftreten können.

Mir fällt noch was ein: Java unterstützt auch das bilden von großen Caches. Fürs Caching ist es ja oft nicht zwingend, dass die Daten im Speicher bleiben. Sie können ja bei Bedarf wieder nachgeladen werden. Für diesen Zweck gibt es sog. Weak- und Soft-References. Die derart referenzierten Objekte gibt der GC frei, wenn ihm keine andere Wahl bleibt.
Vor dem Zugriff muss man dann einfach eine "echte" Referenz beantragt werden, die man dann entweder bekommt (weil das Objekt noch im Speicher ist) oder nicht (weil der Speicherplatz benötigt wurde). Diese Referenz ist dann sicher (so wie üblich) und wird nachher einfach wieder freigegeben.
Dadurch kann der GC flexibler arbeiten und man kann trotzdem riesige Datenmengen im Speicher cachen.
Vielleicht hilft das deinem Freund?

Ich hab auch sehr von dieser Diskussion profitiert. Freu mich immer schon auf deine nächsten Posts...

LG,

Deacon



Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.....................
Re(18): Scheinbar sieht die Lösung echt so aus...
13.07.2005, 12:00:20
Error/Exceptions sind mir in Java schon klar... und die Catch-or-Throw-Regel gilt ja in jeder Sprache mit Exceptions - wenn schon nicht explizit, dann implizit ;-).

RuntimeExceptions... Da hab' ich mit meinem Java-entwickelnden Freund des öfteren eine religiöse Debatte (er setzt immer auf die falsche Religion ;-) ).

Division durch 0:
Sein Statement: Programmierfehler. Darf es nicht geben - denn vor jeder Division hätte man zu checken.
Mein Statement: Entweder die JavaVM braucht unendlich lange für's ExceptionHandling oder er schreibt schlechten Code... Denn man /darf/ net vor jeder Division checken, ob der Divisor 0 werden kann - kostet sinnlos Zeit. Zumindest in Assembler ist ein "einfach mal Dividieren und notfalls Exception abfangen" ohne Zeitverlust möglich - während ein Divisorcheck doch einige Statements kostet. Wenn die Division eh nur selten passiert, ist's wurscht... Wenn das aber in einer inneren Loop passiert... wird's teuer...

Er läßt sich aber nicht überzeugen... Wie sieht's aus in Java ? Ist dort das Exception-Handling derart teuer, daß man möglichst drauf verzichtet ? Dann sollte man tendenziell Exceptions catchen statt throwen (natürlich nur in den Fällen, wo es vom Design her wurscht ist, wie mans löst)... Oder hat er nur die falsche Religion ?

Weak- und Soft-References
Seeehr guter Tipp - das kann man sicher sehr oft brauchen... das paßt perfekt in einige meiner getter-Methoden. Bisher dachte ich, ich füll einfach meine VM oder laß alles in der DB oder mach eine final-Konstante, wieviel Objecte ich Cache (zB 100 Personen, ..)
Alles an sich unbrauchbar - oder zumindest net optimal. Da klingt dein Lösungsansatz seeehr perfekt... Cache solange wie geht (also vermutlich je nach Wunsch Benutzer) und kümmer dich selbst... Kann man das parametrisieren ? Sinngemäß: Laß immer zumindest Platz für 10*sizeof(Person), ... damit der Benutzer wenn er navigiert auf jeden Fall noch Platz hat für neue Anzeigen ? Weak/Soft-Referenzen sind das eigentlich Synonyme ? Oder verschiedene Sachen ? Sind das die Begriffe, nach denen ich in der API-Beschreibung von Java Suchen soll ? Gibt's einen empfehlenswerten Link zu dem Thema ?

Thx für den Tipp
gepeinigter

EDIT:
Je nach Wunsch Benutzer - damit meine ich seine Storage-Parameter beim Aufruf der VM... Wie klappt das eigentlich bei Applets ? Wo definiert man da, wieviel Stack/Heap/... die VM bekommen soll ? Hätte so eine Einstellung in Browsern noch nie bemerkt... Oder ist das eine fixe Konstante ?

EDIT²:
Hab's gefunden: http://java.sun.com/developer/technicalArticles/ALT/RefObj/
Thx..

13.07.2005, 12:30 Uhr - Editiert von gepeinigter_aon_neukunde, alte Version: hier
Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
......................
Re(19): Scheinbar sieht die Lösung echt so aus...
13.07.2005, 12:42:02
Umso besser, wenn du schon Bescheid weisst! Ich versuche nur gründlich zu sein, damit Du nicht nur die halbe Wahrheit hörst...

Wie teuer Exception Handling ist, kann ich dir nicht sagen. Das hängt aber auch (wie alle Performance-Überlegungen) von zu vielen Faktoren ab: Plattform, Implementierung der VM, Fähigkeit des Compilers, der JIT, usw.
Ich denke, das ist aber in jedem Fall hochoptimiert, da schon seit Urzeiten in der Sprache inkludiert.
Exception Handling ist eine wichtige Komponente für modernes Design. Es ist in den meisten Fällen besser als "komische" Rückgabewerte oder dergleichen, weil der Aufrufer einer Methode auf Fehlerfälle derselben besser reagieren kann bzw. diese auch noch oben durchgereicht werden können (zentrale Behandlung von Ausnahmen).
Exception Handling ist aber nicht angebracht, wenn den Aufrufer die Fehlerfälle ohnehin nicht interessieren (close ist schiefgegangen. so what?) oder er nichts dagegen unternehmen kann (internal error? na toll!).
In jedem Fall ist es wichtig Exceptions gut zu dokumentieren. Insbesondere RuntimeExceptions, die bewusst ausgelöst werden (z.B.: Diese Methode wirft eine NullPointerException, wenn du eine null-Referenz übergibst).
Performance-Überlegungen sollten nur eine sehr untergeordnete Rolle spielen. Nur insofern, als man sich schon überlegen sollte, ob man eine Exception jetzt wirklich braucht oder nicht. Weder übertriebener Einsatz (auch für fast alle Normalfälle schon Exceptions) noch zu sparsamer Umgang (Das tritt eh nie auf) sind anzuraten.
Ach ja: Für private bzw. protected Methoden verwendet man meist assert zur Einhaltung von pre- bzw. postconditions. Wenn diese falsch angesteuert werden, sind das ja eher Programmierfehler (sind ja "meine eigenen" Methoden).
Für public Methoden wird mit if-Statements abgefragt und ggfs. eine Exception geworfen. Hier gilt das Prinzip der Vorsicht. Man bietet ja eine Schnittstelle nach aussen an.

Im Fall deines Freundes würde ich aber Exceptions in jedem Fall vorziehen. Warum? Egal, ob er jetzt vorher prüft oder nachher die Exception fängt, in jedem Fall muss der Ausnahmefall irgendwie behandelt werden, wenn er eintritt. Die Codeersparnis in diesem Fall ist also gleich Null.
Außerdem ist die interne Prüfung der VM auf eine Division durch Null ganz sicher nicht langsamer (weil schon fest verdrahtet in der VM), als eine manuelle Prüfung mittels Java-Code. Wenn die Instruktionen selten ausgeführt werden sogar sicher langsamer, weil dann wird interpretiert (wegen einem Durchlauf springt der JIT erst gar nicht an). Also kann man hier nur schlechter liegen.

Die Klasse SoftReference ist, glaube ich, was du suchst. Es gibt auch noch die Klasse WeakReference. Wirf einfach mal selbst einen Blick in die API-Beschreibung (siehe http://java.sun.com/reference/api/index.html ).
Um entsprechend zu parametrisieren genügt es ja die entsprechenden Anzahl von Objekten auch mittels harter Referenzen zu referenzieren (geht, glaub ich, mittels Zuweisung). Die dürfen ja dann nicht mehr freigegeben werden. Damit kannst du genau steuern, wieviele und welche Objekte in jedem Fall im Speicher bleiben (auch "hart" referenziert) und welche bei Bedarf freigegeben werden können (nur weiche Referenz).
Wenn du also 100.000 Objekte nur weich referenzierst und zusätzlich 10 davon auch mit harten Referenzen referenziert, hast du genau das was du willst. Die 10 bleiben dann immer im Speicher. Die kannst du dann bei Bedarf ersetzen (durch eine Zuweisung zu einem anderen/neuen Objekt) und hast so immer den erforderlichen Speicherplatz.

Soweit ich weiss gibt's entsprechende Tags. Da bin ich mir aber extrem unsicher. Vielleicht steht auch was in der API bei der Klasse Applet?

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.......................
Re(20): Scheinbar sieht die Lösung echt so aus...
13.07.2005, 13:12:02
(close ist schiefgegangen. so what?)

Hehe, Beliebter Programmierfehler von C-Leutchen, gerade von close() den returncode net auszuwerten...
Denn definitiv macht das Sinn - aus der Manpage

       Not checking the return value of close  is  a  common  but
       nevertheless  serious programming error.  It is quite pos-
       sible that errors on a  previous  write(2)  operation  are
       first  reported  at  the  final  close.   Not checking the
       return value when closing the file may lead to silent loss
       of  data.   This  can  especially be observed with NFS and
       disk quotas.


Beim Applet muß ich noch nachstöbern - trifft mich aber derzeit net so...
Applet wäre für eine geplante App von mir (Umstellung von PHP auf "bequemeres" UI) total nett - allerdings bin ich mir nicht mehr sicher, ob das klappt...
Denn das Applet darf ja defaultmäßig (alles andere wäre bei meinen Kunden utopisch ;-) ) nur mit dem Server kommunizieren, von dem es geladen wurde... Das scheint aber bei Firewall-Umgebungen, die den Zugriff nur via Squid oder anderen Proxies erlauben kaum möglich (und so ist es ja in den meisten Firmen). Das wiederum bedeutet, man muß wohl HTTP-Connections vom Applet via Proxy aufbauen (was vermutlich einem Applet net erlaubt ist)... Schade.

Möchte da noch mit WebStart forschen... Ob das DAU-sicher zum Anwenden ist... Darf man eigentlich eine Sun-VM (also das Installationsbinary) mit ausliefern oder darf man nur einen Link zur Sun anbieten ? Ich vermute letzteres - sonst hätte Debian net diese besch*ene Installationsverweigerung von Java (bzw. eben keine Pakete dafür)...

Letzte Frage:
Muß ich beinhart für jeden Browser getrennt eine VM installieren ?
zB Konqueror meldet eine andere VM als wenn ich java -version eingeb...

Auf jeden Fall viel Glück bei deiner Zertifizierung - das Zeug zum Tutor dürftest ja haben ;-)

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
........................
Re(21): Scheinbar sieht die Lösung echt so aus...
13.07.2005, 13:37:55
Programmierfehler:
Danke für den Hinweis. Wusste ich gar nicht.
Ich fürchte, aber da hab ich mich missverständlich ausgedrückt. Ich meinte, dass es bei close keinen Sinn macht eine Exception zu werfen. Da bleibt ja immer noch die Frage, wie ich eine solche behandeln soll? Die Datei ist verhunzt, nochmal schreiben würde wahrscheinlich das gleiche Ergebnis bringen, usw. Ich kann höchstens dem Nutzer eine Meldung auf den Schirm knallen "...konnte nicht geschrieben werden." Und DAFÜR reicht der Rückgabewert vollkommen aus. Diesen Fehlerfall mit Exceptions zu behandeln ist sinnlos, weil der Aufrufer keine Chance hat den Fehler selbst zu beseitigen.
Auch die Rückgabewerte nicht auszuwerten ist leider oft Praxis, aber verständlich, weil gerade in C (C++ ist da schon besser) ständig irgendwo ein Fehlerwert zurückgegeben werden kann und viele schon zu faul sind für die vielen if-Kaskaden ;-)

Mit Applets hab ich mich leider nur sehr oberflächlich beschäftigt. Mit WebStart leider noch gar nicht. Da kann ich dir also leider keine Tipps geben.

Das JRE ist frei und kann daher ohne Probleme mit jeder Software mitgeliefert werden, nur darf man dafür keine irgendwie geartete Gegenleistung verlangen (für die Software natürlich schon! aber nicht für die Runtime selbst).
Das das JRE bei Debian nicht dabei ist, muss wohl an der Distri selbst liegen. Bei Suse bspw. ist es bereits inkludiert (da ist sogar das SDK dabei).

Browser verwenden ein eigenes Plugin. Das hat Sicherheitsgründe, weil die "normale" VM würde ja alle Zugriffe gestatten. Das Plugin kann aber je nach Konstruktion die "normale" VM, bereichert mit einem entsprechenden SecurityManager, benutzen.

Vielen Dank für das Kompliment. Macht mich ganz schön stolz :-)
Aber die erste Zertifizierung (Certified Programmer) wird wohl erst im Dezember diesen Jahres nach intensivem Studium möglich sein. Wie du schon sagtest, Java ist ganz schön komplex...

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
............
Re(9): Scheinbar sieht die Lösung echt so aus...
12.07.2005, 17:00:40
I see your point. Ist sicher auch in machen Fällen ein Nachteil. Trotzdem: Der Ansatz ist halt ein anderer. Eine Ableitung bedeutet ja immer: verhält sich wie ein. In machen Fällen wär's sicher praktisch (und auch kein Problem), wenn ich mich gleichzeitig wie A und B verhalte(n muss). Problematisch wird's nur, wenn A und B teilweise konträres Verhalten voraussetzen. Diese Probleme wollte man in Java eben von vornherein ausschliessen.

Zum Glück gibt's aber noch die Aggregation: Ich muss ja nicht unbedingt erben, um Funktionalitäten anderer Klassen nutzen. Ich kann ja auch einfach Objekte dieser Klassen inkludieren und dann deren Methoden aufrufen.

Ausserdem: Ich kann mir nicht vorstellen, das die Java-Bibliothek verlangt, dass ich Funktionalitäten von 2 Klassen gleichzeitig einerben muss. Das kann ich mir nur selbst einfallen lassen und dann gibt's sicher auch eine andere Lösung ohne Stress ;-)

Zum Edit:
Ist wohl nur eine Frage der Sichtweise. Ich find synchronized z.B. eine wunderschöne Sache, weil das Thema Synchronisation gleich in der Sprache inkludiert ist. In C++ kann ich sowas ja nur über selbstgebaute Konstrukte lösen.

Und der Fallenreichtum von C++?
Memory-leaks und dangling pointers.
Nicht-virtuelle Destruktoren sind absolut sinnlos, in C++ aber möglich.
Probleme mit (impliziten) Casts.
Überläufe von Arrays.
Fall-Through bei switch-case.
Zuweisungen in if-Anweisungen, die eigentlich Vergleiche sein sollten.
Nicht-boolsche Ausdrücke in if/for/while/do-while sind erlaubt, aber eine furchtbare Falle.
Makros, die nur 1 Zeile lang sind können 1000 Zeilen Code hundertfach in den Code einschleusen und sind nicht typsicher.
Überladene Operatoren schaffen Verwirrung.
Und erklär einem Anfänger mal die diversen Konstrukte der STL...

Du siehst. Wenn ich Schwierigkeiten finden will, geht das auch in C++ ;-)

EDIT:
Ach ja, nochwas. Ich glaube, dein größtes Problem ist nicht Java, sondern deine C++-Kenntnisse. ;-)
Ich kenn zumindest keinen Anfänger, der sofort fragt: "Und? Wie mach ich Mehrfachvererbung?"
Ich denke, das ist wie beim Englisch lernen. Wenn du in Deutsch denkst und das dann Wort für Wort in Englisch übersetzt holpert's gewaltig. Sobald du aber in Englisch zu denken beginnst, konstruierst du die Sätze schon von Grund auf ganz anders.
Genauso ist es hier. Wenn du mit C++-Design-Patterns im Kopf eine Implementierung in Java versuchst, schreit ständig der Compiler und du denkst: "Ist ja schlechter als in C++. Da wär's gegangen!" ;-)
Vielleicht solltest du dir mal guten Java-Code anschauen und studieren? Auf der Sun-Homepage (java.sun.com) gibt's sicher entsprechendes in den Tutorials...

12.07.2005, 17:26 Uhr - Editiert von DeaconFrost, alte Version: hier
Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
...
Re(3): Java-Dau-Anfängerproblem...
12.07.2005, 12:09:04
Zu 3.) Meiner Meinung nach ist da kein Unterschied zu C++. Dort gibt's auch eine add-Methode für JEDE Klasse, also auch Trillionen verschiedene. Nur heissen sie alle gleich, es gibt den genannten Pferdefuss UND es besteht Verwechslungsgefahr (nebenbei finde ich es unübersichtlicher). An der Funktionalität ändert sich also nichts...

Zu private: Private Methoden sind in Kindklassen auch nicht sichtbar. Das heisst, es ist auch in Java möglich, dass eine private Methode der Elternklasse und eine private Methode der Kindklasse gleich heissen, aber unterschiedliche Rückgabewerte haben. Hat auch seinen Grund. Private Methoden sind Methoden, mit deren Hilfe die Klasse ihre Aufgaben erfüllt, stellen aber keine Schnittstelle nach aussen dar. Deshalb erlaubt Java auch das private Methoden in Eltern-Kind-Klassen gleich heissen. Alles andere wäre auch unsinnig. Ich kann bei einer Klassen, deren Sourcecode ich nicht besitze (nur class-Datei) ja gar nicht wissen, dass es diese Methode überhaupt gibt. Trotzdem darf ich ja von dieser Klasse ableiten.

*TRÖT*setzung ist aber, dass beide Methoden (Eltern- und Kindklasse) privat sind. Ansonsten könnte ich ja durch Vererbung die Sichtbarkeit ändern und das ist verboten.

Zum Zitat: "Insofern wird deine Regel..."

Es sind nicht meine Regeln. Ich habe Java nicht erfunden. Ich bin SW-Entwickler und mache gerade eine Expertenausbildung für Java (Ziel ist, die diversen Zertifikate zu erreichen) und war bisher vor allem in C++ unterwegs. Ich weiss deshalb schon ein wenig darüber Bescheid. Ich versuche nur, dir mit meinem Wissen zu helfen so gut ich kann. Ich hoffe, dass wir beide davon profitieren. Ich kann aus deinen Problemen lernen und du auch vielleicht ein bischen von meinem Input profitieren.

Zu 1) Ich hoffe, ich habe dich richtig verstanden. Also: In C++ ist dieser Pferdefuss möglich, weil Methoden dort virtuell (Schlüsselwort: virtual) sein KÖNNEN. Wenn ich mir dessen bewusst bin, ist das ja gar kein Problem. Sonderlich intuitiv finde ich es aber auch nicht (meine Meinung).
In Java sind Methodenaufrufe immer virtuell (das Schlüsselwort gibt's deshalb auch nicht). Deshalb kann ich mich in Java als Aufrufer NIE an dem eigentlichen Typ des Objekts vorbeibewegen. Das Stichwort super in Java kann nur innerhalb einer Klasse verwendet werden, um Methoden bzw. Felder der Elternklasse zu referenzieren, die ich sonst nicht erreichen könnte (weil sie überschrieben wurden).

Nur aus Neugier: Wie könnte ich die Java-Lösung jetzt unabsichtlich falsch benutzen?

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
....
Re(4): Java-Dau-Anfängerproblem...
12.07.2005, 12:53:09
Ad [3] - Übersichtlichkeit...
Ich finde Java grotesk unübersichtlich zum entwickeln - gebe aber gerne zu, daß sich meine Meinung da ändern kann, weil es eben ganz neu für mich ist.
Ich vermisse [noch?] Templates, schlichte Includes, ..
Komplett unübersichtlich finde ich zB die Sichtbarkeitsmodifikatoren: Erstens vermisse ich ein "friends", das ja doch gerne mal was vereinfacht (Es ist zugegeben net zwingend erforderlich, aber oft "handy"), zweitens finde ich es absolut unintuitiv, daß kein Modifikator mehr Sicherheit bietet als ein "protected" ;-). Aber letzter Punkt ganz sicher rein aus dem Bauch raus...
Ad private:
Entweder, ich hab' mich gestern vertippt, oder ein private in der Vaterklasse nutzte nix... Ich änderte nur die Sichtbarkeit der Vaterklasse auf private - im Kind müßte [IMHO] protected oder sogar public erlaubt sein. Denn aus Sicht der Kindklasse müßte es ja so aussehen, daß es in der Vaterklasse die Methode gar net gab - eben weil sie dort private war... Oder es liegt einfach daran, daß Sichtbarkeiten in Kindklassen net erweitert werden dürfen.

Ad 'Zum Zitat: "Insofern wird deine Regel..."' - war nicht als Kritik an Dir gemeint - sorry, wenn es so ankam. So war es echt net gemeint..
Ich profitier stark von deinem Fachwissen - und bin mir dessen durchaus bewußt - sei unbesorgt *virtuelles Bier spendier* ;-)

Ad 1 - virtual...
War in Delphi genauso wie in TurboVision [in den beiden sammelte ich den Großteil meiner OO-Kenntnisse] - wie in C. Wobei es IMHO gleichwertig ist, entweder virtuelle Methoden zu kennzeichnen ("virtual") - oder nicht-virtuelle ("final"). Nachdem jeder Zugriff über eine VMT allerdings teuer ist - gefällt mir der Ansatz von C++ besser... Wenn was teuer sein soll-sag's... sonst nehm' ich per Default den billigeren ;-)
Zu dem Falschbenutzen.... Ich hab's zugegebenermaßen net versucht...
Aber könnte ein Aufrufer net ein super.add() verwenden - sofern die Methode add des vaters den Zugriff zuläßt ? Oder ... Welches add würde ein ((Vater)sohn).add() aufrufen ? Sorry, vielleicht [oder sogar sicher] Anfänger-Daufragen ;-)

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.....
Re(5): Java-Dau-Anfängerproblem...
12.07.2005, 13:29:44
Zur Übersichtlichkeit: Ich kann deine Probleme voll nachvollziehen. Das Problem ist IMHO, dass Java zwar eine sehr ähnlich aussehende Syntax hat, aber vom Konzept her komplett verschieden zu C++ ist. Deshalb sind C++-Kenntnisse beim Java lernen auch oft hinderlich.
Etwas ähnliches wie Templates gibt es bereits. Ist in Java 5 neu hinzugekommen und nennt sich Generics.
Includes sind in Java nicht nötig, da es keine Header-Dateien gibt. Grundsätzlich ist jede (sichtbare) Klasse über ihren vollqualifizierten Namen erreichbar (z.B.: packet.subpacket.MeineKlasse). Ein Header einzubinden ist daher nicht nötig. Damit nicht immer der vollqualifizierte Name verwendet werden muss, kann man das import-Statement verwenden.
Sowas wie friends gibt's in Java auch. Es handelt sich um die Pakete. Ich darf innerhalb eines Pakets auf alle, außer auf private deklarierte Methoden & Felder zugreifen. Das heisst, dass alle Klassen innerhalb eines Pakets "friends" sind. Nur der Vollständigkeit halber: Es gibt 4 versch. Sichtbarkeiten: public, protected, private und package-default (dafür gibt's kein Schlüsselwort, sondern einfach nichts schreiben). Klassen selbst können nur public oder package-default sein.

Zu private:
Ich denke, du hast Recht. Eigentlich dürfte add dann in der Kind-Klasse auch protected oder public sein. Ich bin mir da aber ehrlich gesagt unsicher, weil es sich eben um statische Methoden handelt. Da kann es anders geregelt sein, als bei den normalen Methoden. Bei normalen Methoden wäre ich mir sicher, dass privates in der Kind-Klasse ohne Probleme überschrieben werden dürfen (aus den genannten Gründen).

Danke fürs Bier! Ich bin halt etwas übervorsichtig was mögliche Missverständnisse anbetrifft. Ich wollte lediglich sichergehen, dass du das nicht als meine Erfindung missverstehst...

Zu virtual:
In C++ ist es tatsächlich so, dass virtuelle Methoden immer mehr Zeit kosten als nicht-virtuelle. Grund ist, dass C++ statisch übersetzt wird und Objekte der Kindklasse möglicherweise immer präsent sind. Deshalb gibt's ja auch das Schlüsselwort und es ist schon sinnvoll, sich das für die jeweilige Methode zu überlegen.
Bei Java liegt der Fall anders. Die Virtual Machine weiss, welche Klassen präsent sind. Und beim dynamischen übersetzen (Just in time) wird davon auch Gebrauch gemacht. Wenn virtuelle Methoden nicht nötig sind (weil noch keine Kindklassen geladen wurden), dann ist der JIT-Compiler so schlau diese auch direkt, anstatt über eine VMT zu verlinken.
Übrigens: Alle wissenschaftlichen Arbeiten über Performance-Optimierung die ich kenne haben eine Grundaussage. Vorzeitige Performance-Optimierung ist die Quelle alles Bösen ;-)
Denn im Endeffekt liegt der Flaschenhals immer nur an wenigen Stellen, an denen man sie vorher eh nicht vermuten würde. Deshalb als general rule: Immer nachher messen und dann optimieren.

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
......
Re(6): Java-Dau-Anfängerproblem...
12.07.2005, 13:49:56
includes vermissen: Da fehlte ein Zwischenschritt:
Ursprünglich vermißte ich ja parametrisierbare Makros...
Beim nichtfinden vermißte ich "normale" Makros...
Wenn's die auch nicht gibt, muß man halt auf schräge Includes ausweichen, denkt man sich - und so ein quasi-Makro abbilden... Nachdem's die aber auch net gibt ... ;-).

Scheinbar muß man via Delegates alles das lösen, was sonst so trivial einfach funktioniert hätte ;-). Echt, ich programmier in C eigentlich nur im vim - weil's IMHO keinen besseren Editor gibt [Ich hoffe, du bist kein verblendeter emacs-jünger ;-) ]. In Java würde mir das undenkbar erscheinen - und ohne gute GUI's wie Eclipse et al wäre IMHO java unbedienbar... In C, C++, ... konnte ich mit dem vi vom Fleck weg beginnen - in java hätt' ich das nicht hingekriegt - vielleicht bin ich einfach schon zu alt dafür ;-)

Ad *TRÖT*e... Ein package als Friend-workaround würde ich so nicht sehen.. ich hätt' ein package als namespace-äquivalent gesehen... Muß ich aber noch überdenken, zugegeben.

VMT-Methoden kosten übrigens auch in Java mehr zeit - zumindest bin ich in 3 Büchern über die Aussage gestoßen, daß das final()isieren von Methoden Performance bringt, weil die Zugriffe eben nicht mehr die VMT abklappern müssen...

Und ad Performance-Tuning - natürlich nur generell:
IMHO triffst du mit deinem Design der Applikation weitreichende Entscheidungen - auch für die Performance. Natürlich tunst du nachher mit Profiler-Einsatz (hab' ich mir unter Java noch net angesehen) die Hot-Spots... nur bist du dann schon in deinem Design gefangen - zumindest mir geht's oft so. Wenn du zum Schluß draufkommst, daß eine gaaaanz frühe Entscheidung... nun ja - suboptimal ... war, dann kannst nicht mehr alles Umstellen. Daher brauchst IMHO ein sehr sauberes "Grobdesign/Konzept" - an dem nachher nicht mehr gerüttelt werden darf. Und häufig benutzte Klassen würde ich dort vermuten.

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.......
Re(7): Java-Dau-Anfängerproblem...
12.07.2005, 14:28:09
Makros gibt's in Java wirklich nicht. Die sind zwar sehr nützlich, aber auch ein zweischneidiges Schwert. Der Vorteil ist natürlich, dass ich mir ein Haufen Tipparbeit ersparen kann. Nachteile sind aber nicht vorhandene Typsicherheit und stetiges Wiederholen ein- und desselben Codes (jedesmal wenn ich das Makro benutze). Java ist enorm streng was Typen angeht, was auch manchmal lästig ist, dafür aber enorme Sicherheit bietet und viele Fehlerquellen schon im vorhinein eliminiert.
Wie wär's mit (statischen) Methoden?

Eclipse ist schon äußerst praktisch, aber ich hab auch schon mit Notepad entwickelt. Das geht auch ganz gut, aber wahrscheinlich nur wenn man zuvor seine C++-Kenntnisse vergisst :-)

Ad Pakete: Es ist beides. Durch Pakete hab ich einerseits den namespace, andererseits aber auch eine weitere Zugriffsebene. Ich kann ja in C++ zwei Klassen in einen namespace geben, die aber aufeinander nicht zugreifen dürfen. In Java ist das Zugriffsrecht gegeben.

VMT-Methoden: Dieses Gerücht habe ich auch schon öfters gehört ;-) Das war auch für frühere Java-Versionen nicht ganz unrichtig, aber in der modernen hot spot-VM ist das sicher überholt. Wie gesagt: Der JIT-Compiler ist mittlerweile enorm schlau geworden und optimiert bis zum Erbrechen.
Final-Methoden sind aber von ihrem Einsatzzweck her keine Performance-Optimierungsmassnahmen. Sie sind aus ganz anderem Grund da: Wenn ich kein Überschreiben wünsche bzw. kein sinnvolles Überschreiben möglich ist. Das macht in diversen Fällen absolut Sinn.
Dieses Instrument nur zur Performance-Optimierung einzusetzen geht IMHO an der Sache völlig vorbei und kann im schlimmsten Fall nur zu einem führen: vermurkstes Design.

Du hast natürlich Recht mit dem Design. Ich muss da schon Performance-Überlegungen miteinfliessen lassen, sonst komme ich womöglich in Teufels Küche. Was ich meinte, waren Performance-Optimierungen im Code nach dem Motto: "Dieses Statement ist viel schneller, weil im Maschinencode sind das dann nur 4 schnelle XOR-Operationen anstatt..."
Das ist schon in C++ ziemlich unsinnig, weil die Flaschenhälse ja meist im Design entstanden sind und nicht bei irgendwelchen Statements. In Java mit virtueller Maschine, Garbage Collector und JIT-Kompilierung auf allen möglichen unterschiedlichen Plattformen (vom Handy bis zum Business Server) macht sowas ja schon überhaupt keinen Sinn, denn ob und welcher Maschinencode da herauskommen wird ist beim Schreiben sicher nicht vorhersehbar...



Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
........
Re(8): Java-Dau-Anfängerproblem...
12.07.2005, 14:38:28
Makros ... zweischneidiges Schwert.

Sehe ich nicht so... Bei korrekter Anwendung (und das gilt natürlich immer) sind sie pippifein... Wobei ich nicht ein Macro meinte wie
#define X 20
sondern eines wie
#define X(y) { ....
Also ein funktionsmacro.

... mit Notepad entwickelt ...

Sorry, aber das brachte mich zum Lachen... Da gibt's vi, vim, für die Ketzer gibt's Emacs (beides weit länger als Windows/Notepad) - und du hast mit Notepad entwickelt... Finde ich insoferne lustig, als ich einen Java-Fan gut kenne, der bekennender Masochist ist ;-)... Aaaah, ich erkenne ein Muster ;-)

Dieses Instrument nur zur Performance-Optimierung einzusetzen geht IMHO an der Sache völlig vorbei und kann im schlimmsten Fall nur zu einem führen: vermurkstes Design.

Da hab' ich mich schlecht ausgedrückt... Ich wollte nie von final nur zum Optimieren verwenden sprechen... Sondern eben auch. Denn es macht ja sinn, nur das virtuell zu verwenden, was auch überladbar sein soll... Meine primäre Informationsquelle ist Guido Krüger's Handbuch der Java-Programmierung [www.javabuch.de] - das mir auf Java-Einführungskursen der IBM empfohlen wurde... Dort kommt u.a. auch das final vor.

Den letzten Absatz teil ich wieder mit Dir - meine Rede... Mit dem Design der App kannst am meisten Gewinnen/verlieren. Nur scheint es bei mir so, als ob du unter Java net nur mit "ein paar" Design-Pattern auskommst, sondern dir echt die Literatur der 3er-Bande zu Gemüte führen mußt... Soviel zu einfacher, leicht erlernbarer Sprache ;-)

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.........
Re(9): Java-Dau-Anfängerproblem...
12.07.2005, 15:11:21
Ich denke, eine endgültige Entscheidung für oder wider Makros kann es nicht geben. Bei korrekter Anwendung haben sie schon was für sich. Klar. In jedem Fall gibt es sie in Java nicht. Unbegründet ist das, wie schon gesagt, auch nicht.

Nun, ich sage nicht das ich besonders gerne in Notepad entwickelt habe. Allein die ständigen Compilefehler *grummel*. Es erfordert enorm viel Disziplin und ist manchmal eine ziemliche Qual. Ich wollte nur sagen, dass es geht. Eclipse ist mir im Übrigen deutlich lieber. Sofort alle Schwachstellen am Schirm (im Hintergrund wird ständig übersetzt), Code Completion, Syntax Highlighting... Aaaah. Wie schön ist doch so eine IDE :-)
Ich bin im Übrigen kein Masochist, sondern beim Programmieren sehr faul. Motto: Muss ich das wirklich selber implementieren? *gg*

"Da hab' ich mich schlecht ausgedrückt..."

Denke ich nicht. Ich wollte dir nur ganz deutlich machen, dass final kein Instrument zur Optimierung ist. Es wäre ja schlechtes Design, wenn ich final nur deswegen schreibe, damit das Programm schneller wird. Es genauso schlechtes Design, es zu vergessen, obwohl es notwendig wäre UND das kostet auch noch (möglicherweise) Performance. Das ist alles. Ich denke, die Drohung mit der Performance-Keule wird nur deshalb ausgepackt, damit man es nicht vergisst. Aber das ist nur meine Meinung.

Deinem letzten Absatz stimme ich voll zu. Ich möchte nur noch anmerken, dass sich hinter dem Begriff Java ja vielerlei verschiedene Dinge verbergen. Deshalb kommt es wahrscheinlich zu so vielen (falschen) Gemeinplätzen und Missverständnissen.

Die reine Sprache Java ist syntaktisch äußerst einfach gehalten. Die Java Language Specification ist sicher viel dünner als die entsprechende Syntax-Beschreibung der Sprache C++.

Die Designprinzipien und Patterns, die hinter dem Konzept Java und der Java Bibliothek stehen sind äußert kompliziert. Außerdem hat die Java-Klassenbibliothek mittlerweile einen Umfang erreicht, der eben nicht mal in 5 Minuten zu überblicken ist.

Und der "Nachteil" bei Java ist sicherlich, dass diese Designprinzipien forciert werden. Man ist ja faktisch gezwungen sich mit gutem Design zu beschäftigen, sonst hüpft man mit Java nicht weit.

Also weiterhin viel Glück! ;-)

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
 

Dieses Forum ist eine frei zugängliche Diskussionsplattform.
Der Betreiber übernimmt keine Verantwortung für den Inhalt der Beiträge und behält sich das Recht vor, Beiträge mit rechtswidrigem oder anstößigem Inhalt zu löschen.
Datenschutzerklärung