aanhalen setter methode met behulp van Java reflectie

Ik moet de setter methoden van een klasse te roepen met behulp van reflectie, en de code is als volgt:

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

valueeen ArrayListen de aanbrenginrichting werkwijze is als volgt:

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

A java.lang.NoSuchMethodExceptionwordt gegooid bij het uitvoeren van deze code, maar wanneer de aanbrenginrichting methodeparameter type wordt gewijzigd in ArrayListin Listhet voert prima. Is er een manier om de setter methode parameter in super-type en nog steeds gebruik reflectie te houden, zonder handmatig te geven van het type van de parameter bij het krijgen van de methode uit de klasse?


Antwoord 1, Autoriteit 100%

Je zou kunnen gebruiken BeanUtils :

Stap # 1

Customer customer = new Customer();

Stap # 2

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

Je zou kunnen herhalen alle groepsleden met behulp van reflectie en ingestelde waarden dienovereenkomstig, ervan uitgaande dat de klant object:

private String firstName;
// Getter and Setter are defined

Antwoord 2, gezag 96%

Als je toevallig gebruik Spring Framework , kunt u de PropertyAccessorFactory voor het ophalen van een implementatie van de PropertyAccessor interface:

Toegang eigenschappen direct

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

Toegang opent via accessors / mutators

Als u nodig hebt om toegang te krijgen tot uw eigenschappen met behulp van de doorzetters en setters , kunt u in plaats daarvan gebruik maken van de forBeanPropertyAccessmethode:

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

Antwoord 3, gezag 46%

In tegenstelling tot andere antwoorden, is er een heel eenvoudige oplossing. Zie java.beans.Statement. Het geeft je een manier om willekeurige reflecterende code uit te voeren, zonder zich zorgen te maken over de werkelijke versus formele types (en een paar andere dingen).


Antwoord 4, Autoriteit 7%

Er is een eenvoudige oplossing , maar dat eenvoud ten koste gaat van de prestaties.

Ik gebruik dit monster in plaats:

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

parameterTypeszijn wat u krijgt van uw value.getClass(). Sommige of alle kunnen ook nul zijn. Daarna worden ze behandeld als overeenkomsten voor alle niet-primitieve parametervelden.

Zelfs dit is nog niet helemaal perfect: als er verschillende methoden zijn die polymorf geschikt zijn, maar geen daarvan exact overeenkomt, wordt de geretourneerde methode willekeurig gekozen (de eerste overeenkomst in de array die clazz.getMethods()retouren worden in rekening gebracht). Dit gedrag wijkt af van het taalgedrag van Java, waarbij altijd de “beste overeenkomst” wordt gebruikt.

Als het voldoende is om de methode op naam te krijgen (d.w.z. u gaat ervan uit dat de parameters geschikt zijn als de naam overeenkomt), dan kunt u het veel eenvoudiger (en iets sneller) doen:

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

Overweeg een soort cache om het verder op te krikken.


Antwoord 5, autoriteit 5%

Reflection Class wordt soms dynamische aanroep genoemd.

laten we bijvoorbeeld eens kijken naar getter-methoden met behulp van reflectie

bedenk dat er een klasse is met de naam MyReflectionClassen een methode heeft met de naam getreflect(). (bv. type string)
laten we eens kijken hoe we reflectieklassen kunnen gebruiken

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

now setter-methode

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

als u dezelfde bewerking moet uitvoeren met een reeks strings, dan

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

hoop dat het nuttig kan zijn


Antwoord 6, autoriteit 2%

Voorbeeldset Alle filds met behulp van de setters-methoden die de waarden krijgen met 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;
}

Antwoord 7

Het detecteren van methodenamen met behulp van String Handling lijkt misschien niet de juiste manier om dit te doen. Beschouw dit als een van de oplossingen.

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

Other episodes