Java 动态分派、重载和泛型
使用此类:Java 动态分派、重载和泛型,java,generics,dispatch,Java,Generics,Dispatch,使用此类: public class Fallible<T> { private final Exception exception; private final T value; public Fallible(final T value) { this.value = value; this.exception = null; } public Fallible(final Exception exce
public class Fallible<T> {
private final Exception exception;
private final T value;
public Fallible(final T value) {
this.value = value;
this.exception = null;
}
public Fallible(final Exception exception) {
this.value = null;
this.exception = exception;
}
}
公共类易出错{
私人最终例外;
私人最终T值;
公众易犯错误(最终T值){
这个值=值;
this.exception=null;
}
公共易出错(最终例外){
this.value=null;
this.exception=异常;
}
}
我可以安全地假设
value
将从不包含异常对象吗 不,你不能做出这样的假设。例如:
Object obj = new Exception();
Fallible f = new Fallible(obj);
将调用泛型构造函数
检查这一点的唯一方法是使用instanceof
显式检查值的类型:
public Fallible(final T value) {
if (value instanceof Exception) {
this.exception = (Exception) value;
this.value = null;
} else {
this.value = value;
this.exception = null;
}
}
不,你不能
如果您考虑运行时得到的类型的擦除版本:
,这将更容易分析。
public Fallible(最终T值)
变为public Fallible(最终java.lang.Object值)
因此,如果重载Fallible(最终异常)
更匹配,则将使用它;i、 e.如果异常
属于异常
类型或其子类
在java中,构建一个允许从java.lang.Object
构造但禁止从子类构造(在编译时)的类是不可能的。您必须依赖于运行时检查(instanceof
&c)。顺便说一下,你可以用C++在C++中解决这个问题。在这一点以及其他许多方面,java被认为是C++的进化,是一个向前迈进一步又回到两步的例子。注意到,在这个例子中,将异常扩展到Obj/<代码>等同于信息的丢失,也有相反的可能:<代码>新的错误(新的运行时异常)()。
现在还将调用泛型构造函数,因为它比显式构造函数更具体。也许这是故意的。正确的解决方案是删除重载的public
构造函数,并使用具有不同名称的工厂方法,例如value(T)
和异常(Exception)
允许调用者记录意图并消除对实例的需要。这些工厂方法不添加任何假设,即“value
永远不会包含异常对象”:您仍然可以调用Fallible.value(new Exception())
或Fallible.value(obj)
。如果该类需要作出规定的假设,则有必要进行instanceof
检查,作为防御措施。如果它是一个公共类,你就不能相信它的用户会做正确的事情来设置它的不变量。@Holger实际上,我希望value(t)
和exceptive(Exception)
都是Fallible
@cuichtlauac类型,然后你可以调用Fallible.Exception(…)
@cuihtlauac:这并不矛盾。在异常情况下,T
可以是调用者想要的任何内容,因为没有实际值:publicstaticfallibleexcellective(异常e){…}
。与返回一个可选值的
进行比较。