reflexion principio method ejemplos java reflection

principio - reflection java stack overflow



Invocando el método setter utilizando el reflejo de java (7)

Necesito invocar los métodos setter de una clase usando reflexión, y el código es el siguiente:

try { Method method = myObj.getClass().getMethod("set" + fieldName, new Class[] { value.getClass() }); method.invoke(myObj, value); } catch (Exception ex) { ex.printStackTrace(); }

El value es ArrayList y el método setter es el siguiente:

public void setNames(List<String> names){ this.names = names; }

Se ejecuta una java.lang.NoSuchMethodException al ejecutar este código, pero cuando el tipo de parámetro del método setter cambia a ArrayList de List se ejecuta correctamente. ¿Hay alguna manera de mantener el parámetro del método setter en supertipo y aún usar el reflejo sin dar manualmente el tipo del parámetro al obtener el método de la clase?


Al contrario de otras respuestas, hay una solución realmente simple. Ver java.beans.Statement . Le brinda una forma de ejecutar código reflexivo arbitrario sin tener que preocuparse por los tipos reales frente a los formales (y algunas otras cosas).


Ejemplo de conjunto Todos los gráficos que usan los métodos de setters obtienen los valores con ResultSet.

private Object setAllSetters(Object ob, ResultSet rs) throws SQLException{ // MZ: Find the correct method Class cls = ob.getClass(); while (rs.next()) { for (Field field : cls.getDeclaredFields()){ for (Method method : cls.getMethods()) { if ((method.getName().startsWith("set")) && (method.getName().length() == (field.getName().length() + 3))) { if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase())) { // MZ: Method found, run it try { method.setAccessible(true); if(field.getType().getSimpleName().toLowerCase().endsWith("integer")) method.invoke(ob,rs.getInt(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("long")) method.invoke(ob,rs.getLong(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("string")) method.invoke(ob,rs.getString(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("boolean")) method.invoke(ob,rs.getBoolean(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("timestamp")) method.invoke(ob,rs.getTimestamp(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("date")) method.invoke(ob,rs.getDate(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("double")) method.invoke(ob,rs.getDouble(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("float")) method.invoke(ob,rs.getFloat(field.getName().toLowerCase())); else if(field.getType().getSimpleName().toLowerCase().endsWith("time")) method.invoke(ob,rs.getTime(field.getName().toLowerCase())); else method.invoke(ob,rs.getObject(field.getName().toLowerCase())); } catch (IllegalAccessException | InvocationTargetException | SQLException e) { System.err.println(e.getMessage()); } } } } } } return ob; }


Hay una solución simple , pero esa simplicidad tiene un costo de rendimiento.

Estoy usando este monstruo en su lugar:

public static Method findMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException { // First try the trivial approach. This works usually, but not always. try { return clazz.getMethod(methodName, parameterTypes); } catch (NoSuchMethodException ex) { } // Then loop through all available methods, checking them one by one. for (Method method : clazz.getMethods()) { String name = method.getName(); if (!methodName.equals(name)) { // The method must have right name. continue; } Class<?>[] acceptedParameterTypes = method.getParameterTypes(); if (acceptedParameterTypes.length != parameterTypes.length) { // Must have right number of parameters. continue; } boolean match = true; for (int i = 0; i < acceptedParameterTypes.length; i++) { // All parameters must be right type. if (null != parameterTypes[i] && !acceptedParameterTypes[i].isAssignableFrom(parameterTypes[i])) { match = false; break; } if (null == parameterTypes[i] && acceptedParameterTypes[i].isPrimitive()) { // Accept null except for primitive fields. match = false; break; } } if (match) { return method; } } // None of our trials was successful! throw new NoSuchMethodException(); }

parameterTypes es lo que obtienes de tu value.getClass() . Algunos o todos ellos también pueden ser nulos. Luego se tratan como matces para cualquier campo de parámetro no primitivo.

Incluso esto no es perfecto: si hay varios métodos que son polimórficamente adecuados pero ninguno de los cuales coincide exactamente, el método devuelto se elige arbitrariamente (se toma la primera coincidencia en la matriz que clazz.getMethods() ). Este comportamiento difiere del comportamiento de Java the Language, en el que siempre se utiliza la "coincidencia más cercana".

Si obtener el método por nombre es suficiente (es decir, asumes que los parámetros son adecuados si el nombre coincide), entonces puedes administrarlo con mucho más simple (y algo más rápido):

public static Method findMethod(Class<?> clazz, String methodName) { for (Method method : clazz.getMethods()) { if (method.getName().equals(methodName)) { return method; } } throw new NoSuchMethodException(); }

Para aumentar aún más, considere algún tipo de caché.


La detección de nombres de métodos usando String Handling podría no parecer una forma correcta de hacerlo. Considere esto como una de las soluciones.

try { Animal animal = new Animal(); BeanInfo beaninfo = Introspector.getBeanInfo(Animal.class); PropertyDescriptor pds[] = beaninfo.getPropertyDescriptors(); Method setterMethod=null; for(PropertyDescriptor pd : pds) { setterMethod = pd.getWriteMethod(); // For Setter Method /* You can get Various property of Classes you want. */ System.out.println(pd.getName().toString()+ "--> "+pd.getPropertyType().toString()+"--Setter Method:->"+pd.getWriteMethod().toString()); if(setterMethod == null) continue; else setterMethod.invoke(animal, "<value>"); } }catch(Exception e) {e.printStackTrace();}


Puede usar BeanUtils :

Paso 1

Customer customer = new Customer();

Paso 2

BeanUtils.setProperty(customer,"firstName","Paul Young");

Podría iterar a todos los miembros de la clase utilizando la reflexión y establecer valores en consecuencia, suponiendo que el objeto del cliente tiene:

private String firstName; // Getter and Setter are defined


Reflection Class a veces se llama como invocación dinámica.

por ejemplo, veamos los métodos getter usando la reflexión

considere que hay una clase llamada MyReflectionClass y tiene un método llamado getreflect() . (por ejemplo, tipo cadena) permite ver cómo usar las clases de reflexión

MyReflectionClass obj = new MyReflectionClass(); <? extends MyReflectionClass> tempClass = obj.getClass(); String a = (String) obj.getMethod("getreflect").invoke(obj);

ahora método setter

(String) obj.getDeclaredMethod("setreflect", String.class).invoke(obj,"MyString");

si necesita hacer la misma operación con secuencia de cadena, entonces

(String) obj.getDeclaredMethod("setreflect", new String.class{}).invoke(obj,"MyString1","MyString2");

espero que pueda ser útil


Si usa framework de primavera , podría usar PropertyAccessorFactory para recuperar una implementación de la interfaz de PropertyAccessor :

Acceder a propiedades directamente

PropertyAccessor myAccessor = PropertyAccessorFactory.forDirectFieldAccess(object); // set the property directly, bypassing the mutator (if any) myAccessor.setPropertyValue("someProperty", "some value");

Accediendo a propiedades a través de accessors / mutators

Si necesita acceder a sus propiedades utilizando sus getters y setters , puede usar en su lugar el método forBeanPropertyAccess :

PropertyAccessor myAccessor = PropertyAccessorFactory.forBeanPropertyAccess(object); // a `setSomeProperty()` method will be used myAccessor.setPropertyValue("someProperty", "some value");