如何访问通用对象的类型?

时间:2014-02-25 00:25:03

标签: java generics reflection

查看下面的Crud对象代码,我期待的是类型为T的Field对象数组。我实际得到的是Object类型的Field对象的空数组。我的测试类叫做Timezone。所以,当我实例化Crud对象时,它看起来像......

Crud<Timezone> tz = new Crud<Timezone>();

但正如我所说,这不起作用。帮助赞赏。

import java.util.*;
import java.lang.reflect.*;
public class Crud<T> {

    public T getInstance()
    {
        @SuppressWarnings("unchecked")
        T object = (T) new Object();
        return object;
    }

    public ArrayList<String> getMembers() {
        ArrayList<String> retval = new ArrayList<String>();
        try {
            T object = this.getInstance();
            Field[] fields = object.getClass().getDeclaredFields(); //Always empty
            for (Field field : fields) {
                retval.add(field.getName());
            }
        } catch (Exception e) {
            System.out.println(e);
        }

        return retval;
    }

}

5 个答案:

答案 0 :(得分:2)

即使没有泛型,也不能做这样的事情:

Timezone object = (Timezone) new Object();

new Object()将创建一个运行时类型Object的对象。这将包含Object所有的所有字段和方法,但没有其他字段和方法。创建Object后,不能使用强制转换将对象神奇地转换为其他类型;这将涉及添加Timezone所具有的所有新字段和方法,而Java无法做到这一点。

所以这也不可行:

T object = (T) new Object();

不幸的是,Java也不允许你这样做:

T object = new T();

因为“类型擦除”。有关解决此问题的一些想法,请参阅Create instance of generic type in Java?(除非没有泛型的解决方案适合您)。

答案 1 :(得分:2)

不,由于type erasure,您无法在运行时访问该类型。

但是,有一种模式可以解决创建泛型类型实例的问题;您必须将类型标记传递给构造函数:

public class Crud<T> {
    private Class<T> clazz;
    public Crud(Class<T> clazz) {
        this.clazz = clazz;
    }

    public T getInstance() {
        return clazz.newInstance();
    }

答案 2 :(得分:1)

如果您想要包装实例并获取其字段,则无需使用泛型。您可以使用Object作为基类来允许包装器中的任何类型的对象。例如

public class Crud {

    private final Object object;

    public Crud(final Object someObject) {
        this.object = someObject;
    }

    public ArrayList<String> getMembers() {
        ArrayList<String> retval = new ArrayList<String>();
        try {
            Field[] fields = this.object.getClass().getDeclaredFields();
            for (Field field : fields) {
                retval.add(field.getName());
            }
        } catch (Exception e) {
            System.out.println(e);
        }

        return retval;
    }

}

然后你就做了

Crud tz = new Crud(new Timezone());

答案 3 :(得分:0)

您可能应该在Timezone类中专门为Timezone实现方法getDeclaredFields()

答案 4 :(得分:0)

我们可以像这样定义泛型类:

public class Crud<T> {

    private final Class<T> mClass;

    public Crud(Class<T> tClass)
    {
        mClass = tClass;
    }

    public T getInstance() throws Exception
    {
        T object = mClass.newInstance();
        return object;
    }

    ...
}

然后我们可以像这样使用它:

try
{
    Date tDate = new Crud<Date>(Date.class).getInstance();
    System.out.println("Date: " + tDate);
}
catch(Exception e)
{
    System.out.println("Error: " + e);
}

输出:Date: Mon Feb 24 21:00:04 PST 2014