类构造函数中的 ArrayList 字段

Posted

技术标签:

【中文标题】类构造函数中的 ArrayList 字段【英文标题】:ArrayList fields in class constructors 【发布时间】:2021-04-02 23:51:35 【问题描述】:

我目前正在学习初级 Java,并且在将 ArrayList 用作构造函数中的参数时遇到问题。

当我必须在类构造函数中初始化一个ArrayList 时,我通常会这样写(为了这个例子,假设我想创建一个整数的ArrayList 作为类字段)。

public class Example 

    private ArrayList<Integer> myList;

    public Example(ArrayList<Integer> myInts)
        this.myList = myInts;
    
       

但是,当我看到人们在教程或教科书中做同样的事情时,他们会编写以下代码:

public class Example 

    private ArrayList<Integer> myList;

    public Example(int myInts)
        this.myList = new ArrayList<>();
        addIntegers(myInts);
    
 
    public void addIntegers(int myInts)
        this.myList.add(myInts);
    
      

这两个例子有区别吗?我认为我的方法是错误的,但实际上运行这两个版本给了我相同的结果(根据我的有限理解),所以我很难掌握这两个变体的区别。

【问题讨论】:

在你的第二个例子中,你为什么命名一个int参数myInts(复数)? int 是单数,而不是 Collection 类型或数组。这令人困惑,使我无法理解您的问题。 您是否尝试过将null 传递给两个示例,然后尝试对ArrayList 字段进行操作?第一个会抛出异常。 @Glains:错字。将其视为“myInt”。 我认为在第二个示例中,构造函数的 myInts 参数也应该是 ArrayList&lt;Integer&gt;不是 int,对吗? @KevinAnderson 我打错了:它实际上接受一个名为 myInt 的 int(不带 s)。 【参考方案1】:

有区别,是的。在呈现的代码中,可以像这样调用构造函数:

ArrayList<Integer> values = new ArrayList<>(List.of(1, 2, 3, 4));
Example example = new Example(values);

对象构造完成后,调用方仍然可以访问values,即example使用的内部数据结构。通过操纵此数据结构,调用方可能会使example 处于意外状态并导致问题。

为了防止此类问题,我们通常不会直接使用从外部传入的引用类型来获取内部状态,而是生成它们的副本。本质上,这就是第二个示例所做的。如果我们仍然想将List 作为参数传递给构造函数,我们可以复制列表:

public class Example 

    private ArrayList<Integer> myList;

    public Example(Collection<Integer> myInts) 
        this.myList = new ArrayList<>(Objects.requireNonNull(myInts));
    

    public Example(Integer... myInts) 
        this(Arrays.asList(Objects.requireNonNull(myInts)));
    

    public Example(int... myInts) 
        this(Arrays.stream(Objects.requireNonNull(myInts))
                .boxed()
                .collect(Collectors.toList()));
               

现在,如果调用方改变了传递给构造函数的ListExample-instance 中的内部数据结构不会受到影响,因为它在原始列表的副本上运行。

备注:如果列表类型是可变的,那么复制列表通常是不够的;我们将不得不深度复制列表(即创建每个列表条目的副本)。这 - 通常 - 在 Java 中是不可能的。

【讨论】:

感谢您的出色回答:这正是我想要的。 @CarloBresciani - 更好的感谢方式是接受和/或支持答案。 ***.com/help/someone-answers @ArvindKumarAvinash 我做到了,但我不是 lv 15。 @CarloBresciani 现在你是 @CarloBresciani - 此外,您无需拥有+15 信誉点即可接受答案。为了将其标记为已接受,您需要单击left of the answer 的大复选标记✓。

以上是关于类构造函数中的 ArrayList 字段的主要内容,如果未能解决你的问题,请参考以下文章

当 ArrayList 和构造函数/获取器存储 2 个其他类时,如何从一个类添加到 ArrayList

有没有办法让 Arraylist 元素等于类构造函数?

面试题总结

如何使用 Visual Studio(和/或 ReSharper)从类字段生成构造函数?

39.C#--面对对象构造函数及构造函数继承使用

派生类中的重载构造函数