Java Auto Cast一个对象

时间:2016-05-21 19:11:49

标签: java casting

我想知道是否有办法通过将Class类型与对象一起存储来自动将对象转换为某种类型?我认为这可能是Java,但也许不是。

例如:

class StorageItem
{
    private int itemcount;

    StorageItem(int itemcount)
    {
        this.itemcount = itemcount;
    }

    int getItemCount()
    {
        return itemcount;
    }
}

class Storage
{
    private Class clazz;

    private Object value;

    public Storage(Class clazz, Object value)
    {
        this.clazz = clazz;
        this.value = value;
    }

    //Is there a way such a call can be created to automatically cast 
    //the object to the class type and return that cast type in a 
    //generic way. The idea being that Storage knows what it should
    //already be cast to. Is this possible?
    public T getValue()
    {
        return clazz.cast(value);
    }
}

用法示例:

public static void main(String[] args)
{
    //Create storage item
    Storage storage = new Storage(StorageItem.class, new StorageItem(1234));

    //The call to getValue() will automatically cast to the Class passed
    //into Storage.
    int itemcount = storage.getValue().getItemCount(); //returns 1234
}

显然,Storage中的getValue()调用是伪代码调用,但它只是提供了我想做什么的想法。

无论如何都有一个getValue()调用,它会自动转换为存储在Storage类中的Class类型。同样,这个想法是Storage类知道它应该被强制转换为什么。或者,无论如何这可以完成吗?

StorageItem只是一个简单的例子。在这里,它只是存储一个int用于讨论目的。但是,它可能会更复杂。

另一个用法示例是将存储对象存储在列表中。

List<Storage> row = new ArrayList<Storage>();
row.add(new Storage(StorageItem.class, 1234));
row.add(new Storage(String.class, "Jason"));
row.add(new Storage(Integer.class, 30));
row.add(new Storage(Double.class, 12.7));

然后,可以通过以下方式访问这些内容。

//calls StorageItem's getItemCount() method
row.get(0).getValue().getItemCount(); //returns 1234

//calls String's length() method
row.get(1).getValue().length(); //returns 5

//calls Integer's intValue() method
row.get(2).getValue().intValue(); 

//calls Integer's doubleValue() method
row.get(3).getValue().doubleValue(); 

如果getValue()只返回一个Object,我必须总是手动转换为特定的Object。相反,如果我可以将转换类存储在Storage对象中,那么Storage有足够的信息来知道在getValue()调用中自动将Object转换为什么。

如果在Java中这是可行的,那就是我正在寻求的问题的答案。如果是这样,怎么样?

2 个答案:

答案 0 :(得分:6)

这可以解决这个问题吗?需要更少的黑客攻击:

class Storage<T> {

    private T value;

    public Storage(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

答案 1 :(得分:1)

我真的没有看到你在这里试图解决的问题。 @ bali182的答案确实为您提供了存储引用的“通用”方法 - 但存储引用本身更容易。

考虑如果将包含不同类型引用的两个Storage实例放入集合中会发生什么:

List<Storage<SOMETHING>> storages = new ArrayList<>();
storages.add(new Storage<String>("Hello"));
storages.add(new Storage<Integer>(1));

那么:SOMETHING是什么?好吧,它必须是?,因为这是唯一满足两个元素的类型。

现在,当您遍历列表以检索它们时,您必须将它们作为Object处理:

for (Storage<?> storage : storages) {
  Object object = storage.getValue();
  // ...
}

因为您通常不知道任何给定元素的存储引用的类型。对于上面的列表,object的具体类型将是元素的具体类型 - StringInteger - 但是如果不使用某些方法,则无法使用这些不同的类型检测该类型(例如if (object instanceof String))。

如果引用直接存储在列表中,那会更容易:

List<Object> objects = new ArrayList<>();
storages.add("Hello");
storages.add(1;
for (Object object : objects) {
  // ...
}

你仍然需要做一些事情来检测对象的具体类型;你只是在没有额外的间接层的情况下这样做。

虽然上面的示例适用于不相关的类型,但如果它们是相同的类型,使用直接引用仍然更容易:

List<String> objects = Arrays.asList("Hello", "World");
for (String object : objects) {
  // ...
}

现在你不需要做任何事情来了解具体类型(如果元素属于非final类,你想可能,并且你想特别处理一些子类),但是您仍然需要取消引用Storage.getValue()以获得您可以直接获得的值。