我有一个类型为
的类public class Scan<T extends Data>{
...
}
Data
是一种抽象类型,我从中有一些实现。
现在我想要某种选择器,使用哪种实现。这可能吗?如果是,变量必须具有哪种类型(我尝试使用Class
,但这不起作用)
Class datatype;
switch(datatypeInt){
case 2:
datatype = Simple3DData.class;
break;
case 1:
default:
datatype = Simple2DData.class;
}
Scan<datatype> scan = new Scan<>();
(显然这不起作用)
我无法在交换机块中实例化Scan,因为我还会动态选择Scan类。
修改
我知道,这不容易,我会尝试转换代码,而不是使用类型,而是将所有T
替换为Data
并将Class
对象作为参数传递给我扫描。
答案 0 :(得分:1)
您无法以编程方式从Class<? extends Data>
对象(或者在您的情况下,从原始Class
对象中)选择参数化类型。
您可以在instanceof
引用的对象上使用Data
来检查其具体类型,并相应地初始化您的Scan
。
但是,这可能会首先玷污使用有界类型参数的概念,因为您希望Scan
实例使用可从Data
分配的所有类型参数。
因此,根据Scan
课程的使用情况,您可以使用Scan<Data>
或Scan<? extends Data>
(使用通配符的上限)或Scan<? super Data>
(带通配符的下限)引用。
以下是一个例子:
class Scan<T extends Data> {
// this method takes an instance of the Scan's type parameter
void doSomething(T t){}
// this method returns some object assignable from Data given some logic
T returnSomething() {
// just for test - note that you can't instantiate a generic type
return null;
}
}
abstract class Data {}
class Simple3DData extends Data {}
class Simple2DData extends Data {}
// somewhere in some method/initializer...
{
Scan<Data> scan = new Scan<>();
// works with both, as both are Data
scan.doSomething(new Simple3DData());
scan.doSomething(new Simple2DData());
// generalized to Data, instance type depends on logic in Scan class
Data someData = scan.returnSomething();
}
答案 1 :(得分:1)
您尝试实现的功能无法正常工作,因为类型参数仅在编译时由编译器使用,以确保您的代码符合定义的类型,以避免在运行时获得类型ClassCastException
的异常。
在运行时,由于type erasure
,类型参数甚至不再存在,因此您的代码将是这样的:
Class datatype;
switch(datatypeInt){
case 2:
datatype = Simple3DData.class;
break;
case 1:
default:
datatype = Simple2DData.class;
}
Scan = new Scan();
这意味着您需要明确指定类,因此您的代码可能是这样的:
Class<? extends Data> datatype;
switch(datatypeInt){
case 2:
datatype = Simple3DData.class;
break;
case 1:
default:
datatype = Simple2DData.class;
}
Scan scan = new Scan(datatype);
更多OO方法可能是实现strategy pattern,每种类型的数据可以有一个扫描策略,代码将是:
ScanStrategy strategy;
switch(datatypeInt){
case 2:
strategy = new Simple3DDataScanner();
break;
case 1:
default:
strategy = new Simple2DDataScanner();
}
Scan scan = new Scan(strategy);
答案 2 :(得分:0)
当你知道自己在做什么时,你总是可以这样做:
sys.partitions
含义:您可以使用 reflection 来实例化对象,并使用 hard cast 来“强制”使用正确的类型(当然,您需要处理可能发生的各种异常)。
另一方面,foo()做什么来返回你感兴趣的一个Class对象当然不是那么容易。一种解决方案是将真正的 Class对象传递给Scan的构造函数;然后 foo()就是传入的对象。