请教大佬一个泛型的问题

2021-12-24 11:35:24 +08:00
 Macolor21

我有一个抽象类 Animal, 如下

public abstract class Animal<T> {

    public List<T> getList(){
        return new ArrayList<>();
    }

}

我想要扩展这个抽象类的功能,于是我继承了该抽象类实现了 Tiger 。在这里我会限制 Tiger 的泛型必须是 String 的子类。

我的核心需求是扩展 getList 方法,让其返回值不再是空 List, 而是包含一个元素 "I'm Tiger" 的字符串集合。

以下面的写法,IDEA 会编译出错,请问有什么其他方式实现这个需求吗?

public abstract class Tiger<T extends String> extends Animal<T> {

    @Override
    public List<T> getList() {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("I'm Tiger");
        return strings;
    }
}
2505 次点击
所在节点    Java
8 条回复
gadfly3173
2021-12-24 11:48:44 +08:00
首先 string 没法被继承。。。这是 final class 。
保留 extends String 的话可以改成
ArrayList<T> strings = new ArrayList<>();
strings.add((T) "I'm Tiger");
Leviathann
2021-12-24 11:52:48 +08:00
翻译成 ts ,报错更友好
‘string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'String'.
只能返回 T 的子类型而不是 string
因为 string 不能直接赋值给子类型
wolfie
2021-12-24 11:53:06 +08:00
编译期的东西不指定泛型就行。

或者

public abstract class Tiger extends Animal<String> {
@Override
public List<String> getList() {}
}
debuggerx
2021-12-24 11:54:21 +08:00
Tiger.java:

public abstract class Tiger extends Animal<String> {
--@Override
----public List<String> getList() {
------ArrayList<String> strings = new ArrayList<>();
------strings.add("I'm Tiger");
------return strings;
----}
}
aguesuka
2021-12-24 11:55:32 +08:00
String 是 final 的.
如果 String 不是 final 的, 假如它有一个子类 A. 那么我可以定义 Tiger<A> tiger, 但是 tiger.getList().get(0) 会报 ClassCastException, 因为期待的类型是 A, 实际上是 String. 就像一楼那样
实际上应该是

ArrayList<T> strings = new ArrayList<>();
strings.add(aObjectWhichClassIsT);
return strings;
shily
2021-12-24 12:05:11 +08:00
所以楼主不看错误提示吗?问问题也不发错误提示吗?

楼上也就 2 楼靠谱。


根本原因是父类的 List 无法直接赋值给子类 List; 比如 List<Object> 是无法赋值 给 List<String> 的,因为你无法判断 List 里是否有不合法的数据。

例如:
ArrayList<Object> objs = new ArrayList<>();
objs.add("I am string");
Integer iAmInteger = 10;
objs.add(iAmInteger);


// 一下的场景中 String 就是 T extends Object
List<String> strings = objs; // 此处编译错误,提示需要 List<String> 但是提供了 List<Object>
unco020511
2021-12-24 17:38:38 +08:00
你需要一篮子苹果,我说我给你一篮子水果(水果里啥都有,除了苹果还有别的),你会同意吗?
CodeGou
2021-12-24 22:14:35 +08:00
kotlin 里有 in out 的概念。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/824177

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX