2010-10-25 10 views
1

J'ai un objet A1 de type A. Je le trouve dynamiquement, cet objet A1 est de type A. J'ai maintenant une propriété dit "Nom" que je voulez accéder à partir de A1, comment puis-je le faire?Accès Méthodes et fonctions d'un objet dont le type de classe est dynamiquement connu

Maintenant le plus gros problème est que l'objet A1 peut même être de type B. S'il est de type B alors je devrai obtenir la valeur "Adresse". Maintenant comment je résous ça?

Ci-dessous le code effectue la vérification de type,


public static void testing(Object A1, String s) s - Classtype 
    { 
     try{ 
      Class c = Class.forName(s); 

      if(c.isInstance(A1)) // 
      { 
       //Now I know that A1 is of the type C. But I dont know what type 'c' is (whether type A or type B. Because Only then I can access the appropriate member.) Like I said, type A contain 'name' and type B contains address. 
       // The access may not only be a member but also a method . 
      } 
     }catch (Exception e){ System.out.println(e);} 
    } 

Les pointeurs aiderait beaucoup. merci

Répondre

3

Vous pouvez connaître les champs déclarés de la classe

Class cls = Class.forName("MyClass"); 
Field fieldlist[] = cls.getDeclaredFields(); 
+0

: O! Java est génial !! Permettez-moi de parcourir toute la page pour plus de précisions. Je vous remercie. – bsoundra

+0

@bsoundra Si vous trouvez exactement cela comme réponse, vous pouvez aussi le marquer comme réponse et/ou upvote aussi. et aussi commencer à le faire pour le reste de vos questions –

0

Les champs sont généralement privés. Donc, pour y accéder, vous devez appeler

field.setAccessible(true); 

BTW, êtes-vous sûr que vous voulez vraiment utiliser la réflexion dans ce cas? Avez-vous probablement pensé à déclarer l'interface? La classe (implémentation) peut encore être chargée dynamiquement. Par exemple, NameAccessor et AddressAccessor sont des interfaces.

FirstClass et SecondClass sont des classes. Supposons que FirstClass implémente NameAccessor et SecondClass implémente les deux interfaces.

Maintenant vous pouvez dire:

Class clazz = Class.forName("SecondClass"); 
Object obj = clazz.newInstance(); 
//...... 
String name = ((NameAccessor)obj).getName(); 
String address = ((AddressAccessor)obj).getAddress(); 

Je pense (à mon humble avis) que cette solution est meilleure que l'accès à des champs privés à l'aide de la réflexion.

1

Ce genre de chose est délicat et sujet aux erreurs si vous le faites manuellement. Vous devriez utiliser l'une des nombreuses classes BeanUtils/BeanHelper que contient presque chaque framework majeur. Voici ma propre exemple d'implémentation rapide que vous pouvez utiliser si vous voulez:

public final class BeanHelper{ 

    /** 
    * Return a map of an object's properties (key: property name, value: 
    * property type). 
    * 
    * @exception NullPointerException 
    *    if bean is null 
    */ 
    public static Map<String, Class<?>> describeProperties(final Object bean){ 
     if(bean == null){ 
      throw new NullPointerException(); 
     } 
     final Map<String, Class<?>> map; 
     final Class<?> beanClass = bean.getClass(); 
     if(PROPERTIES_CACHE.containsKey(beanClass)){ 
      map = PROPERTIES_CACHE.get(beanClass); 
     } else{ 
      final PropertyDescriptor[] propertyDescriptors = 
       getBeanInfo(beanClass); 
      if(propertyDescriptors.length == 0){ 
       map = Collections.emptyMap(); 
      } else{ 
       final Map<String, Class<?>> innerMap = 
        new TreeMap<String, Class<?>>(); 
       for(final PropertyDescriptor pd : propertyDescriptors){ 
        innerMap.put(pd.getName(), pd.getPropertyType()); 
       } 
       map = Collections.unmodifiableMap(innerMap); 
      } 
      PROPERTIES_CACHE.put(beanClass, map); 
     } 
     return map; 
    } 

