Подтвердить что ты не робот

Вызов метода setter с использованием java-отражения

Мне нужно вызвать методы setter класса с использованием отражения, а код выглядит следующим образом:

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

value - это ArrayList, а метод настройки:

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

A java.lang.NoSuchMethodException вызывается при запуске этого кода, но когда тип параметра метода setter изменяется на ArrayList из List, он выполняет штраф. Есть ли способ сохранить параметр метода setter в супертипе и по-прежнему использовать отражение, не задавая вручную тип параметра при получении метода из класса?

4b9b3361

Ответ 1

В отличие от других ответов, существует очень простое решение. См. java.beans.Statement. Это дает вам возможность выполнить произвольный отражающий код, не беспокоясь о фактических формальных типах (и нескольких других вещах).

Ответ 2

Вы можете использовать BeanUtils:

Шаг # 1

Customer customer = new Customer();

Шаг # 2

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

Вы можете выполнять итерацию всех членов класса с использованием отражения и устанавливать значения соответственно, предполагая, что объект-клиент имеет:

private String firstName;
// Getter and Setter are defined

Ответ 3

Если вы используете фреймворк spring, вы можете использовать PropertyAccessorFactory для извлечения реализации PropertyAccessor интерфейс:

Доступ к свойствам напрямую

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

Доступ к свойствам с помощью аксессуаров/мутаторов

Если вам нужно получить доступ к своим ресурсам, используя их получатели и сеттеры, вы можете использовать вместо этого метод forBeanPropertyAccess:

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

Ответ 4

Существует простое решение, но эта простота идет за счет производительности.

Вместо этого я использую этот монстр:

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 - это то, что вы получаете от своего value.getClass(). Некоторые или все из них могут быть также нулевыми. Затем они рассматриваются как матчи для любых непримитивных полей параметров.

Даже это не прекращается: если существует несколько методов, которые являются полиморфно подходящими, но ни один из которых не соответствует точно, тогда возвращаемый метод выбирается произвольно (выполняется первое совпадение в массиве, возвращаемое clazz.getMethods()). Это поведение отличается от поведения Java Language, в котором всегда используется "самое близкое совпадение".

Если получить метод по имени достаточно (т.е. вы предполагаете, что параметры подходят, если имя совпадает), то вы можете управлять гораздо проще (и несколько быстрее):

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

Чтобы еще больше увеличить его, рассмотрите какой-то кеш.

Ответ 5

Пример set Все filds, используя методы seters, получая значения с помощью 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;
}

Ответ 6

Класс отражения иногда называют динамическим вызовом.

например, давайте рассмотрим методы геттера с использованием отражения

считают, что существует класс под названием MyReflectionClass и имеет метод под названием getreflect(). (например, строка типа) позволяет увидеть, как использовать классы отражения

MyReflectionClass  obj = new MyReflectionClass();

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

теперь метод setter

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

если вам нужно выполнить ту же операцию с последовательностью строки, затем

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

надеюсь, что это может быть полезно

Ответ 7

Обнаружение имен методов с использованием String Handling может выглядеть не так, как нужно. Рассмотрим это как одно из решений.

    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();}