gpt4 book ai didi

java - 在 Java Generics 中输入泛型类型而不是它自己的类型

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:49:56 25 4
gpt4 key购买 nike

我需要输入方法签名,以便它接受 2 个相同类型的不同具体子类型的参数。

是否可以用泛型编写这样的代码?你会怎么解决? (案例绝对是一个例子)

public <T extends List<?>> T<String> sum(T<Integer> sublistOfInts, T<Boolean> sublistOfBooleans){
/*fusion both lists*/
return sublistOfStrings;
}

编辑:最后,我正在寻找的是编译器通过的一种方式:

ArrayList<String> myList = sum(new ArrayList<Integer>(), new ArrayList<Boolean>());

但不是:

ArrayList<String> myList = sum(new ArrayList<Double>(), new ArrayList<Boolean>());

也不

ArrayList<String> myList = sum(new LinkedList<Integer>(), new ArrayList<Boolean>());

(...)

编辑 2:我找到了一个更好的例子。想象一个接口(interface) Tuple,带有子类 Duple、Triple>...,如果有像这样的东西就太好了

<T extends Tuple<?>>  T<String> reset( T<String> input, T<Boolean> listToNull){          
T copy = input.copy();
for (int i=0; i<input.size();i++){
if (listToNull.get(i)){
copy.set(i,null);
}
}
}

最佳答案

我建议你做些什么

首先,摆脱方法参数泛型。没有理由强制调用者提供 ArrayList<Integer>ArrayList<Boolean>当你想返回 ArrayList<String> 时.只需接受任何 List<Integer>List<Boolean> , 并留给你的方法将它们变成适当的返回 List .

既然你知道你想要返回某种类型的 ListString您可以将参数写为 <T extends List<String>>你的返回类型很简单 T .

这给我们留下了困难的部分:让您的方法实例化未知类型的对象。那很难。你不能只做 new T(); .您需要调用会产生 T 的东西代表你。幸运的是,Java 8 为 Supplier<T> 提供了一个函数式接口(interface).您只需要调用 get()获取ArrayList<String>的方法或者你可能想要的任何其他东西。痛苦的部分是您的调用者需要提供他们自己的 Supplier .但我认为这与 Java 8 中的一样好。

代码如下:

public <T extends List<String>> T sum(
List<Integer> sublistOfInts,
List<Boolean> sublistOfBooleans,
Supplier<T> listMaker) {
T sublistOfStrings = listMaker.get();
/*fusion of both lists*/

return sublistOfStrings;
}

至少这个编译:

ArrayList<String> myNewList = thing.<ArrayList<String>>sum(intList, boolList, ArrayList::new);

这不是:

ArrayList<String> myNewList = thing.<ArrayList<String>>sum(intList, boolList, LinkedListList::new);

您甚至可以在调用时省略类型参数。这编译:

ArrayList<String> myNewList = thing.sum(intList, boolList, ArrayList::new);

这不是:

ArrayList<String> myNewList = thing.sum(intList, boolList, LinkedListList::new);

为什么你不能只做你要求的事情

简而言之,这是因为类型参数本身不能被参数化。那是因为我们不知道他们自己会接受多少类型参数,也不知道可能对他们施加的限制。

学习相对晦涩的类(class)RoleList .它扩展了 ArrayList<Object> , 所以它适合 List<?> .但它根本不需要类型参数。因此,如果有人调用了您的 sum()使用 RoleList 的方法,在您的示例中需要:

RoleList<Integer> intList = // something
RoleList<Boolean> boolList = // something
RoleList<String> myNewList = thing.sum(intList, boolList);

这显然行不通,因为它需要一个未参数化的类型来接受类型参数。如果你像这样去掉类型参数:

RoleList intList = // something
RoleList boolList = // something
RoleList myNewList = thing.sum(intList, boolList);

然后你的方法需要能够接受两个List<Object>参数并返回值 List<Object> .这违反了您的基本前提,即您能够控制这些事情。

实际上,RoleList这里根本不应该被允许,因为你永远不能保证一个实例只包含 Integer s,另一个只有Boolean s,只有第三个String秒。允许 RoleList 的编译器这里的类型检查肯定比我们现在的要弱。

所以归根结底,你不能做你要求的事情,因为 Java 不是那样构建的。

为什么可以

您仍然可以在 sum() 中获得完整的类型安全使用上面我建议的方法的方法。您确保传入的 List s 只包含 IntegerBoolean值,分别。您确保调用者可以依赖 List 的特定子类型的返回仅包含 String值。所有有所作为的保证都在那里。

关于java - 在 Java Generics 中输入泛型类型而不是它自己的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34512157/

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