Java中的复杂泛型
我有一个超类型定义为:Java中的复杂泛型,java,generics,Java,Generics,我有一个超类型定义为: public abstract class AType<T> { .... private T value; private T mask; public T getValue() { if (isMasking()) return null; return this.value; } public void setValue(T value
public abstract class AType<T> {
....
private T value;
private T mask;
public T getValue() {
if (isMasking())
return null;
return this.value;
}
public void setValue(T value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = value;
}
protected T getMask() {
if (!isMasking())
return null;
return this.mask;
}
protected void setMask(T mask) {
if (mask == null)
throw new IllegalArgumentException("Mask is mandatory.");
this.setMasking(true);
this.mask = mask;
}
...
}
一切都正常,但此模块的用户不希望每次都在enum中查找并手动强制转换。这可能会出错,并花费大量时间进行调试:/
我的问题是我如何重构它,或者我如何定义继承结构以允许用户动态转换?可能吗
编辑:
我正在解析来自网络的数据包。有很多类型在供应商类型标识符和值/掩码类型上有所不同-这些字段对于每个组合都是常量,所以我将其定义为枚举常量。F.e.20仅具有不同的TypeID,但具有相同的VendorID,并且它们都可以表示为整数,接下来的10具有不同的VendorID和TypeID,但它们都可以表示为Short,以此类推 可能使用如下设置值方法:
public enum Type {
SOME_TYPE(new TypeID(0, (short) 0), OFMU16.class,
new Instantiable<AType<?>>() {
@Override
public SpecType instantiate() {
return new SpecType(new OFMatchTypeIdentifier(0, (short) 0));
}
}),...;
...
public Class<? extends AType<?>> toClass() {
return this.clazz;
}
...
}
public void setValue(Object value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = (T)value;
}
虽然你将有一个未经检查的演员阵容
希望这能有所帮助现在还不清楚你为什么要选演员。只要
SOME_TYPE
被写入源代码或中,setsetValue
方法的类型就被硬编码(在您的示例中是int
或Integer
),您不需要运行时检查-您需要编译时检查
因此,我认为以下代码片段是API用户应该如何编写代码的:
public class TypeTest {
public static void main(String[] args) {
AType<Integer> type0 = Types.SOME_TYPE_0.instantiate();
type0.setValue(10);
AType<String> type1 = Types.SOME_TYPE_1.instantiate();
type1.setValue("foo");
}
}
清理:您的用户必须查看界面:是的,他在任何情况下都必须查看,因为他必须知道哪个类型适合setValue
1。没有任何解决办法可以绕过这一点。尽管Eclipse可能会对您和您的用户有所帮助:在main
中,只需键入Types.SOME_type_1.instantiate()代码>然后转到行的开头,点击Ctrl2+L(“分配给loccal变量”),Eclipse将为您替换AType instantiate=
部分
1如果您的用户不知道setValue
方法的正确类型,则您提出的问题是错误的。在这种情况下,您应该询问类似“如何设计通用安全转换设施?”的问题。我不明白,如果您可以这样做,为什么您要强制转换:AType type=SOME_type.newInstance();类型。设置值(10)你真的需要那个复杂的代码吗?尽量保持简单。使用接口而不是动态强制转换如何?您实际上想解决什么问题?…AType。setValue(T值)
已参数化。这是不可用的:-/user仍然必须在枚举中查看它是什么类型,而不是超过适当的值。它可以很容易地抛出运行时异常:-/。静态强制转换可能是最好的解决方案,因为它是在编译时选择的。虽然它不是用户友好的。
((SpecType) type).setValue(10);
public void setValue(Object value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = (T)value;
}
public class TypeTest {
public static void main(String[] args) {
AType<Integer> type0 = Types.SOME_TYPE_0.instantiate();
type0.setValue(10);
AType<String> type1 = Types.SOME_TYPE_1.instantiate();
type1.setValue("foo");
}
}
abstract class AType<T> {
private T value;
// standard getter/setter
public T getValue() { return this.value; }
public void setValue(T value) { this.value = value; }
}
class SpecTypeInt extends AType<Integer> {
}
class SpecTypeString extends AType<String> {
}
interface Instantiable<T> {
T instantiate();
}
interface Types {
Instantiable<? extends AType<Integer>> SOME_TYPE_0 = new Instantiable<SpecTypeInt>() {
@Override
public SpecTypeInt instantiate() {
return new SpecTypeInt();
}
};
Instantiable<? extends AType<String>> SOME_TYPE_1 = new Instantiable<SpecTypeString>() {
@Override
public SpecTypeString instantiate() {
return new SpecTypeString();
}
} ;
}