2015-11-29 47 views
2

我想做一个简单的存储类,它将存储不同的类实例。我设法做的唯一几乎正确的方式是使用未经检查的类型转换。Java - 混合类型容器(非泛型类)可能没有未经检查的转换?

HashSet<T> result = (HashSet<T>) storage.get(s); 

是否可以不选中铸造和未做类通用(class Storage<T> { })做了什么?

import java.util.*; 
import org.junit.*; 

class Tests { 
    @Test 
    public static void main (String[] args) { 
     Storage storage = new Storage(); 

     HashSet<Child1> child1Set = storage.get("child1"); 
     HashSet<Child1> duplicateChild1Set = storage.get("child1"); 

     Assert.assertNotNull(child1Set); 
     Assert.assertSame(child1Set, duplicateChild1Set); 

     HashSet<Child2> child2Set = storage.get("child2"); 

     Assert.assertNotNull(child2Set); 
     Assert.assertNotSame(child1Set, child2Set); 
    } 
} 

class Storage { 

    public Map<String, HashSet<? extends Parent>> storage = new HashMap<>(); 

    public <T extends Parent> HashSet<T> get(String s) { 
     HashSet<T> result = (HashSet<T>) storage.get(s); 
     if (result == null) { 
      result = new HashSet<>(); 
      storage.put(s, result); 
     } 
     return result; 
    } 
} 

class Parent { } 

class Child1 extends Parent { } 

class Child2 extends Parent { } 
+0

这种未经检查的类型转换是安全的,您不应该担心它。你甚至可以压制 - “@SuppressWarnings(”unchecked“)'。不幸的是,这就是您创建Heterogenous类型安全容器的方式。 –

回答

2

可以使用Class对象作为键,而不是String做吧。这是一个简短的例子。为了简单起见,我没有包含extends Parent - 你可以把它们放回去。

public final class Storage { 

    private final Map<Class<?>, Set<?>> storage = new HashMap<>(); 

    public <T> Set<T> get(Class<T> s) { 
     Set<T> result = (Set<T>) storage.get(s); // Unchecked cast 
     if (result == null) { 
      result = new HashSet<>(); 
      storage.put(s, result); 
     } 
     return result; 
    } 
} 

这是不可能消除这样的混合类型的容器中的未经检查的强制转换。如果密钥的类型为Class<T>,则无法指定该值的类型为Set<T>。但是,只要Storage类的用户不忽略任何类型的安全警告,这是完全类型安全的。

例如,要使用该类,您可以执行storage.get(Double.class).add(4.2);

+0

downvote的任何理由? –

+0

你说:“这是不可能消除未检查的演员”这是一个错误的论据来回答问题 –

+0

@HeyStackExchange你已经错过了整个问题的关键。整个想法是'Storage'是一个混合型容器。该OP甚至明确表示“没有使类通用(类存储' –