Come importare una classe dal pacchetto predefinito


98

Possibile duplicato: come accedere alle classi java nel pacchetto predefinito?


Sto usando Eclipse 3.5 e ho creato un progetto con una struttura di pacchetti insieme al pacchetto predefinito. Ho una classe nel pacchetto predefinito - Calculations.java e voglio utilizzare quella classe in qualsiasi pacchetto (ad esempio in com.company.calc). Quando provo a utilizzare la classe che si trova nel pacchetto predefinito, mi dà un errore del compilatore. Non è in grado di riconoscere la classe nel pacchetto predefinito. Dov'è il problema?

Calculations.java - codice sorgente

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

Non posso inserire la mia classe in nessun altro pacchetto. Questa classe ha alcuni metodi nativi che sono implementati in Delphi. Se metto quella classe in una qualsiasi delle cartelle, dovrò apportare modifiche a quella DLL che voglio evitare (davvero - non posso). Ecco perché ho inserito la mia classe nel pacchetto predefinito.


1
Ho trovato questo collegamento: stackoverflow.com/questions/283816/… dopo aver creato queste domande.
Michał Ziober


Ovviamente, la parte importante di questa domanda è che la classe e il suo codice devono essere nel pacchetto predefinito . A partire da ora, qualsiasi risposta diversa dall'uso dell'API di riflessione (in realtà, un eccessivo per qualcosa di così semplice) non è una soluzione. È sbalorditivo il modo in cui Java cerca di avere la sua torta (scoraggiare il pacchetto predefinito) e anche di mangiarlo (rendi JNI così contorto, la maggior parte di noi finisce per utilizzare DLL che richiedono un pacchetto predefinito).
ADTC

Il motivo sembra storico, ma a volte morde. ad esempio `` T.java: import static a.Foo. *; classe T {Bar bar = new Bar (); } a / Foo.java: pacchetto a; public class Foo {public static final class Bar {}} `` `` Quanto sopra si compila bene, tuttavia, se Foo è inserito nel pacchetto predefinito, non funziona. Pertanto, non posso importare staticamente Foo. * In modo da utilizzare l'abbreviazione Bar invece di Foo.Bar.
Kedar Mhaswade

Risposte:


87

Dalle specifiche del linguaggio Java :

È un errore in fase di compilazione importare un tipo dal pacchetto senza nome.

Dovrai accedere alla classe tramite la riflessione o qualche altro metodo indiretto.


1
Wow, non conosco affatto Java. È stato di grande aiuto. Immagino che dovrò spostare la mia classe in un pacco ...
anhoppe

46

Le classi nel pacchetto predefinito non possono essere importate dalle classi nei pacchetti. Questo è il motivo per cui non dovresti usare il pacchetto predefinito.


Questa dovrebbe essere la risposta predefinita accettata, poiché è la più utile. Grazie.
Neoraptor

8

C'è una soluzione alternativa per il tuo problema. Puoi usare la riflessione per ottenerlo.

Innanzitutto, crea un'interfaccia per la tua classe target Calculatons:

package mypackage;

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

}

Quindi, fai in modo che la tua classe di destinazione implementi quell'interfaccia :

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

Infine, usa la reflection per creare un'istanza di Calculationsclasse e assegnarla a una variabile di tipo CalculationsInterface:

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

5

Posso darti questo suggerimento, Per quanto ne so dalla mia esperienza di programmazione C e C ++, Una volta, quando ho avuto lo stesso tipo di problema, l'ho risolto cambiando la struttura scritta della dll in File ".C" cambiando il nome del funzione che ha implementato la funzionalità nativa di JNI. ad esempio, se desideri aggiungere il tuo programma nel pacchetto "com.mypackage", modifichi il prototipo del JNI che implementa la funzione / metodo del file ".C" in questo:

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
}

Dato che sono nuovo di Delphi, non posso garantirti, ma alla fine lo dirò (ho imparato poche cose dopo aver cercato su Google di Delphi e JNI): Chiedi a quelle persone (se non sei tu) che hanno fornito l'implementazione Delphi del nativo codice per cambiare i nomi delle funzioni in qualcosa di simile:

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;

Ma, un ultimo consiglio: sebbene tu (se sei il programmatore delphi) o loro cambierai i prototipi di queste funzioni e ricompilerai il file dll, una volta compilato il file dll, non sarai in grado di cambiare il nome del pacchetto del tuo File "Java" ancora e ancora. Perché, questo richiederà di nuovo a te o loro di modificare i prototipi delle funzioni in delphi con prefissi modificati (ad esempio JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Penso che questo risolva il problema. Grazie e saluti, Harshal Malshe


Questo è utile per chiunque cerchi di utilizzare le librerie native nei propri progetti.
Randnum

5

Da alcuni dove ho trovato di seguito: -

In effetti puoi.

Utilizzando l'API Reflections puoi accedere a qualsiasi classe fino ad ora. Almeno sono stato in grado di :)

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

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

2
Sembra che la riflessione sia l'unica strada da percorrere. Ho una libreria JNI che si rifiuta semplicemente di funzionare quando si trova in un pacchetto diverso da quello predefinito. Non ho creato la DLL quindi non posso ricostruirla. Tutto quello che faccio deve essere in Java. Grazie per aver salvato la giornata :)
ADTC

3

Sfortunatamente, non puoi importare una classe senza che sia in un pacchetto. Questo è uno dei motivi per cui è altamente scoraggiato. Quello che proverei è una sorta di proxy: inserisci il tuo codice in un pacchetto che può essere utilizzato da qualsiasi cosa, ma se hai davvero bisogno di qualcosa nel pacchetto predefinito, rendila una classe molto semplice che inoltra le chiamate alla classe con il codice reale. O, ancora più semplice, fallo estendere.

Per fare un esempio:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}

1

Crea un nuovo pacchetto E poi sposta le classi del pacchetto predefinito nel nuovo pacchetto e usa quelle classi


Benvenuto in StackOverflow! Forse puoi aggiungere più dettagli, per spiegare meglio le parti più importanti della tua risposta. Leggi come scrivo una buona risposta? per maggiori informazioni. Inoltre, una volta ottenuta una maggiore reputazione, sarai in grado di pubblicarlo come commento piuttosto che come risposta, il che sarebbe più appropriato.
Francesco B.

-1
  1. Crea un nuovo pacchetto.
  2. Sposta i tuoi file dal pacchetto predefinito a quello nuovo.

-3
  1. Ad esempio, crea il pacchetto (cartella) "root" nel tuo progetto.

    sorgente del pacchetto; (... / path_to_project / source /)

  2. Sposta YourClass.class in una cartella di origine. (... / path_to_project / source / YourClass.class)

  3. Importa in questo modo

    import source.YourClass;


1
brutta risposta, se vuole questo, ne ha bisogno di default, non in qualche pacchetto personalizzato
Enerccio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.