primitivos - Encuentra dinĂ¡micamente la clase que representa un tipo primitivo de Java
tipos de variables en java ejemplos (7)
Necesito hacer algunas llamadas a métodos reflexivos en Java. Esas llamadas incluirán métodos que tienen argumentos que son tipos primitivos (int, double, etc.). La forma de especificar dichos tipos al buscar el método de forma reflexiva es int.class, double.class, etc.
El desafío es aceptar una entrada de una fuente externa que especifique los tipos dinámicamente. Por lo tanto, también necesito presentar estas referencias de Clase dinámicamente. Imagine un archivo delimitado una lista de nombres de métodos con listas de tipos de parámetros:
doSomething int double
doSomethingElse java.lang.String boolean
Si la entrada era algo así como java.lang.String
, sé que podría usar Class.forName("java.lang.String")
para volver a esa instancia de clase. ¿Hay alguna forma de utilizar ese método, u otro, para recuperar las Clases de tipo primitivo?
Editar: Gracias a todos los encuestados. Parece claro que no hay una forma integrada de hacer lo que quiero, así que me conformaré con reutilizar la clase ClassUtils
del framework Spring. Parece contener un reemplazo para Class.forName () que funcionará con mis requisitos.
El marco Spring contiene una clase de utilidad ClassUtils que contiene el método estático forName. Este método se puede utilizar para el propósito exacto que describió.
En caso de que no le guste tener una dependencia en Spring: se puede encontrar el código fuente del método e. gramo. here en su repositorio público. El código fuente de la clase tiene licencia bajo el modelo Apache 2.0.
Sin embargo, tenga en cuenta que el algoritmo utiliza un mapa codificado de tipos primitivos.
Editar: Gracias a los comentaristas Dávid Horváth y Patrick por señalar el enlace roto.
El siguiente código explica cómo obtener la clase de un tipo primitivo cuyo nombre de campo se conoce, por ejemplo, en este caso ''sampleInt''.
public class CheckPrimitve {
public static void main(String[] args) {
Sample s = new Sample();
try {
System.out.println(s.getClass().getField("sampleInt").getType() == int.class); // returns true
System.out.println(s.getClass().getField("sampleInt").getType().isPrimitive()); // returns true
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
class Sample {
public int sampleInt;
public Sample() {
sampleInt = 10;
}
}
También se puede verificar si un valor dado es primitivo o no obteniendo su respectiva clase contenedora o su valor de campo.
public class CheckPrimitve {
public static void main(String[] args) {
int i = 3;
Object o = i;
System.out.println(o.getClass().getSimpleName().equals("Integer")); // returns true
Field[] fields = o.getClass().getFields();
for(Field field:fields) {
System.out.println(field.getType()); // returns {int, int, class java.lang.Class, int}
}
}
}
Google Guava ofrece com.google.common.primitives.Primitives
para este tipo de cosas.
Las instancias de Class
para los tipos primitivos se pueden obtener como usted dijo utilizando, por ejemplo, int.class
, pero también es posible obtener los mismos valores usando algo como Integer.TYPE
. Cada clase de envoltura primitiva contiene un campo estático, TYPE
, que tiene la instancia de clase primitiva correspondiente.
No puede obtener la clase primitiva a través de forName
, pero puede obtenerla de una clase que esté fácilmente disponible. Si absolutamente debes usar la reflexión, puedes intentar algo como esto:
Class clazz = Class.forName("java.lang.Integer");
Class intClass = clazz.getField("TYPE").get(null);
intClass.equals(int.class); // => true
Probablemente solo necesite mapear las primitivas y para el resto de las clases realice el método "forName":
Haría algo como:
void someWhere(){
String methodDescription = "doSomething int double java.lang.Integer java.lang.String"
String [] parts = methodDescription.split();
String methodName= parts[0]
Class [] paramsTypes = getParamTypes( parts ); // Well, not all the array, but a, sub array from 1 to arr.length..
Method m = someObject.class.getMethod( methodName, paramTypes );
etc. etc etc.
}
public Class[] paramTypes( String [] array ){
List<Class> list = new ArrayList<Class>();
for( String type : array ) {
if( builtInMap.contains( type )) {
list.add( builtInMap.get( type ) );
}else{
list.add( Class.forName( type ) );
}
}
return list.toArray();
}
// That''s right.
Map<String,Class> builtInMap = new HashMap<String,Class>();{
builtInMap.put("int", Integer.TYPE );
builtInMap.put("long", Long.TYPE );
builtInMap.put("double", Double.TYPE );
builtInMap.put("float", Float.TYPE );
builtInMap.put("bool", Boolean.TYPE );
builtInMap.put("char", Character.TYPE );
builtInMap.put("byte", Byte.TYPE );
builtInMap.put("void", Void.TYPE );
builtInMap.put("short", Short.TYPE );
}
Es decir, crea un mapa donde se almacenan los tipos de primitivas y si la descripción pertenece a una primitiva, utiliza la clase mapeada. Este mapa también se puede cargar desde un archivo de configuración externo, para agregar flexibilidad para que agregue String como una función incorporada en lugar de java.lang.String o potencialmente tenga un método como este.
"doSomething string yes | no"
Hay muchos tipos de este tipo de código en proyectos de sistema operativo como Struts, Hibernate, Spring y Apache libs (solo por mencionar algunos), por lo que no necesita comenzar desde cero.
Por cierto. No compilé el código anterior, pero estoy bastante seguro de que funciona con pequeñas modificaciones, no me vote por eso.
Varios métodos de Clase no manejan primitivas de manera consistente desafortunadamente. Una forma común de esto en forName es tener una tabla como;
private static final Map<String, Class> BUILT_IN_MAP =
new ConcurrentHashMap<String, Class>();
static {
for (Class c : new Class[]{void.class, boolean.class, byte.class, char.class,
short.class, int.class, float.class, double.class, long.class})
BUILT_IN_MAP.put(c.getName(), c);
}
public static Class forName(String name) throws ClassNotFoundException {
Class c = BUILT_IN_MAP.get(name);
if (c == null)
// assumes you have only one class loader!
BUILT_IN_MAP.put(name, c = Class.forName(name));
return c;
}
Apache Commons Lang tiene ClassUtils.getClass(String) , que admite tipos primitivos.