【问题标题】:Java Auto Cast an ObjectJava 自动转换对象
【发布时间】:2016-09-18 22:04:26
【问题描述】:

我想知道是否有一种方法可以通过将 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 类中的类。同样,这个想法是 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() 只返回一个对象,我将不得不手动强制转换为特定对象。相反,如果我可以将转换类存储在 Storage 对象中,那么 Storage 就有足够的信息来知道在 getValue() 调用上自动将 Object 转换为什么。

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

【问题讨论】:

  • 为什么不使用简单的泛型类?
  • 为什么是Storage storage = new Storage(StorageItem.class, new StorageItem(1234)); 而不是StorageItem storageItem = new StorageItem(1234);
  • class Storage { ...private Object value 分别更改为class Storage&lt;T&gt; { ...private T value; 一切就绪。
  • 如果可以自动为我完成,我想避免直接转换 Object 类型。由于 Storage 也知道它应该自己转换哪个类,所以我不确定是否可以将一个方法写入 Auto Cast 到传递给 Storage 对象的 Class。请在上面查看我最近的更新。
  • 您在这里要求做的事情无法完成:编译器无法知道row.get(0) 是“StorageItem-bearing”Storage 的一个实例,而不是“String-bearing”Storage

标签: java casting


【解决方案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) {
  // ...
}

现在你不需要做任何事情来知道具体类型(你可能,如果元素属于非最终类,并且你想专门处理一些子类),但是您仍然避免需要取消引用 Storage.getValue() 来获得您可以直接拥有的值。

【讨论】:

  • “因为您通常不知道任何给定元素的存储引用的类型。对象的具体类型将是元素的具体类型”。确切地说,除非 Storage 知道将其转换为什么具体类型。你可以看到我传入了Concrete类型。因此,Storage 现在知道可以将其转换为的东西。查看我最近发布的更新。我可能试图做的事情可能是不可能的。但是,这就是我问的原因,因为我不知道是否有办法。 =)
  • @JasonF 编译器 不知道存储对象的类型,但存储对象知道自己的类型,您可以使用getClass() 检索它。请记住,强制转换不会创建一个新对象——它只是对编译器说“你认为这是一个Object,但相信我,我知道它是一个String”。换句话说,object == (String) objecttrue,假设object.getClass() == String.class
  • @AndyT,顺便说一句,感谢您对此的投入。对,强制转换不会创建新对象。 getItemCount() 可调用的唯一方法是对象被理解为 StorageItem 类型。你可以看到我是如何使用上面的 getValue 调用的。如果 getValue 可以自动转换为 StorageItem,则 getItemCount() 将是可调用的。在 Java 中我不知道如何做到这一点或如果可以做到这一点。如果它可以以某种方式完成,那么怎么做?如果不是,那为什么?
  • “如果不是,那为什么?”因为这就是 Java 类型系统的工作方式。
  • 好的,所以您是说存储中的 getValue() 无法写入自动将对象转换为存储正在存储的类类型。如果做不到,那就做不到。这就是我问的原因 =)
【解决方案2】:

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

class Storage<T> {

    private T value;

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

    public T getValue() {
        return value;
    }
}

【讨论】:

  • 不仅需要更少的黑客攻击,它还适用于不存在非原始类实例的泛型类型,例如List&lt;String&gt;
猜你喜欢
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 2019-10-13
相关资源
最近更新 更多