【问题标题】:Accessing Methods and functions of a object whose class type is dynamically known访问类类型动态已知的对象的方法和函数
【发布时间】:2011-04-30 01:52:16
【问题描述】:

我有一个 A 类型的对象 A1。我动态地发现,该对象 A1 属于 A 类型。我现在有一个属性说“名称”,我想从 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);}
  }

任何指针都会有很大帮助。谢谢

【问题讨论】:

    标签: java dynamic classloader


    【解决方案1】:

    可以知道类的声明字段

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

    【讨论】:

    • :哦!爪哇真棒!!让我浏览整个页面以获得更多说明。谢谢。
    • @bsoundra 如果您发现这正是您的答案,您也可以将其标记为答案和/或投票。并开始为您的其余问题做它
    【解决方案2】:

    如果您手动执行,这种事情会很棘手且容易出错。您应该使用几乎每个主要框架都包含的众多 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}
    baz:phleem
    富:酒吧

    【讨论】:

      【解决方案3】:

      看看这个:BeanUtils

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

      【讨论】:

        【解决方案4】:

        这些字段通常是私有的。因此,要访问它们,您必须调用

        field.setAccessible(true);
        

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

        例如:NameAccessorAddressAccessor 是接口。

        FirstClassSecondClass 是类。假设FirstClass 实现了NameAccessorSecondClass 实现了这两个接口。

        现在你可以说:

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

        我认为(恕我直言)这个解决方案比使用反射访问私有字段更好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-10
          相关资源
          最近更新 更多