Comment importer une classe à partir du package par défaut

98

Dupliquer possible: comment accéder aux classes java dans le package par défaut?


J'utilise Eclipse 3.5 et j'ai créé un projet avec une structure de package avec le package par défaut. J'ai une classe dans le package par défaut - Calculations.java et je souhaite utiliser cette classe dans l'un des packages (par exemple dans com.company.calc). Lorsque j'essaye d'utiliser la classe qui se trouve dans le package par défaut, cela me donne une erreur de compilation. Il ne peut pas 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 mettre ma classe dans aucun autre package. 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 devrai apporter des modifications à cette DLL que je veux éviter (vraiment - je ne peux pas). C'est pourquoi j'ai mis ma classe dans le package par défaut.

Michał Ziober
la source
1
J'ai trouvé ce lien: stackoverflow.com/questions/283816/… après avoir créé cette question.
Michał Ziober
Bien sûr, l'élément important de cette question est que la classe et son code doivent être dans le package par défaut . Pour le moment, toute réponse autre que l'utilisation de l'API de réflexion (vraiment, une exagération pour quelque chose d'aussi simple) n'est pas une solution. C'est époustouflant de voir comment Java essaie d'avoir son gâteau (décourager le paquet 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 paquet par défaut).
ADTC
La raison semble historique, mais elle mord parfois. par exemple `` `` T.java: import statique a.Foo. *; classe T {Bar bar = new Bar (); } a / Foo.java: package a; public class Foo {public static final class Bar {}} `` `` Ce qui précède compile bien, cependant, si Foo est placé dans le package par défaut, cela ne fonctionne pas. Ainsi, je ne peux pas importer statiquement Foo. * Pour utiliser la barre abrégée au lieu de Foo.Bar.
Kedar Mhaswade

Réponses:

87

À partir de la spécification du langage Java :

L'importation d'un type à partir du package sans nom est une erreur de compilation.

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

McDowell
la source
1
Wow, je ne connais vraiment pas du tout java. C'était une aide précieuse. Je suppose que je vais devoir déplacer ma classe dans un package ...
anhoppe
46

Les classes du package par défaut ne peuvent pas être importées par les classes des packages. C'est pourquoi vous ne devez pas utiliser le package par défaut.

mat b
la source
Cela devrait être la réponse acceptée par défaut, car c'est la plus utile. Je vous remercie.
Neoraptor
8

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

Tout 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 en sorte que votre classe cible implémente 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, utilisez la réflexion pour créer une instance de Calculationsclasse et l'assigner à une variable de type CalculationsInterface:

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

Je peux vous donner cette suggestion, pour autant que je sache de mon expérience de programmation C et C ++, Une fois, quand j'ai eu le même problème, je l'ai résolu en changeant la structure écrite par DLL dans le fichier ".C" en changeant le nom du fonction qui a implémenté la fonctionnalité native JNI. par exemple, si vous souhaitez ajouter votre programme dans le package "com.mypackage", vous changez le prototype du JNI implémentant la fonction / méthode du fichier ".C" en 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
}

Puisque je suis nouveau chez Delphi, je ne peux pas vous garantir mais je vais le dire enfin, (j'ai appris peu de choses après avoir googlé à Delphi et JNI): Demandez à ces personnes (si vous n'êtes pas celui) qui ont fourni l'implémentation Delphi du natif code pour changer les noms des fonctions en 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 programmeur delphi) ou eux modifiez les prototypes de ces fonctions et recompilez le fichier dll, une fois le fichier dll compilé, vous ne pourrez pas changer le nom du package de votre Fichier "Java" encore et encore. Parce que, cela vous obligera à nouveau à changer les prototypes des fonctions dans 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

Harshal Malshe
la source
C'est bon pour tous ceux qui essaient d'utiliser des bibliothèques natives dans leurs projets.
Randnum
5

De certains où j'ai trouvé ci-dessous: -

En fait, vous pouvez.

En utilisant l'API réflexions, 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");
Adnan Ghaffar
la source
2
On dirait que la réflexion est la seule voie à suivre. J'ai une bibliothèque JNI qui refuse simplement de fonctionner dans un package 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
3

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éconseillé. Ce que j'essaierais, c'est une sorte de proxy - mettez votre code dans un package que tout peut utiliser, mais si vous avez vraiment besoin de quelque chose dans le package par défaut, faites-en une classe très simple qui transmet les appels à la classe avec le vrai code. Ou, encore plus simple, faites-le simplement s'étendre.

Pour donner un exemple:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}
Jon
la source
1

Créez un nouveau package, puis déplacez les classes du package par défaut dans un nouveau package et utilisez ces classes

Khushboo Kashyap
la source
Bienvenue dans StackOverflow! Peut-être pouvez-vous ajouter plus de détails pour mieux expliquer les parties les plus importantes de votre réponse. Lisez comment écrire une bonne réponse? pour plus d'informations. De plus, une fois que vous aurez plus de réputation, vous pourrez le publier sous forme de commentaire plutôt que de réponse, ce qui serait plus approprié.
Francesco B.
-1
  1. Créez un nouveau package.
  2. Déplacez vos fichiers du package par défaut vers le nouveau.
Evgueni
la source
-3
  1. Créez par exemple un package (dossier) "racine" dans votre projet.

    source du paquet; (... / chemin_du_projet / source /)

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

  3. Importez comme ça

    import source.YourClass;

Andreï
la source
1
mauvaise réponse, s'il veut c'est ça, il en a besoin par défaut, pas dans un package personnalisé
Enerccio