【问题标题】:When returning an ArrayList do I have to return the <Type> along with it?返回 ArrayList 时,我是否必须将 <Type> 连同它一起返回?
【发布时间】:2019-01-17 13:51:56
【问题描述】:

具体来说,如果我返回一个填充的ArrayList,我是否必须返回带有它的类型,例如ArrayList&lt;modNode&gt;?为了补充这一点,如果我对使用&lt;T&gt; 标签的自定义链接列表使用通用类型,我是否必须返回ArrayList&lt;modNode&lt;T&gt;&gt;?只是对包含泛型对象的 ArrayList 的属性有点好奇...提前致谢!

【问题讨论】:

  • 不太清楚你在问什么。你能举例说明你的意思吗?
  • 你能分享一下代码和你遇到的问题吗?
  • 如果您打开所有编译器警告,当您不正确地返回原始类型或任何其他不安全类型时,编译器会告诉您。开启所有警告通常是一种很好的做法。

标签: java arraylist linked-list generic-programming


【解决方案1】:

假设您有一个返回 ArrayListString 对象的方法:

public ArrayList<String> foo() {
    ArrayList<String> list = new ArrayList<>();
    // ... fill list ...
    return list;
}

这就是您通常1在 Java 5+ 中声明方法的方式(因为添加了泛型)。但是您没有必须这样做。您可以将方法声明为:

public ArrayList foo() {
    // ... code ...
    return list;
}

这意味着您正在使用raw types。除非您正在与旧版(Java 5 之前)库/应用程序进行交互,否则您 never want to use raw types。原因是原始类型(几乎?)等同于返回ArrayList&lt;Object&gt;。您刚刚失去了泛型提供的所有类型安全性。泛型的原因是提供编译时2 类型检查,这样您就不会意外使用错误的类型。例如,您现在可以将Dog 添加到foo 返回的ArrayList,即使您希望它只包含String 对象。此外,使用返回的ArrayList 的代码不能保证ArrayList 内只有String 对象,这可能会导致各种令人头疼的问题。

您可以通过强制转换来绕过原始类型:

String element = (String) foo().get(0);

但是,无论如何,这基本上是通用代码编译的内容;除非您不再具有编译时安全性。

如果元素类型也是通用的,那么是的,您也希望返回该信息。假设您返回 ArrayListSupplier 对象。每个Supplier 都会返回所需的String 对象。

public ArrayList<Supplier<String>> foo() {
    // ... code ...
}

请务必在此处给出Supplier 的通用签名,以便您可以执行以下操作:

for (Supplier<String> sup : foo()) {
    String str = sup.get();
    // .. do something with "str" ...
}

如果您返回ArrayList&lt;Supplier&gt;,那么每个Supplier.get() 将返回一个Object。你又失去了所有类型安全。


1.实际上,在几乎所有情况下,您都希望返回 List 而不是 ArrayList。最好program to an interface

2。由于type erasure,它仅在编译时有效。另见this

【讨论】:

  • 我明白了!非常感谢您的意见!
【解决方案2】:

类型参数&lt;T&gt; 取决于您提供给通用类型的实际类型参数。例如:-

   List<String> names = new ArrayList<>();

String是参数化类型List&lt;String&gt;的实际类型参数。在幕后编译器会自动对每个元素进行强制转换。所以你可以放心地期待get 方法将返回String 类型。

modNode 类是泛型类型。然后调用者必须声明什么是实际的类型参数。它可以是 String,扩展 Node 的类型或其他类型。下面的例子:-

   List<modeNode<String>> modeNodes = new ArrayList<>();

但是您的ArrayList&lt;modNode&lt;T&gt;&gt; 实际类型参数已经是modeNode。因此get 方法可能会返回某种参数化类型modeNode&lt;T&gt;。例如:-

   List<modeNode<String>> modeNodes = new ArrayList<>();
   ....
   modeNode<String> mn = modeNodes.get(0);

注意事项:-

** 将 modNode 类型类名重命名为 ModNode 以遵循 Java 约定。类名必须以大写字母开头。

   ModeNode<Node> mn = ModeNode.getInstance();
   //More readable due to following naming convention.
   List<ModeNode<Node>> mns = new ArrayList<>();

** 最好声明为接口类型List,而不是具体类型ArrayList。除非你想使用特定的ArrayList 行为实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多