So importieren Sie eine Klasse aus einem Standardpaket

98

Mögliches Duplikat: Wie greife ich im Standardpaket auf Java-Klassen zu?


Ich verwende Eclipse 3.5 und habe ein Projekt mit einer Paketstruktur zusammen mit dem Standardpaket erstellt. Ich habe eine Klasse im Standardpaket - Calculations.java und möchte diese Klasse in jedem Paket verwenden (zum Beispiel in com.company.calc). Wenn ich versuche, die im Standardpaket enthaltene Klasse zu verwenden, erhalte ich einen Compilerfehler. Die Klasse im Standardpaket kann nicht erkannt werden. Wo ist das Problem?

Calculations.java - Quellcode

public class Calculations {
    native public int Calculate(int contextId);
    native public double GetProgress(int contextId);
    static  {
        System.loadLibrary("Calc");
    }
}

Ich kann meine Klasse nicht in ein anderes Paket packen. Diese Klasse verfügt über einige native Methoden, die in Delphi implementiert sind. Wenn ich diese Klasse in einen der Ordner lege, muss ich Änderungen an der DLL vornehmen, die ich vermeiden möchte (wirklich - ich kann nicht). Deshalb habe ich meine Klasse in das Standardpaket aufgenommen.

Michał Ziober
quelle
1
Ich habe diesen Link gefunden: stackoverflow.com/questions/283816/… nachdem ich diese Fragen erstellt habe.
Michał Ziober
Das Wichtige an dieser Frage ist natürlich, dass sich die Klasse und ihr Code im Standardpaket befinden müssen . Ab sofort keine Antwort außer Gebrauch Reflection - API (wirklich, ein Overkill für etwas so einfach) ist nicht eine Lösung. Es ist umwerfend, wie Java versucht, seinen Kuchen zu haben (Standardpaket entmutigen) und ihn auch zu essen (JNI so kompliziert zu machen, dass die meisten von uns DLLs verwenden, für die Standardpaket erforderlich ist).
ADTC
Der Grund scheint historisch, aber es beißt manchmal. zB `` `T.java: statische a.Foo importieren. *; Klasse T {Balkenbalken = neuer Balken (); } a / Foo.java: Paket a; public class Foo {public static final class Bar {}} `` `Die obige Kompilierung funktioniert einwandfrei. Wenn Foo jedoch in das Standardpaket aufgenommen wird, funktioniert es nicht. Daher kann ich Foo. * Nicht statisch importieren, um die Kurzschrift Bar anstelle von Foo.Bar zu verwenden.
Kedar Mhaswade

Antworten:

87

Aus der Java-Sprachspezifikation :

Es ist ein Fehler bei der Kompilierung, einen Typ aus dem unbenannten Paket zu importieren.

Sie müssen über Reflektion oder eine andere indirekte Methode auf die Klasse zugreifen.

McDowell
quelle
1
Wow, ich kenne Java überhaupt nicht. Das war eine große Hilfe. Ich denke, ich muss meine Klasse in ein Paket umziehen ...
anhoppe
46

Klassen im Standardpaket können nicht von Klassen in Paketen importiert werden. Aus diesem Grund sollten Sie das Standardpaket nicht verwenden.

matt b
quelle
Dies sollte die standardmäßig akzeptierte Antwort sein, da sie am nützlichsten ist. Danke dir.
Neoraptor
8

Es gibt eine Problemumgehung für Ihr Problem. Sie können Reflexion verwenden, um dies zu erreichen.

Zuerst eine Schnittstelle schaffen für Ihre Zielklasse Calculatons:

package mypackage;

public interface CalculationsInterface {  
    int Calculate(int contextId);  
    double GetProgress(int contextId);  

}

Stellen Sie als Nächstes sicher, dass Ihre Zielklasse diese Schnittstelle implementiert :

public class Calculations implements mypackage.CalculationsInterface {
    @Override
    native public int Calculate(int contextId);
    @Override
    native public double GetProgress(int contextId);
    static  {
        System.loadLibrary("Calc");
    }
}

Schließlich Verwendung Reflexion eine Instanz erstellen CalculationsKlasse und weisen Sie auf eine Variable vom Typ CalculationsInterface:

Class<?> calcClass = Class.forName("Calculations");
CalculationsInterface api = (CalculationsInterface)calcClass.newInstance();
// Use it 
double res = api.GetProgress(10);
Mohammad Banisaeid
quelle
5

Ich kann Ihnen diesen Vorschlag machen. Soweit ich aus meiner C- und C ++ - Programmiererfahrung weiß, habe ich ihn einmal, als ich das gleiche Problem hatte, gelöst, indem ich die geschriebene DLL-Struktur in der ".C" -Datei geändert habe, indem ich den Namen der geändert habe Funktion, die die native JNI-Funktionalität implementiert. Wenn Sie beispielsweise Ihr Programm zum Paket "com.mypackage" hinzufügen möchten, ändern Sie den Prototyp der JNI-implementierenden Funktion / Methode der ".C" -Datei in diesen:

