Cloneable在Java中本质上是破碎的.具体来说,我对界面的最大问题是它需要一种不定义方法本身的方法行为.因此,如果遍历Cloneable列表,则必须使用反射来访问其定义的行为.但是,在Java 8中,我们现在有默认方法,现在我问为什么没有默认clone()方法Cloneable.
我理解为什么接口不能默认Object方法,但是,这是一个明确的设计决策,因此可以做出异常.
我有点想到弃用Object.clone()并将其内部代码更改为:
if(this instanceof Cloneable) {
return ((Cloneable) this).clone();
}
else {
throw new CloneNotSupportedException();
}
Run Code Online (Sandbox Code Playgroud)
并继续前进任何魔法使其clone()成为默认方法Cloneable.这并没有真正解决,clone()仍然可以很容易地错误地实现,但这本身就是另一个讨论.
据我所知,这种变化将完全向后兼容:
clone()但未实现的类Cloneable(为什么?!)在技术上仍然可以(即使在功能上不可能,但这与以前没有什么不同).clone()但实现的类Cloneable在其实现上仍将起相同的作用.clone(),但确实实现Cloneable(为什么?!)的类现在将遵循规范,即使它在功能上并不完全正确.Object.clone()仍然可以在功能上工作.super.clone()即使它正在引用,它在功能上仍然是相同的Object.clone().更不用说这将解决一个巨大的问题Cloneable.虽然繁琐且仍然容易错误地实现,但它将解决界面的巨大面向对象问题.
我能看到的唯一问题是那些实现Cloneable没有义务覆盖的问题clone(),但这与以前没有什么不同.
这已在内部进行过讨论,但从未取得成果吗?如果是这样,为什么?如果是因为接口不能默认使用Object方法,那么在这种情况下做出异常是否有意义,因为所有继承Cloneable的对象都是期待clone()的?
使用Guava's ClassPath我正在尝试初始化位于特定包中的类,但我想使用构造函数进行初始化,因为它不会传播异常.所以这就是我为获得构造函数而设计的:
ClassPath.from(classLoader).getTopLevelClasses("test.package").stream()
.map(ClassPath.ClassInfo::load)
.map(Class::getConstructors)
.map(Arrays::stream)
.map(constructorStream -> constructorStream
.filter(constructor -> constructor.getParameterCount() == 0)
.findAny()
.orElseThrow(RuntimeException::new)
);
Run Code Online (Sandbox Code Playgroud)
但是,这只是在简单地说明Cyclic接口时在InteliJ中给出错误.我想我知道Cyclic接口是什么,但我不确定为什么会导致这个错误.据我所知,只要返回类型是已知的(orElseThrow在这种情况下它具有返回值Constructor<?>),那么抛出未经检查的异常应该没问题.如果我使用orElse(null)那么错误消失了.这里发生了什么以及如何抛出我想抛出的RuntimeException?