2010-02-03 11 views
74

Mögliche Duplizieren importieren: How to access java-classes in the default-package?Wie eine Klasse von Standardpaket


Ich verwende Eclipse 3.5 und ich habe ein Projekt mit einiger Paketstruktur zusammen mit dem Standard-Paket erstellt. Ich habe eine Klasse im Standard-Paket - Calculations.java und ich möchte die Verwendung dieser Klasse in einem der Paket (zum Beispiel in com.company.calc) machen. Wenn ich versuche, die Klasse zu verwenden, die im Standardpaket enthalten ist, bekomme ich einen Compilerfehler. Es ist nicht in der Lage, die Klasse im Standardpaket zu erkennen. 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 nicht meine Klasse in einem anderen Paket geschnürt. Diese Klasse hat einige native Methoden, die in Delphi implementiert sind. Wenn ich diese Klasse in einen der Ordner lege, muss ich Änderungen an dieser DLL vornehmen, die ich vermeiden möchte (wirklich - ich kann nicht). Deshalb lege ich meine Klasse in das Standardpaket.

+1

Ich habe diesen Link gefunden: http://stackoverflow.com/questions/283816/how-to-access-java-classes-in-the-default-package nach dem Erstellen dieser Fragen. –

+0

mögliche Duplikate von [Wie lautet die Syntax zum Importieren einer Klasse in ein Standardpaket in Java?] (Http://stackoverflow.com/questions/2030148/whats-the-syntax-to-import-a-class-in-a- -default-package-in-java) – Pops

+0

Natürlich ist das Wichtige an dieser Frage, dass die Klasse ** und ** ihr Code ** im Standardpaket ** sein müssen. Ab sofort ist jede Antwort anders als die Verwendung von Reflection API * (wirklich, ein Overkill für etwas so einfaches) * ist ** keine ** Lösung. Es ist verblüffend, wie Java versucht, seinen Kuchen zu bekommen (vom Standardpaket abzuraten) und ihn auch zu essen (machen Sie JNI so kompliziert, dass die meisten von uns am Ende DLLs verwenden, die ein Standardpaket benötigen). – ADTC

Antwort

70

Vom Java language spec:

Es ist ein Fehler zur Kompilierzeit einen Typen aus dem ungenannten Paket zu importieren.

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

+1

Ich benutze Reflektion, um mein Problem zu lösen. –

+0

Wow, ich kenne Java überhaupt nicht. Das war eine große Hilfe. Ich denke, ich muss meine Klasse in ein Paket verschieben ... – anhoppe

1

Leider können Sie eine Klasse nicht importieren, ohne dass sie in einem Paket enthalten ist. Dies ist einer der Gründe, warum es sehr mutlos ist. Was ich versuchen würde, ist eine Art Proxy - setze deinen Code in ein Paket, das alles verwenden kann, aber wenn du wirklich etwas im Standardpaket brauchst, mach das zu einer sehr einfachen Klasse, die Aufrufe an die Klasse mit dem echten Code weiterleitet. Oder, noch einfacher, einfach erweitern.

ein Beispiel geben:

import my.packaged.DefaultClass; 

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

public class DefaultClass { 

    // Code here 

}
37

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

4

Ich kann Ihnen diesen Vorschlag geben, Soweit weiß aus meiner C und C++ Programmierung Erfahrung, Einmal, als ich das gleiche irgendwie Problem hatte, löste ich es durch die DLL geschrieben Struktur in „.C“ Datei zu ändern durch Ändern des Namens der Funktion, die die native JNI-Funktionalität implementiert hat. zum Beispiel, wenn Sie Ihr Programm in das Paket "com.mypackage" hinzufügen möchten, Sie ändern den Prototyp des JNI implementieren ".C“Datei die Funktion/Methode, um diese:

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 bin neu in delphi, kann ich Ihnen nicht garantieren, aber sagen, dass dies schließlich (ich einige Dinge gelernt, nachdem über Delphi und JNI googeln): Frage diese Leute (Wenn Sie nicht derjenige sind), die die Delphi Umsetzung des nativen Code bereitgestellt, um die Funktionsnamen, so etwas zu ändern:

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 Rat: Auch wenn Sie (Wenn Sie die delphi Programmierer) oder sie werden die Prototypen dieser Funktionen ändern und die DLL-Datei neu kompilieren, sobald die DLL-Datei kompiliert ist, können Sie nicht ändern der Paketname Ihrer "Java" -Datei erneut & erneut. Denn diese wieder werden Sie oder sie benötigen, um die Prototypen der Funktionen in delphi mit geändertenen Präfixen (z JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Ich denke, das löst das Problem zu ändern. Danke und Gruß, Harshal Malshe

+0

Dies ist gut für alle, die versuchen, Native Libraries in ihren Projekten zu verwenden. – Randnum

+0

ja. funktioniert wie Charme! – nikk

3

Von einigen, wo ich Sie unten: -

In der Tat, Sie können.

Mit Reflections-API können Sie bisher auf jede Klasse zugreifen. Immerhin war ich in der Lage

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

String fooReturned = 
    (String) fooMethod.invoke(fooClass.newInstance(), "I did it"); 
+0

Es funktionierte für mich perfekt!, Danke! – Israelm

+1

Scheint, als ob Reflexion der einzige Weg zu gehen ist. Ich habe eine JNI-Bibliothek, die einfach nicht funktioniert, wenn sie in einem anderen als dem Standardpaket ist. Ich habe die DLL nicht erstellt, sodass ich sie nicht wiederherstellen kann. Alles, was ich mache, muss in Java sein. Vielen Dank für die Rettung des Tages :) – ADTC

-1
  1. erstellen "root" Paket (Ordner) in einem Projekt :), zum Beispiel.

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

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

  3. Import ähnliche

    Import source.YourClass;

+1

schlechte Antwort, wenn er das will, braucht er es standardmäßig, nicht in einigen benutzerdefinierten Paket – Enerccio

-1
  1. ein neues Paket erstellen.
  2. Verschieben Sie Ihre Dateien vom Standardpaket zum neuen.
5

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

Zuerst eine Schnittstelle für Ihre Zielklasse Calculatons erstellen:

package mypackage; 

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

} 

Als nächstes Ihre Zielklasse machen diese Schnittstelle implementieren:

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 von Calculations Klasse zu erstellen und weisen Sie es einer Variablen vom Typ CalculationsInterface zu:

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