我处于这样一种情况,我希望有一个映射,其中键是一个接口类,相应的值是一个实现该接口的类。换句话说,键和值类型是相关的。
我当前实现的方法添加到地图中,并获取实现类的实例,如下所示:
// should be something like Class<T>, Class<? extends T>
static Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>> ();
public static <T> void add(Class<T> interfaceT,
Class<? extends T> implementationT) {
map.put(interfaceT, implementationT);
}
public static <T> T get(Class<T> interfaceT) {
// cast caused by definition not complete.
Class<T> implementationT = (Class<T>) map.get(interfaceT);
// try catch stuff omitted
T t = implementationT.newInstance();
return t;
}
我的问题是:
可以我定义了“map”变量,因此不需要get(...)方法中的强制转换?我无法使“新HashMap<Class<T>, Class<? extends T>>
()”工作,所以要么是不可能的,要么我错过了一些基本的东西:)
请告知:)
编辑:事实证明Class上的asSubclass()方法做了我想要的:D
Class<?> rawClassFromMap = map.get(interfaceT);
Class<? extends T> implementationT = rawClassFromMap.asSubclass(interfaceT);
很好,implementationT的类型为“?extends T”,因为我只需要返回一个T对象。
我喜欢泛型。让我想起了Haskell ......
答案 0 :(得分:4)
看起来像Josh Bloch在Chapter 5 of Effective Java (item 29).中描述的类似“Typesafe Heterogenous Container”的东西在他的情况下,他将类型(Class<T>
)映射到(已经实例化的)实例(T
)。
您可以使用asSubclass
代替cast
来执行类似操作:
final class Factory
{
private Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
<T> void map(Class<T> type, Class<? extends T> impl)
{
map.put(type, impl.asSubclass(type));
}
private <T> Class<? extends T> get(Class<T> type)
{
Class<?> impl = map.get(type);
if (impl == null)
throw new IllegalArgumentException("Unknown type: " + type);
return impl.asSubclass(type);
}
<T> T create(Class<T> type)
throws Exception
{
Class<? extends T> impl = get(type);
Constructor<? extends T> ctor = impl.getConstructor();
return ctor.newInstance();
}
}
答案 1 :(得分:0)
我建议Proxy。这是Java example。
public interface Bike {
public String getWheels();
public int getSize();
}
public class MountainBike implements Bike {
@Override
public int getSize() {
return 24;
}
@Override
public String getWheels() {
return "Treaded";
}
@Override
public String toString() {
String newLine = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
sb.append("Type: MOUNTAIN").append(newLine);
sb.append("Wheels: ").append(getWheels()).append(newLine);
sb.append("Size: ").append(getSize()).append(newLine);
return sb.toString();
}
}
public class CruiserBike implements Bike {
@Override
public int getSize() {
return 26;
}
@Override
public String getWheels() {
return "Smooth";
}
@Override
public String toString() {
String newLine = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
sb.append("Type: CRUISER").append(newLine);
sb.append("Wheels: ").append(getWheels()).append(newLine);
sb.append("Size: ").append(getSize()).append(newLine);
return sb.toString();
}
}
public class BikeProxy implements InvocationHandler {
private Object obj;
public static Object newInstance(Object obj)
{
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
.getClassLoader(), obj.getClass().getInterfaces(),
new BikeProxy(obj));
}
public static <T> T newInstance(String className)
{
try
{
return (T) newInstance(Class.forName(className));
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
public static <T> T newInstance(Class<T> bikeClass)
{
try
{
return (T) java.lang.reflect.Proxy.newProxyInstance(Bike.class.getClassLoader(), new Class[]{Bike.class},
new BikeProxy(bikeClass.newInstance()));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
private BikeProxy(Object obj)
{
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object result;
try
{
result = m.invoke(obj, args);
}
catch (InvocationTargetException e)
{
throw e.getTargetException();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
return result;
}
}
public class ProxyTester
{
public static void main(String[] args)
{
Bike mountainBike = BikeProxy.newInstance(MountainBike.class);
System.out.println(mountainBike);
Bike mountainBike2 = BikeProxy.newInstance(MountainBike.class.getName());
System.out.println(mountainBike2);
Bike cruiserBike = BikeProxy.newInstance(CruiserBike.class);
System.out.println(cruiserBike);
Bike cruiserBike2 = BikeProxy.newInstance(CruiserBike.class.getName());
System.out.println(cruiserBike2);
}
}