Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Eclipse中列出Java类及其祖先公开的所有属性?_Java_Eclipse_Reflection_Recursion_Eclipse Plugin - Fatal编程技术网

如何在Eclipse中列出Java类及其祖先公开的所有属性?

如何在Eclipse中列出Java类及其祖先公开的所有属性?,java,eclipse,reflection,recursion,eclipse-plugin,Java,Eclipse,Reflection,Recursion,Eclipse Plugin,给定一个Java类,我希望能够列出所有祖先中公开的所有属性,并以相同的方式递归遍历它们公开的所有属性(即public或使用getter/setter) 用一个简单的例子更容易解释: public class BaseClass1 { private int intProperty; // has getter and setter (not shown) } public class SubClass1 extends BaseClass1 { private int priva

给定一个Java类,我希望能够列出所有祖先中公开的所有属性,并以相同的方式递归遍历它们公开的所有属性(即
public
或使用getter/setter)

用一个简单的例子更容易解释:

public class BaseClass1 {
    private int intProperty; // has getter and setter (not shown)
}
public class SubClass1 extends BaseClass1 {
    private int privateSoNotListed;
    public SubClass2 subClass2Property;
}
public class BaseClass2 {
    public String stringProperty;
}
public class SubClass2 extends BaseClass2 {
    private long longProperty; // has getter and setter (not shown)
}
给定上面的
子类1
作为输入,输出如下:

intProperty-int[来自BaseClass1]
子类2Property.stringProperty-字符串[来自BaseClass2]
子类2Property.longProperty-long[来自子类2]
应该可以使用一些巧妙的反射来编写这样的东西,但我不想重新发明轮子——有没有一个现有的工具可以做到这一点(可能是Eclipse插件?)

编辑:Eclipse的类型层次结构在显示单个类的属性方面做得很好-在我看来,理想的解决方案是,如果这是一个树状视图(类似于Package Explorer),能够扩展本身就是类的属性。

看一看。它们有实用程序类,允许您列出属性(以及其他内容),特别是

请注意,它们对“属性”的定义是可以通过getter/setter方法访问/编辑的。如果要列出字段,则需要执行其他操作

另请参见重复项,它也可以递归工作。以下是我们正在使用的自定义版本(日志记录在log4j记录器中):

导入java.beans.BeanInfo;
导入java.beans.IntrospectionException;
导入java.beans.Introspector;
导入java.beans.PropertyDescriptor;
导入java.lang.reflect.Field;
导入java.lang.reflect.Method;
导入java.util.array;
导入java.util.Collection;
导入java.util.Collections;
导入java.util.HashMap;
导入java.util.HashSet;
导入java.util.Map;
导入java.util.Set;
导入java.util.TreeMap;
导入org.apache.commons.beanutils.BeanUtilsBean;
导入org.apache.commons.beanutils.ConvertUtilsBean;
导入org.apache.log4j.Logger;
/*
*见原始版本:https://stackoverflow.com/questions/6133660/recursive-beanutils-describe
*/
公课督学{
公共静态void递归描述BeandLog(对象ob、记录器日志){
log.info(ob.getClass());
试一试{
地图道具=递归描述(ob);
对于(Map.Entry p:props.entrySet()){
log.info(“->”+p.getKey()+“=”+p.getValue());
}
}捕获(可丢弃的e){
log.error(e.getMessage(),e);
}
}
公共静态映射递归描述(对象){
Set cache=new HashSet();
返回递归描述(对象、null、缓存);
}
私有静态映射递归描述(对象、字符串前缀、设置缓存){
if(object==null | | cache.contains(object))返回Collections.EMPTY_映射;
cache.add(对象);
前缀=(前缀!=null)?前缀+“:”;
Map beanMap=newtreemap();
映射属性=getProperties(对象);
for(字符串属性:properties.keySet()){
对象值=properties.get(属性);
试一试{
如果(值==null){
//忽略空值
}else if(Collection.class.isAssignableFrom(value.getClass())){
putAll(convertAll((集合)值,前缀+属性,缓存));
}else if(value.getClass().isArray()){
beanMap.putAll(convertAll(Arrays.asList((Object[])值)、前缀+属性、缓存);
}else if(Map.class.isAssignableFrom(value.getClass())){
putAll(convertMap((Map)值,前缀+属性,缓存));
}否则{
putAll(convertObject(值、前缀+属性、缓存));
}
}捕获(例外e){
e、 printStackTrace();
}
}
返回beanMap;
}
私有静态映射getProperties(对象){
Map propertyMap=getFields(对象);
//在任何名称冲突的情况下,getter优先
propertyMap.putAll(getGetterMethods(object));
返回属性映射;
}
私有静态映射getGetterMethods(对象){
映射结果=新的HashMap();
BeanInfo信息;
试一试{
info=Introspector.getBeanInfo(object.getClass());
对于(PropertyDescriptor pd:info.getPropertyDescriptors()){
方法reader=pd.getReadMethod();
if(读卡器!=null){
String name=pd.getName();
如果(!“类”。等于(名称)){
试一试{
对象值=reader.invoke(对象);
结果.put(名称、值);
}捕获(例外e){
//你可以选择在这里做点什么
}
}
}
}
}捕获(内省异常e){
//你可以选择在这里做点什么
}最后{
返回结果;
}
}
私有静态映射getFields(对象){
返回getFields(object,object.getClass());
}
私有静态映射getFields(对象对象,类类型){
映射结果=新的HashMap();
Class superClass=classType.getSuperclass();
if(superClass!=null)result.putAll(getFields(object,superClass));
//仅获取公共字段
Field[]fields=classType.getFields();
用于(字段:字段){
试一试{
put(field.getName(),field.get(object));
}捕获(非法访问例外e){
//你可以选择在这里做点什么
}
}
返回结果;
}
普里夫
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.log4j.Logger;

/*
 * See the original version: https://stackoverflow.com/questions/6133660/recursive-beanutils-describe
 */
public class Inspector  {

    public static void recursivelyDescribeAndLog(Object ob, Logger log){
        log.info(ob.getClass());
        try {
            Map<String, String> props = recursiveDescribe(ob);
            for (Map.Entry<String, String> p : props.entrySet()) {
                log.info(" -> " + p.getKey() + "="+p.getValue());
            }

        } catch (Throwable e) {
            log.error(e.getMessage(), e);
        }
    }

    public static Map<String, String> recursiveDescribe(Object object) {
        Set cache = new HashSet();
        return recursiveDescribe(object, null, cache);
    }

    private static Map<String, String> recursiveDescribe(Object object, String prefix, Set cache) {
        if (object == null || cache.contains(object)) return Collections.EMPTY_MAP;
        cache.add(object);
        prefix = (prefix != null) ? prefix + "." : "";

        Map<String, String> beanMap = new TreeMap<String, String>();

        Map<String, Object> properties = getProperties(object);
        for (String property : properties.keySet()) {
            Object value = properties.get(property);
            try {
                if (value == null) {
                    //ignore nulls
                } else if (Collection.class.isAssignableFrom(value.getClass())) {
                    beanMap.putAll(convertAll((Collection) value, prefix + property, cache));
                } else if (value.getClass().isArray()) {
                    beanMap.putAll(convertAll(Arrays.asList((Object[]) value), prefix + property, cache));
                } else if (Map.class.isAssignableFrom(value.getClass())) {
                    beanMap.putAll(convertMap((Map) value, prefix + property, cache));
                } else {
                    beanMap.putAll(convertObject(value, prefix + property, cache));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return beanMap;
    }

    private static Map<String, Object> getProperties(Object object) {
        Map<String, Object> propertyMap = getFields(object);
        //getters take precedence in case of any name collisions
        propertyMap.putAll(getGetterMethods(object));
        return propertyMap;
    }

    private static Map<String, Object> getGetterMethods(Object object) {
        Map<String, Object> result = new HashMap<String, Object>();
        BeanInfo info;
        try {
            info = Introspector.getBeanInfo(object.getClass());
            for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
                Method reader = pd.getReadMethod();
                if (reader != null) {
                    String name = pd.getName();
                    if (!"class".equals(name)) {
                        try {
                            Object value = reader.invoke(object);
                            result.put(name, value);
                        } catch (Exception e) {
                            //you can choose to do something here
                        }
                    }
                }
            }
        } catch (IntrospectionException e) {
            //you can choose to do something here
        } finally {
            return result;
        }

    }

    private static Map<String, Object> getFields(Object object) {
        return getFields(object, object.getClass());
    }

    private static Map<String, Object> getFields(Object object, Class<?> classType) {
        Map<String, Object> result = new HashMap<String, Object>();

        Class superClass = classType.getSuperclass();
        if (superClass != null) result.putAll(getFields(object, superClass));

        //get public fields only
        Field[] fields = classType.getFields();
        for (Field field : fields) {
            try {
                result.put(field.getName(), field.get(object));
            } catch (IllegalAccessException e) {
                //you can choose to do something here
            }
        }
        return result;
    }

    private static Map<String, String> convertAll(Collection<Object> values, String key, Set cache) {
        Map<String, String> valuesMap = new HashMap<String, String>();
        Object[] valArray = values.toArray();
        for (int i = 0; i < valArray.length; i++) {
            Object value = valArray[i];
            if (value != null) valuesMap.putAll(convertObject(value, key + "[" + i + "]", cache));
        }
        return valuesMap;
    }

    private static Map<String, String> convertMap(Map<Object, Object> values, String key, Set cache) {
        Map<String, String> valuesMap = new HashMap<String, String>();
        for (Object thisKey : values.keySet()) {
            Object value = values.get(thisKey);
            if (value != null) valuesMap.putAll(convertObject(value, key + "[" + thisKey + "]", cache));
        }
        return valuesMap;
    }

    private static ConvertUtilsBean converter = BeanUtilsBean.getInstance().getConvertUtils();

    private static Map<String, String> convertObject(Object value, String key, Set cache) {
        //if this type has a registered converted, then get the string and return
        if (converter.lookup(value.getClass()) != null) {
            String stringValue = converter.convert(value);
            Map<String, String> valueMap = new HashMap<String, String>();
            valueMap.put(key, stringValue);
            return valueMap;
        } else {
            //otherwise, treat it as a nested bean that needs to be described itself
            return recursiveDescribe(value, key, cache);
        }
    }
}