【问题标题】:Why can I change private final ArrayList<Book>? [duplicate]为什么我可以更改私有 final ArrayList<Book>? [复制]
【发布时间】:2013-10-17 10:16:54
【问题描述】:

我的课看起来像这样:

public class InformationSystem {
    private final ArrayList<Book> books;
    private final ArrayList<Reader> readers;

    public InformationSystem() {
        books = new ArrayList<Book>();
        readers = new ArrayList<Reader>();
    }

    public void addBook(final String author, final String title) {
        Book book = new Book(author, title);
        books.add(book);
    }
}

为什么我可以从最终的数组列表中添加/删除值?

【问题讨论】:

  • 你不能重新分配它,但它仍然是可变的
  • 因为它是最终的,嗯?

标签: java arraylist


【解决方案1】:

我不能换车,但我可以换车里的零件:)

来自Language specification # chapter 14.12.4

一旦分配了最终变量,它总是包含相同的值。如果 final 变量持有对对象的引用,则对象的状态可能会通过对对象的操作而改变,但变量将始终引用同一个对象。

你不能回复assign,你仍然可以改变状态。

简而言之

  books  =newBooksList;   // huh! I'm final, No
  books.add(book);       //ok

【讨论】:

    【解决方案2】:

    你想要的是让你的 List 不可变。看到这个帖子:java-immutable-collections

    或者直接看java.util.Collections.unmodifiableList()方法。

    http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html?is-external=true#unmodifiableList%28java.util.List%29

    【讨论】:

      【解决方案3】:

      ArrayList 对象的引用是最终的 - 您不能更改该引用,也不能重新分配。

      但是,你可以调用对象的方法。尤其是这些改变对象状态的方法。

      所以,ArrayList 对象是可变的。另一方面,例如,String 对象是不可变的。你不能改变它们的内部状态。

      【讨论】:

        【解决方案4】:

        您已将 ArrayList 类型的书籍对象创建为 final。 因此,books 对象引用堆上的 ArrayList 对象,并且由于它被声明为 final,因此它的引用永远不会改变,但您可以更改对象的内容。 因此,您可以从定义为 final 的 ArrayList 中添加/删除项目。

        【讨论】:

          【解决方案5】:

          保持对对象 final 的引用使指向该对象的链接保持为 final,不能更改。但是实际对象的状态是可以改变的。

          引用变量指向的链接是final,它指向的对象的状态不是final

          如果您所指的对象是不可变的,那么您将实现您认为会发生的事情。

          【讨论】:

            【解决方案6】:

            final 表示您的引用是不可变的 - 它无法更改。

            然而 ArrayList 是一个可变(可以改变)的数据结构。

            您无法更改books 指向的内容,但您可以更改它指向的数据结构。总之,您拥有对可变数据结构的不可变引用。

            【讨论】:

              【解决方案7】:

              因为您已将 ArrayList 变量 book 声明为最终变量,所以您不能将 book 重新分配给另一个对象,而您可以对当前对象执行任何操作。

                ArrayList<Book> book = new ArrayList<Book>();
              

              您不能像下面这样重新分配 book 变量。

                ArrayList<Book> book2 = new ArrayList<Book>();  
                book = book2;   
              

              虽然您可以对当前 book 对象执行任何操作,因为您没有更改 final 变量的内容,但您正在更改 final 变量所引用的对象的内容。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-05-13
                • 2012-02-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-01-09
                相关资源
                最近更新 更多