gpt4 book ai didi

java - 如果构造函数的签名包含泛型类型的定义,那么该构造函数的用户需要承担哪些额外责任?

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:05:16 25 4
gpt4 key购买 nike

我扩展了一个在几个类中使用泛型的现有项目。

我正在研究一个名为 PhiFunction 的类,该类有一个接受多个参数的构造函数。其中包括两个我想强制为相同类型 E 的参数。这些参数仅在构造函数中使用,它们不存储为类字段。

我不想将此类型添加到类签名中(我希望使类定义尽可能简单)。类签名目前只包含类型 T。为了使类签名尽可能简单,我将此类型的定义添加到构造函数签名中,如下所示:

简化旧代码:

public class PhiFunction<T> {

...

public PhiFunction(
final MathematicalGroup<?> group, final List<?> baseElements, ...) {

简化的新代码:

public class PhiFunction<T> {

...

public <E extends GroupElement<T>> PhiFunction(
final MathematicalGroup<E> group, final List<E> baseElements, ...) {

代码编译良好,运行良好。

现在让我感到惊讶和困惑的是,仍然可以像以前一样创建 PhiFunction 的实例。换句话说,在构造函数签名中添加此类型定义不会改变构造函数的使用方式(假设用户确实提供了使用相同类型的参数)。用户仍然可以像以前一样创建 PhiFunction 的实例,而无需关心此类型定义是否已添加到构造函数中。我预计此构造函数的用户必须将 E 定义为某个特定类,但他们没有。

我以前没有以这种方式使用泛型。似乎向构造函数(或我猜的任何方法)添加类型定义只允许定义类型,而无需让构造函数的用户负责定义该类型。

我想我的问题是,如果构造函数的签名包含泛型类型的规范,那么构造函数的用户需要承担哪些额外责任?

我还有一个相关问题。是否应该将该类型 E 作为参数添加到 Java 文档中?如何?我确信它应该被记录下来,因为构造函数的两个参数必须是那种类型,但我不确定应该如何将它添加到 Javadocs。

最佳答案

您不需要为调用泛型方法或构造函数做任何额外的工作。大多数时候,compiler will be able to infer the type argument ,基于您传递给方法的参数,或来自返回类型(虽然此处不适用)。

因此,当您像这样创建该类的实例时:

MathematicalGroup<Sometype> mathematicalGroup;
List<Sometype> list;
PhiFunction<Double> phiFunction = new PhiFunction<>(mathematicalGroup, list);

...类型参数 E的构造函数将自动推断为 Sometype .

但是,如果您传递不符合类型参数规则的参数,您将看到编译器错误,如本例所示:

MathematicalGroup<Sometype> mathematicalGroup;
List<SomeOthertype> list;
// This will give a compiler error.
PhiFunction<Double> phiFunction = new PhiFunction<>(mathematicalGroup, list);

如果有时类型推断没有按预期工作,您还可以选择提供显式类型参数:

// Redundant usage of explicit type argument
PhiFunction<Double> phiFunction =
new <Sometype>PhiFunction<Double>(mathematicalGroup, list);

虽然上述显式类型参数的使用是多余的,但在某些情况下编译器不会推断出您期望的类型。当您将不一致的参数传递给具有相同类型参数的参数时,就会出现这种情况。例如考虑以下方法:

public static <T> void fill( T [] array, T elem) {
for (int i=0; i<array.length; ++i) { array[i] = elem; }
}

.. 如果您尝试调用该方法:

fill(new String [5], new String ("XYZ")); // This is fine
fill(new String [5], new Integer (100)); // This is also fine? How?

理想情况下,您会期望第二个方法调用失败,因为 StringInteger不应替代相同类型的参数 T .但这就是惊喜。编译器将类型参数推断为您传递的参数的所有父类(super class)型的交集。所以,类型 T推断为:

T:=Object&Serializable&Comparable 

在这种情况下,您可能需要提供 <Object>作为显式类型参数:

YourClass.<Object>fill(new String[5], new Integer(100));

P.S:你知道吗 you can invoke non-generic methods in generic way?好吧,泛型充满了惊喜:)

至于 Javadoc,不,你不需要提供任何关于 E 的信息代表。解释一下参数group是什么和 list方法。就是这样。无论如何,类型参数和形式参数都是方法签名的一部分,并且已经存在了。考虑例如 Arrays.binarySearch() 方法。

关于java - 如果构造函数的签名包含泛型类型的定义,那么该构造函数的用户需要承担哪些额外责任?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22688286/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com