JNIEXPORT jint JNICALL
Java_com_mypackage_Calculations_Calculate(JNIEnv *env, jobject obj, jint contextId)
{
   //code goes here
}

JNIEXPORT jdouble JNICALL
Java_com_mypackage_Calculations_GetProgress(JNIEnv *env, jobject obj, jint contextId)
{
  //code goes here
}

Da ich neu bei Delphi bin, kann ich Ihnen keine Garantie geben, werde dies aber abschließend sagen (ich habe einige Dinge gelernt, nachdem ich über Delphi und JNI gegoogelt habe): Fragen Sie die Leute (wenn Sie nicht derjenige sind), die die Delphi-Implementierung des Eingeborenen bereitgestellt haben Code zum Ändern der Funktionsnamen in etwa:

function Java_com_mypackage_Calculations_Calculate(PEnv: PJNIEnv; Obj: JObject; contextId: JInt):JInt; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
var
//Any variables you might be interested in
begin
  //Some code goes here
end;



function Java_com_mypackage_Calculations_GetProgress(PEnv: PJNIEnv; Obj: JObject; contextId: JInt):JDouble; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
var
//Any variables you might be interested in
begin
//Some code goes here
end;

Aber ein letzter Ratschlag: Obwohl Sie (wenn Sie der Delphi-Programmierer sind) oder sie die Prototypen dieser Funktionen ändern und die DLL-Datei neu kompilieren, können Sie den Paketnamen von Ihnen nicht ändern, sobald die DLL-Datei kompiliert ist "Java" -Datei immer wieder. Dafür müssen Sie oder sie erneut die Prototypen der Funktionen in delphi mit geänderten Präfixen ändern (z. B. JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName).

Ich denke, das löst das Problem. Danke und Grüße, Harshal Malshe

Harshal Malshe
quelle
Dies ist gut für alle, die versuchen, native Bibliotheken in ihren Projekten zu verwenden.
Randnum
5

Von einigen, wo ich unten gefunden habe: -

In der Tat können Sie.

Mit der Reflections-API können Sie bisher auf jede Klasse zugreifen. Zumindest konnte ich :)

Class fooClass = Class.forName("FooBar");
Method fooMethod =
    fooClass.getMethod("fooMethod", new Class[] { String.class });

String fooReturned =
    (String) fooMethod.invoke(fooClass.newInstance(), "I did it");
Adnan Ghaffar
quelle
2
Scheint, als wäre Reflexion der einzige Weg. Ich habe eine JNI-Bibliothek, die sich einfach weigert, in einem anderen als dem Standardpaket zu arbeiten. Ich habe die DLL nicht erstellt, daher kann ich sie nicht neu erstellen. Alles was ich tue muss in Java sein. Vielen Dank für die Rettung des Tages :)
ADTC
3

Leider können Sie eine Klasse nicht importieren, ohne sie in einem Paket zu haben. Dies ist einer der Gründe, warum davon dringend abgeraten wird. Was ich versuchen würde, ist eine Art Proxy - fügen Sie Ihren Code in ein Paket ein, das alles verwenden kann, aber wenn Sie wirklich etwas im Standardpaket benötigen, machen Sie dies zu einer sehr einfachen Klasse, die Aufrufe an die Klasse mit dem realen Code weiterleitet. Oder, noch einfacher, lassen Sie es einfach verlängern.

Um ein Beispiel zu geben:

import my.packaged.DefaultClass;

public class MyDefaultClass extends DefaultClass {}
package my.packaged.DefaultClass;

public class DefaultClass {

   // Code here

}
Jon
quelle
1

Erstellen Sie ein neues Paket. Verschieben Sie dann die Klassen des Standardpakets in ein neues Paket und verwenden Sie diese Klassen

Khushboo Kashyap
quelle
Willkommen bei StackOverflow! Vielleicht können Sie weitere Details hinzufügen, um die wichtigsten Teile Ihrer Antwort besser zu erklären. Lesen Sie Wie schreibe ich eine gute Antwort? für mehr Informationen. Sobald Sie mehr Ruf haben, können Sie dies auch als Kommentar und nicht als Antwort veröffentlichen, was angemessener wäre.
Francesco B.
-1
  1. Erstellen Sie ein neues Paket.
  2. Verschieben Sie Ihre Dateien vom Standardpaket in das neue.
Evgueni
quelle
-3
  1. Erstellen Sie beispielsweise ein "Root" -Paket (Ordner) in Ihrem Projekt.

    Paketquelle; (... / path_to_project / source /)

  2. Verschieben Sie YourClass.class in einen Quellordner. (... / path_to_project / source / YourClass.class)

  3. So importieren

    import source.YourClass;

Andrey
quelle
1
schlechte Antwort, wenn er das will, braucht er es standardmäßig, nicht in einem benutzerdefinierten Paket
Enerccio