Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#46

Re: Delphi mit Java komunizieren

  Alt 4. Sep 2006, 23:05
Zitat von Simon1988:
OK. ich werd mal genauer.
Danke! Sorry, aber so genau wie möglich ist halt immer gut. Im Moment besonders, sitze schon ein Weilchen an der Übersetzung von ein paar Modulen, die schlecht dokumentiert, nur zu sehr eingeschränkten Versionen kompatibel und anstrengend sind (ich hasse Makefiles!!!! Besonders wenn es kein sauberes configure Skript gibt).

Zitat von Simon1988:
Also ich hab in der DateiA eine klasse namens Map. erzeuge ich ein Objekt dieser Klasse so wird automatisch beim Erzeugen der Klasse vom Java Quelltext aus ein weiteres Objekt einer anderen Klasse die aber in DateiB vorliegt.

Ich gebe also den Classpath der DateiA an um die Klasse und den Konstruktor zu finden und rufe den auf.
Meine frage ist nun . Kann der Constructor die DateiB (und damit die weitere Klasse) einfach so finden?
Eine interessante Frage, die uns der Theorie des Classpath näher bringt. Wie bereits gesagt (geht eigentlich auch aus dem Namen hervor), der Classpath ist der reine Javasuchpfad. Alle Klassen die Java verwendet müssen in diesem Pfad liegen. Ein Teil des classpath liegt automatisch im JRE (irgendwo müssen ja die Standardklassen herkommen), der Ordner external (oder so) ist dann der Ablageort für global verwendete Bibliotheken/Klassen. Ich scheue hier nicht den Vergleich mit dem Windows/system32 Ordner. Man kann zwar sicher sein, dass hier gesucht wird, aber es ist ein Ort den man meiden sollte. Je voller dieser Ordner ist, desto unübersichtlicher wird die Sache. Zudem kommt es dann schnell zu den Versionskonflikten und einer Jar-Hölle (oder so ähnlich), die man von DLLs kennt. Einfach kein schöner Ort.
Viel viel besser ist es, wenn man in dem Ordner, indem das Programm liegt die richtige Version der verwendeten Bibliotheken/Klassen findet.
Java kann per Schalter mehrere Pfade für eine JVM in den Classpath aufnehmen.

In der Delphikapselung gibst du den Java-Classpath im Konstruktor der TJVM an. Hier wird der Ort angegeben, in dem alle Packages liegen, die du zusätzlich zu den Standardbibliotheken verwendest. In den Beispielprogrammen von mir ist dies der Unterordner Java/bin. Jetzt fällt dir sicherlich auf, dass du aber keine Datei in diesem Unterordner findest, erst im Ordner /Java/bin/package1/subpackage/ liegt dann die .class Datei.
Wenn du dir die .java Datei der Klasse anschaust, findest du hier auch den Eintrag package package1.subpackage; Ist natürlich kein Zufall. Ein Java Package wird auf die Verzeichnisstruktur abgebildet. Java sucht also die Klasse A aus dem Package package1.subpackage im Classpath. Dazu wird nach dem Ordner package1 gesucht, der einen Unterordner subpackage hat, in dem die Klasse liegt. Weitere Subpackages würden weitere Unterordner mit sich bringen. Dateien eines Packages befinden sich damit natürlich immer im gleichen Ordner. Ich hoffe/denke soweit ist erstmal alles klar?

Ja, der Vollständigkeit halber sei hier natürlich noch gesagt, die Klasse allein (ohne Ordner und Unterordner) kann nicht verwendet werden. Liegt sie in einem Package muss diese Struktur auch abgebildet sein. Dies ist einfach schon deshalb erforderlich, da sonst die Klasse A aus package1 und die völlig andere Klasse A auf package2 nicht einfach irgendwo liegen dürfen, man möchte sie schließlich unterscheiden!

Ok, was hat das alles mit deiner ursprünglichen Frage zu tun? Ganz einfach:
Klasse A möchte eine Instanz von Klasse B erzeugen. Lässt sich Klasse B im Classpath finden, ist das kein Problem. Liegt Klasse B im selben Package wie A tritt nie ein Problem auf. Ansonsten musst du schauen. Liegen die Packages im selben Wurzelordner (im Beispiel wäre dies der Unterordner Java/bin/), würde B gefunden werden (Java/bin/ wird komplett in den Classpath übernommen).
In der Regel wirst du genau diesen Fall haben. Da ich gleich auf die .jar Dateien eingehen werde, lasse ich hier den anderen Fall einfach mal aussen vor (ich kann da eh nichts zu sagen!).


