使用java

时间:2016-10-17 15:25:31

标签: java

我有一个类型为

的类
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对象作为参数传递给我扫描。

3 个答案:

答案 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()就是传入的对象。