2010-02-03 5 views
74

Possible en double: How to access java-classes in the default-package?Comment importer une classe de package par défaut


J'utilise Eclipse 3.5 et j'ai créé un projet avec une structure de paquet avec le package par défaut. J'ai une classe dans le paquet par défaut - Calculations.java et je veux faire l'utilisation de cette classe dans l'un des paquets (par exemple dans com.company.calc). Lorsque j'essaie de faire l'utilisation de la classe qui est dans le paquetage par défaut, cela me donne une erreur de compilation. Il n'est pas capable de reconnaître la classe dans le package par défaut. Où est le problème?

Calculations.java - code source

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

Je ne peux pas mettre ma classe dans un autre paquet. Cette classe a des méthodes natives qui sont implémentées dans Delphi. Si je mets cette classe dans l'un des dossiers, je vais devoir apporter des modifications à cette DLL que je veux éviter (vraiment - je ne peux pas). C'est pourquoi j'ai mis ma classe dans le paquet par défaut.

+1

J'ai trouvé ce lien: http://stackoverflow.com/questions/283816/how-to-access-java-classes-in-the-default-package après avoir créé cette question. –

+0

duplication possible de [Quelle est la syntaxe pour importer une classe dans un package par défaut en Java?] (Http://stackoverflow.com/questions/2030148/whats-the-syntax-to-import-a-class-in-a -default-package-in-java) – Pops

+0

Bien sûr, le bit important de cette question est que la classe ** et ** son code ** doit être dans le paquet par défaut **. A partir de maintenant, toute autre réponse que d'utiliser l'API de réflexion * (vraiment, une surpuissance pour quelque chose d'aussi simple) * n'est pas ** une solution. Il est ahurissant de voir comment Java essaie d'avoir son gâteau (décourager le paquetage par défaut) et de le manger aussi (rendre JNI si compliqué, la plupart d'entre nous finissent par utiliser des DLL qui nécessitent un paquetage par défaut). – ADTC

Répondre

70

De l'Java language spec:

Il est une erreur de compilation d'importer un type de l'emballage sans nom.

Vous devrez accéder à la classe par réflexion ou par une autre méthode indirecte.

+1

J'utilise la réflexion pour résoudre mon problème. –

+0

Wow, je ne sais vraiment pas java du tout. C'était une aide précieuse. J'imagine que je devrais déplacer ma classe dans un paquet ... – anhoppe

1

Malheureusement, vous ne pouvez pas importer une classe sans qu'elle soit dans un package. C'est l'une des raisons pour lesquelles il est fortement découragé. Ce que je voudrais essayer est une sorte de proxy - mettre votre code dans un paquet que tout peut utiliser, mais si vous avez vraiment besoin de quelque chose dans le paquet par défaut, faites une classe très simple qui transmet les appels à la classe avec le vrai code. Ou, encore plus simple, il suffit de l'étendre.

Pour donner un exemple:

import my.packaged.DefaultClass; 

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

public class DefaultClass { 

    // Code here 

}
37

Classes dans le package par défaut ne peuvent pas être importés par les classes dans des emballages. C'est pourquoi vous ne devriez pas utiliser le paquet par défaut.

4

Je peux vous donner cette suggestion, autant que savoir de mon C et C++ expérience de programmation, Une fois, quand j'eu le même problème un peu, je l'ai résolu en changeant la structure écrite dll dans le fichier « .C » en changeant le nom de la fonction qui a implémenté la fonctionnalité native de JNI. par exemple, Si vous souhaitez ajouter votre programme dans le package "com.mypackage", Vous modifiez le prototype de l'implémentation JNI ".C » Fonction de fichier/méthode pour celui-ci:

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 
} 

Depuis que je suis nouveau à DELPHI, je ne peux pas vous garantir, mais dis cela enfin, (je l'ai appris quelques petites choses après googler sur Delphi et JNI): Demandez ces personnes (Si vous n'êtes pas celui) qui ont fourni la mise en œuvre Delphi du code natif pour changer les noms de fonction à quelque chose comme ceci:

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; 

Mais, un dernier conseil: Bien que vous (si vous êtes le delphi programmeur) ou eux vont changer les prototypes de ces fonctions et recompiler le fichier dll, une fois le fichier dll compilé, vous ne serez pas en mesure de changer le nom du paquet de votre fichier "Java" à nouveau & à nouveau. Parce que, ce que vous ou les demandera à nouveau de changer les prototypes des fonctions en delphi avec des préfixes modifiés (par exemple JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Je pense que cela résout le problème. Merci et salutations, Harshal Malshe

+0

Ceci est bon pour n'importe qui essayant d'employer des bibliothèques natives dans leurs projets. – Randnum

+0

oui. fonctionne comme le charme! – nikk

3

De quelques-uns où je trouve ci-dessous: -

En fait, vous pouvez. En utilisant l'API reflections, vous pouvez accéder à n'importe quelle classe jusqu'à présent.

Au moins, j'ai pu :)

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

Cela a fonctionné pour moi parfaitement !, merci! – Israelm

+1

On dirait que la réflexion est la seule solution. J'ai une bibliothèque JNI qui refuse tout simplement de travailler dans un paquet autre que celui par défaut. Je n'ai pas construit la DLL, donc je ne peux pas la reconstruire. Tout ce que je fais doit être en Java. Merci d'avoir sauvé la journée :) – ADTC

-1
  1. Créer package "root" (dossier) dans votre projet, par exemple.

    source de paquet; (.../path_to_project/source /)

  2. Déplacez YourClass.class dans un dossier source. (.../path_to_project/source/YourClass.class)

  3. importation comme ce

    source.YourClass à l'importation;

+1

mauvaise réponse, s'il le veut, il en a besoin par défaut, pas dans un paquet personnalisé – Enerccio

-1
  1. Créer un nouveau package.
  2. Déplacez vos fichiers du package par défaut vers le nouveau.
5

Il existe une solution de contournement pour votre problème. Vous pouvez utiliser la réflexion pour y parvenir.

d'abord, créez une interface pour votre classe cible Calculatons:

package mypackage; 

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

} 

Ensuite, faites votre classe cible mettre en œuvre cette interface:

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

Enfin, la réflexion utiliser pour créer une instance de Calculations classe et l'affecter à une variable de type CalculationsInterface:

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