Zitat von Simon1988:
und die zweite frage war eben zum Jar. Da sind alle meine Klassen gespeichert (Auch DateiA und DateiB).
Wie rufe ich genau den Path auf ?
cls := self.jvm.JniEnv.FindClass('SpatialCommander.jar\Da teiA');??
Oh, da hab ich wohl die .jar Dateien etwas falsch erklärt. Nochmal vorweg, die vollen Möglichkeiten eines .jar findest du in der Hilfe von Sun.
Ein .jar File ist wirklich eine tolle Erfindung. Das wichtigste Prinzip hast du schon benannt, du hast alle Klassen in einer Datei. Du kannst dein ganzes Programm einfach in eine einzige Datei packen und hast alles was du brauchst. Wichtig ist hier, dass du eine .jar Datei wie einen lokalen Ordner behandeln kannst. Du hast nicht direkt die Dateien A und B in dem jar File, sondern sie liegen in einem Unterverzeichnis, dass dem Package entspricht.
Für Java verhält sich ein .jar File transparent. Java merkt nicht, dass es ein Archiv ist sondern behandelt diese Datei wie einen normalen Pfad. Du kannst es dir so vorstellen, als ob Java das Archiv aut. entpackt und du dich nun im Wurzelordner des entpackten Archivs befindest.
Das heißt, du kannst auch einfach eine komplette .jar in deinen Classpath aufnehmen und alle Packages die hier drin stecken sind aut. im Classpath zu finden (mit ihren Klassen natürlich). Auch für ein .jar sind nur die .class Dateien wichtig. Die .java sind immer QC und müssen nicht mitgeliefert werden. Ist nur Wichtig bevor du Kunden Quellcode aushändigst

Wenn du also die jar Datei in den Classpath steckst, kannst du ganz normal auf die Klassen zugreifen. Du musst Java nicht sagen, dass die in einem .jar liegen, dass merkt Java eh nicht. Du greifst ganz normal auf das Package zu.

Ich habe das bekannte Beispiel nochmal mit einem .jar erstellt. Also genau genommen habe ich einfach nur die Unterordner java/bin und java/src entfernt und ihren Inhalt in ein sehr einfaches jar gesteckt. Im jar findest du die Dateien TestClass.class/.java in dem Unterverzeichnis package1/subpackage (also dem eingetragenen Package).
TJvm bekommt nun als Classpath den Pfad der .jar Datei. Das Laden der Klasse erfolgt wie gewohnt mittels
cls := self.jvm.JniEnv.FindClass('package1/subpackage/TestClass); Diese Zeile ist wirklich unverändert. Ich hoffe das zeigt dir nochmal, dass die .jars wirklich transparent für Java sind. Hier gibt es keinen Unterschied zu einem lokalen Verzeichnis, es gelten die gleichen Regeln. Allerdings kann ein .jar File noch ein wenig mehr (was du dann in den Details der Manifest Datei findest).

An sich sind .jar Files sehr gut zu verwenden. Du hast eine einfache und kompakte Form alles wichtige zusammen zu halten und weiter zu reichen. Hier sollte auch noch mal deutlich gesagt werden, dass du so sehr leicht konsistente Versionen von Programmen erstellen und verwalten kannst. Liegen alle verwendeten (nicht Standardklassen) in deinem .jar, ist dieses so komplett und kann verwendet werden. Keine Versionskonflikte und (hoffentlich) keine anderen Probleme.
Wie gesagt, häufig werden .jars auch gleich startfähig ausgeliefert, dann hast du eine startbare Datei und musst dich um nichts kümmern.

Ja, anbei das veränderte / neue Beispiel. Hoffe das macht die Verwendung noch etwas klarer.
Angehängte Dateien
Dateityp: zip javagoesdelphi_144.zip (59,2 KB, 31x aufgerufen)
  Mit Zitat antworten Zitat