2009-11-29 24 views
15

Digamos que una base de código java tiene un paquete llamado "com.example".¿Hay alguna manera de forzar a un cargador de clases a cargar un paquete incluso si no se ha cargado ninguna de sus clases?

En tiempo de ejecución, podemos obtener este paquete llamando

Package p = Package.getPackage("com.example"); //(returns null) 

o incluso obtener una lista de todos los paquetes llamando

Packages[] ps = Package.getPackages(); 

El problema es - si el cargador de clases aún no se ha cargado ningún clase del paquete, no estará disponible para estas llamadas a funciones. Podemos forzar para cargar el paquete por la fuerza de carga de una de las clases del paquete en primer lugar, de esta manera:

this.getClass().getClassLoader().loadClass("com.example.SomeClass"); 
Package p = Package.getPackage("com.example"); //(returns non-null) 

Sin embargo, esto es hacky y requiere saber de antemano el nombre de alguna clase que pertenece a el paquete.

Entonces, la pregunta es: ¿hay alguna forma de obtener una instancia de Paquete por nombre, independientemente de si el ClassLoader ha hecho algo? ¿Son precisas mis suposiciones sobre cómo funcionan los paquetes de clases/paquetes en esta situación?

+0

Cuidado con https://stackoverflow.com/questions/3455267/why-does-class-getpackage-return-the-same-package-for-classes-from-different-pac – Vadzim

Respuesta

11

Alternativamente, podría utilizar el directorio raíz de la clase como punto de partida y recorrer todos los archivos * .class y subdirectorios. Esto solo funcionaría si sabes dónde residirán todos tus archivos .class de antemano.

La causa de todo esto es que Java tiene una carga de clases dinámica, por lo que las clases se pueden cargar en tiempo de ejecución desde ubicaciones desconocidas en tiempo de compilación o incluso en el momento del inicio. Por lo tanto, el concepto de paquete es solo un espacio de nombres para las clases cargadas, no un directorio que puede usar para buscarlas.

5

Me temo que sus suposiciones no son válidas. Los cargadores de clases hacen la contabilidad de los paquetes mientras cargan las clases.

Puede pasar un comodín al ClassLoader.getResources y obligarlo a recoger las clases en un paquete, que a su vez hará el trabajo.

Puede hacer su propio ClassLoader que llame al definePackage, pero eso no lo ayudará con los cargadores de clase usuales de vainilla en uso.

5

Supongo que necesita esto porque necesita inspeccionar sus anotaciones. De lo contrario, no estaría interesado en tener una referencia de paquete que solo tenga acceso a todas las operaciones de anotaciones. Esto lleva a la suposición de que también tiene un package-info.java definido allí con algunas anotaciones.

Si marca java.lang.Package verá que el getPackageInfo solo carga la clase package-info como una clase ordinaria.

Tuve el mismo problema y se me ocurrió esta solución.

public static Package getPackage(String packageName) throws ClassNotFoundException { 
    Class.forName(packageName+".package-info"); // makes sure package info exist and that the class loader already knows about the package 
    return Package.getPackage(packageName); 
} 
Cuestiones relacionadas