Java 访问类类型动态已知的对象的方法和函数

Java 访问类类型动态已知的对象的方法和函数,java,dynamic,classloader,Java,Dynamic,Classloader,我有一个类型为A的对象A1。我动态地发现,该对象A1是类型A。我现在有一个属性,比如“Name”,我想从A1访问它,我该怎么做 现在最大的问题是,对象A1甚至可以是类型B。如果它是类型B,那么我必须获得值“Address”。现在我如何解决这个问题 下面的代码执行类型检查 public static void testing(Object A1, String s) s - Classtype { try{ Class c = Class.forName(s)

我有一个类型为A的对象A1。我动态地发现,该对象A1是类型A。我现在有一个属性,比如“Name”,我想从A1访问它,我该怎么做

现在最大的问题是,对象A1甚至可以是类型B。如果它是类型B,那么我必须获得值“Address”。现在我如何解决这个问题

下面的代码执行类型检查


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

任何指示都会很有帮助。谢谢

您可以知道类的声明字段

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

您可以知道类的声明字段

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

这些字段通常是私有的。所以,要访问它们,你必须打电话

field.setAccessible(true);
顺便说一句,你确定你真的希望在这种情况下使用反射吗?您可能考虑过声明接口吗?类(实现)仍然可以动态加载

例如:
NameAccessor
AddressAccessor
是接口

first class
SecondClass
是类。让我们假设
FirstClass
实现了
NameAccessor
,而
SecondClass
实现了这两个接口

现在你可以说:

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

我认为(IMHO)这种解决方案比使用反射访问私有字段要好。

这些字段通常是私有的。所以,要访问它们,你必须打电话

field.setAccessible(true);
顺便说一句,你确定你真的希望在这种情况下使用反射吗?您可能考虑过声明接口吗?类(实现)仍然可以动态加载

例如:
NameAccessor
AddressAccessor
是接口

first class
SecondClass
是类。让我们假设
FirstClass
实现了
NameAccessor
,而
SecondClass
实现了这两个接口

现在你可以说:

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

我认为(IMHO)这种解决方案比使用反射访问私有字段要好。

如果您手动执行这种操作,则会很棘手且容易出错。您应该使用几乎每个主要框架都包含的众多BeanUtils/BeanHelper类中的一个。下面是我自己的快速示例实现,如果您想:

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

}
public final class BeanHelper{
/**
*返回对象属性的映射(键:属性名称,值:
*属性类型)。
* 
*@exception NullPointerException
*如果bean为null
*/
公共静态地图>地图;
最后一个类beanClass=bean.getClass();
if(属性\u缓存.containsKey(beanClass)){
map=PROPERTIES\u CACHE.get(beanClass);
}否则{
最终PropertyDescriptor[]propertyDescriptors=
getBeanInfo(beanClass);
如果(propertyDescriptors.length==0){
map=Collections.emptyMap();
}否则{
最终地图>();
对于(最终PropertyDescriptor pd:propertyDescriptors){
put(pd.getName(),pd.getPropertyType());
}
map=Collections.unmodifiableMap(innerMap);
}
属性\u CACHE.put(beanClass,map);
}
返回图;
}
私有静态属性描述符[]getBeanInfo(最终类beanClass){
试一试{
返回Introspector.getBeanInfo(beanClass,Object.class)
.getPropertyDescriptors();
}捕获(最终内省异常e){
抛出新的非法状态异常(
MessageFormat.format(
“无法访问类{0}的bean属性”,
beanClass),
e) );
}
}
/**
*从指定对象检索命名属性。
* 
*@归还财产
*@exception NullPointerException
*如果其中一个参数为空
*@exception IllegalArgumentException
*如果没有这样的财产
*/
公共静态对象getBeanProperty(最终对象bean,
最终字符串属性){
if(bean==null | | property==null){
抛出新的NullPointerException();
}
最后一个类beanClass=bean.getClass();
地图;
if(属性\描述符\缓存.containsKey(beanClass)){
propMap=PROPERTY\u DESCRIPTOR\u CACHE.get(beanClass);
}否则{
最终属性描述符[]beanInfo=getBeanInfo(beanClass);
if(beanInfo.length==0){
propMap=Collections.emptyMap();
}否则{
propMap=
新的HashMap(beanInfo.length);
对于(最终属性描述符pd:beanInfo){
put(pd.getName(),pd);
}
}
属性\描述符\缓存.put(beanClass,propMap);
}
如果(!propMap.containsKey(属性)){
抛出新的IllegalArgumentException(
MessageFormat.format(
类{0}没有属性“{1}”,
比恩克拉斯,
财产);;
}
返回invokeMethod(propMap.get(property.getReadMethod(),bean);
}
私有静态对象调用方法(最终方法,
最终对象bean,
最终对象…args){
试一试{
invoke(bean、args);
}捕获(最终非法辩论例外e){
投掷e;
}捕获(最终非法访问例外e){
抛出新的非法状态异常(
MessageFormat.format(
“方法不可访问:{0}”,
方法),
e) );
}捕获(最终调用TargetException e){
抛出新的非法状态异常(
MessageFormat.format(
“方法{0}中有错误”,
方法),
e) );
}
}
私有静态最终M