java包装类(java.lang.Integer
,java.lang.Boolean
,...)没有公共超类型背后是否有特殊原因?
我问是因为(例如)沿着经典Object::getClass
WrapperType::getType
函数会非常方便,这将返回基元类型的类。
更具体地说,上下文通过反射调用构造函数,其中您只有Class<T>
和参数Object[]
例如:
public static <T> T createInstance(Class<T> clz, Object... params) throws Exception
为了获取构造函数,我可以通过以下方式获取参数类型:
Class<?>[] c = Arrays
.stream(params)
.map(Object::getClass)
.toArray(Class<?>[]::new);
return clz.getConstructor(c).newInstance(params);
但这当然会失败,像String::new(char[], int, int);
这样的构造函数
如果该超类型存在,我可以执行以下操作:
.map( o -> o.getClass().isPrimitive() ? ((WrapperType) o).getType() : o.getClass() )
我想开发人员没有实现它有一个特殊的原因java
。
Java 设计人员在决策中可能不太抽象,并且找不到数字类型之间的许多相似之处(例如Integer
) 和非数字类型(例如Boolean
) 按超类对它们进行分组。
虽然,所有数值类型都扩展Number
真正表示"可转换为基元类型的数值byte
、double
、float
、int
、long
、short
"。
实际上,所有包装类都有一个通用的接口Comparable<T>
(例如Comparable<Integer>
为Integer
)。
我可以看到这将是多么实用,但就抽象而言,这将是一个大混乱。假设你有包装器Integer和Double以及该家族中的其他包装器,它们确实有java.lang.Number作为他们的超级。然而,它们与布尔值之间没有语义关系(将c的影响分开)。
但是为了论证起见,让我们考虑一下它们都在一个大桶里并且是包装器,它们仍然是数字吗?
考虑到语言历史上对多重继承的厌恶,如果你要选择的话,拥有数字会有更多的场景。
在 SE 8 的语言功能发生重大革命性变化之后,我们现在能够通过接口进行多重继承,同时在这种情况下使用标准实现。如果进一步分析,他们将在逻辑推理中得出结论,这些案件需要合同而不是继承;因此,即使这样做了,这也是接口的工作。
考虑到实现这一点的可靠方法是相当新的,并且 Wrappers 将是一种过于通用的方式,我们可以看到最好不要拥有它。虽然现在有可能,但有历史和语义上的原因可以解释为什么它没有出现,至少作为一个超级类。抽象是这里的关键。但是没有什么能阻止你在管道中插入工厂,或实现提到的接口。
臀部线,关键因素有:
- 抽象:这更像是一个契约或 is-a 关系
- 历史:泛型和通过接口的多重继承
- 想象一下,如果我们愿意容纳,继承三的大小 情况如下:它首先是一个包装器,然后是一个数字或布尔值。