我有一个类型A的对象A1。我动态地找到了,那个对象A1的类型是A.我现在有一个属性说“Name”,我想从A1访问,我该怎么办?
现在最大的问题是对象A1甚至可以是B类型。如果它是B类型,那么我将不得不获得值“地址”。现在我如何解决这个问题?
下面的代码进行了类型检查,
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);}
}
任何指针都会有所帮助。感谢
答案 0 :(得分:3)
您可以知道类
的声明字段 Class cls = Class.forName("MyClass");
Field fieldlist[] = cls.getDeclaredFields();
答案 1 :(得分:1)
如果您手动执行此操作,此类操作非常棘手且容易出错。您应该使用几乎每个主要框架包含的许多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 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)));
}
}
<强>输出:强>
{baz = class java.lang.String,foo = class java.lang.String}
巴兹:phleem
FOO:杆
答案 2 :(得分:1)
看看这个:BeanUtils
myUser.setName("Bob");
// can instead be written:
BeanUtils.setProperty(myUser, "name", "Bob");
// and then retrieve:
BeanUtils.getProperty(myUser, "name");
答案 3 :(得分:0)
这些字段通常是私有的。因此,要访问它们,您必须致电
field.setAccessible(true);
顺便说一句,你确定你真的希望在这种情况下使用反射吗?您是否考虑过声明界面?类(实现)仍然可以动态加载。
例如:NameAccessor
和AddressAccessor
是接口。
FirstClass
和SecondClass
是类。我们假设FirstClass
实现NameAccessor
和SecondClass
实现两个接口。
现在你可以说:
Class clazz = Class.forName("SecondClass");
Object obj = clazz.newInstance();
//......
String name = ((NameAccessor)obj).getName();
String address = ((AddressAccessor)obj).getAddress();
我认为(恕我直言)这个解决方案比使用反射访问私有字段更好。