    private static PropertyDescriptor[] getBeanInfo(final Class<?> beanClass){ 
     try{ 
      return Introspector.getBeanInfo(beanClass, Object.class) 
       .getPropertyDescriptors(); 
     } catch(final IntrospectionException e){ 
      throw new IllegalStateException(
       MessageFormat.format(
       "Couldn''t access bean properties for class {0}", 
       beanClass), 
       e); 
     } 
    } 

    /** 
    * Retrieve a named property from a specified object. 
    * 
    * @return the property 
    * @exception NullPointerException 
    *    if one of the arguments is null 
    * @exception IllegalArgumentException 
    *    if there is no such property 
    */ 
    public static Object getBeanProperty(final Object bean, 
     final String property){ 
     if(bean == null || property == null){ 
      throw new NullPointerException(); 
     } 
     final Class<?> beanClass = bean.getClass(); 
     Map<String, PropertyDescriptor> propMap; 
     if(PROPERTY_DESCRIPTOR_CACHE.containsKey(beanClass)){ 
      propMap = PROPERTY_DESCRIPTOR_CACHE.get(beanClass); 
     } else{ 
      final PropertyDescriptor[] beanInfo = getBeanInfo(beanClass); 
      if(beanInfo.length == 0){ 
       propMap = Collections.emptyMap(); 
      } else{ 
       propMap = 
        new HashMap<String, PropertyDescriptor>(beanInfo.length); 
       for(final PropertyDescriptor pd : beanInfo){ 
        propMap.put(pd.getName(), pd); 
       } 
      } 
      PROPERTY_DESCRIPTOR_CACHE.put(beanClass, propMap); 
     } 
     if(!propMap.containsKey(property)){ 
      throw new IllegalArgumentException(
       MessageFormat.format(
       "Class {0} does not have a property ''{1}''", 
       beanClass, 
       property)); 
     } 
     return invokeMethod(propMap.get(property).getReadMethod(), bean); 

    } 

    private static Object invokeMethod(final Method method, 
     final Object bean, 
     final Object... args){ 
     try{ 
      return method.invoke(bean, args); 
     } catch(final IllegalArgumentException e){ 
      throw e; 
     } catch(final IllegalAccessException e){ 
      throw new IllegalStateException(
       MessageFormat.format(
       "Method not accessible: {0}", 
       method), 
       e); 
     } catch(final InvocationTargetException e){ 
      throw new IllegalStateException(
       MessageFormat.format(
       "Error in method: {0}", 
       method), 
       e); 
     } 
    } 

    private static final Map<Class<?>, Map<String, Class<?>>> 
     PROPERTIES_CACHE = 
     new ConcurrentHashMap<Class<?>, Map<String, Class<?>>>(); 

    private static final Map<Class<?>, Map<String, PropertyDescriptor>> 
     PROPERTY_DESCRIPTOR_CACHE = 
     new ConcurrentHashMap<Class<?>, Map<String, PropertyDescriptor>>(); 

    private BeanHelper(){ 
    } 

} 

Code d'essai:

public static void main(final String[] args){ 
    class Dummy{ 
     private String foo = "bar"; 
     private String baz = "phleem"; 
     public String getFoo(){ 
      return foo; 
     } 
     public void setFoo(final String foo){ 
      this.foo = foo; 
     } 
     public String getBaz(){ 
      return baz; 
     } 
     public void setBaz(final String baz){ 
      this.baz = baz; 
     } 
    } 
    final Object dummy = new Dummy(); 
    final Map<String, Class<?>> beanProperties = 
     BeanHelper.describeProperties(dummy); 
    System.out.println(beanProperties); 
    for(final String key : beanProperties.keySet()){ 
     System.out.println(MessageFormat.format("{0}:{1}", 
      key, 
      BeanHelper.getBeanProperty(dummy, key))); 
    } 
} 

Sortie:

{baz = classe java .lang.String, foo = classe java.lang.String}
baz: phleem
foo: bar

1

Regardez ceci: BeanUtils

myUser.setName("Bob"); 
// can instead be written: 
BeanUtils.setProperty(myUser, "name", "Bob"); 
// and then retrieve: 
BeanUtils.getProperty(myUser, "name");