Cómo importar una clase del paquete predeterminado

98

Posible duplicado: ¿Cómo acceder a las clases de Java en el paquete predeterminado?


Estoy usando Eclipse 3.5 y he creado un proyecto con alguna estructura de paquete junto con el paquete predeterminado. Tengo una clase en el paquete predeterminado: Calculations.java y quiero hacer uso de esa clase en cualquiera de los paquetes (por ejemplo, en com.company.calc). Cuando intento hacer uso de la clase que está en el paquete predeterminado, me da un error de compilación. No puede reconocer la clase en el paquete predeterminado. ¿Dónde está el problema?

Calculations.java - código fuente

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

No puedo poner mi clase en ningún otro paquete. Esta clase tiene algunos métodos nativos que se implementan en Delphi. Si pongo esa clase en cualquiera de las carpetas, tendré que hacer cambios en esa DLL que quiero evitar (en realidad, no puedo). Por eso puse mi clase en el paquete predeterminado.

Michał Ziober
fuente
1
Encontré este enlace: stackoverflow.com/questions/283816/… después de crear estas preguntas.
Michał Ziober
Por supuesto, lo importante de esta pregunta es que la clase y su código deben estar en el paquete predeterminado . A partir de ahora, cualquier respuesta que no sea usar la API de reflexión (en realidad, una exageración para algo tan simple) no es una solución. Es alucinante cómo Java intenta tener su pastel (desalienta el paquete predeterminado) y comérselo también (hacer que JNI sea tan complicado, la mayoría de nosotros termina usando DLL que requieren un paquete predeterminado).
ADTC
La razón parece histórica, pero a veces pica. p. ej., `` `T.java: importar static a.Foo. *; clase T {Barra de barra = nueva barra (); } a / Foo.java: paquete a; public class Foo {public static final class Bar {}} `` `Lo anterior se compila bien, sin embargo, si Foo se coloca en el paquete predeterminado, no funciona. Por lo tanto, no puedo importar Foo. * Estáticamente para usar la abreviatura Bar en lugar de Foo.Bar.
Kedar Mhaswade

Respuestas:

87

De la especificación del lenguaje Java :

Es un error de tiempo de compilación importar un tipo del paquete sin nombre.

Tendrá que acceder a la clase a través de la reflexión o algún otro método indirecto.

McDowell
fuente
1
Wow, realmente no sé nada de Java. Eso fue de gran ayuda. Supongo que tendré que mover mi clase a un paquete ...
anhoppe
46

Las clases en el paquete predeterminado no pueden ser importadas por clases en paquetes. Es por eso que no debe usar el paquete predeterminado.

mate b
fuente
Esta debería ser la respuesta predeterminada aceptada, ya que es la más útil. Gracias.
Neoraptor
8

Existe una solución para su problema. Puedes usar la reflexión para lograrlo.

Primero, cree una interfaz para su clase objetivo Calculatons:

package mypackage;

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

}

A continuación, haga que su clase objetivo implemente esa interfaz :

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

Finalmente, use la reflexión para crear una instancia de Calculationsclase y asígnela a una variable de tipo CalculationsInterface:

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

Puedo darte esta sugerencia, por lo que sé de mi experiencia en programación C y C ++, una vez, cuando tuve el mismo problema, lo resolví cambiando la estructura escrita dll en el archivo ".C" cambiando el nombre del función que implementó la funcionalidad nativa de JNI. por ejemplo, si desea agregar su programa en el paquete "com.mypackage", cambie el prototipo del JNI que implementa la función / método del archivo ".C" a este:

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
}

Como soy nuevo en Delphi, no puedo garantizarle, pero diré esto finalmente (aprendí algunas cosas después de buscar en Google sobre Delphi y JNI): Pregúntele a esas personas (si no es usted) que proporcionaron la implementación de Delphi de la versión nativa. código para cambiar los nombres de las funciones a algo como esto:

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;

Pero, un último consejo: aunque usted (si es el programador de Delphi) o ellos cambiarán los prototipos de estas funciones y volverán a compilar el archivo dll, una vez compilado el archivo dll, no podrá cambiar el nombre del paquete de su Archivo "Java" una y otra vez. Porque, esto requerirá nuevamente que usted o ellos cambien los prototipos de las funciones en delphi con prefijos cambiados (por ejemplo, JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Creo que esto resuelve el problema. Gracias y saludos, Harshal Malshe

Harshal Malshe
fuente
Esto es bueno para cualquiera que intente utilizar bibliotecas nativas en sus proyectos.
Randnum
5

De algún lugar donde encontré a continuación: -

De hecho, puedes.

Usando la API de reflexiones puedes acceder a cualquier clase hasta ahora. Al menos pude :)

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
fuente
2
Parece que la reflexión es el único camino a seguir. Tengo una biblioteca JNI que simplemente se niega a funcionar cuando está en cualquier paquete que no sea el predeterminado. No construí la DLL, así que no puedo reconstruirla. Todo lo que haga tiene que estar en Java. Gracias por salvar el día :)
ADTC
3

Desafortunadamente, no puede importar una clase sin que esté en un paquete. Esta es una de las razones por las que se desaconseja mucho. Lo que probaría es una especie de proxy: ponga su código en un paquete que cualquier cosa pueda usar, pero si realmente necesita algo en el paquete predeterminado, conviértalo en una clase muy simple que reenvíe las llamadas a la clase con el código real. O, incluso más simple, simplemente haz que se extienda.

Para dar un ejemplo:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}
Jon
fuente
1

Cree un nuevo paquete y luego mueva las clases del paquete predeterminado en un nuevo paquete y use esas clases

Khushboo Kashyap
fuente
¡Bienvenido a StackOverflow! Quizás pueda agregar más detalles para explicar mejor las partes más importantes de su respuesta. Lea ¿Cómo escribo una buena respuesta? para más información. Además, una vez que obtenga más reputación, podrá publicar esto como un comentario en lugar de una respuesta, lo que sería más apropiado.
Francesco B.
-1
  1. Crea un paquete nuevo.
  2. Mueva sus archivos del paquete predeterminado al nuevo.
Evgueni
fuente
-3
  1. Cree un paquete (carpeta) "raíz" en su proyecto, por ejemplo.

    fuente del paquete; (... / ruta_al_proyecto / fuente /)

  2. Mueva YourClass.class a una carpeta de origen. (... / ruta_al_proyecto / fuente / YourClass.class)

  3. Importar como este

    import source.YourClass;

Andrey
fuente
1
mala respuesta, si quiere esto, lo necesita por defecto, no en algún paquete personalizado
Enerccio