в чем смысл окончательного ArrayList?

Какие преимущества / недостатки мы можем получить, сделав ArrayList (или другую коллекцию) окончательным? Я все еще могу добавлять в ArrayList новые элементы, удалять элементы и обновлять их. Но какой эффект делает его окончательны

 Pankaj Kumar25 мая 2012 г., 10:26
когда массив объявлен как окончательный, состояние объекта, хранящегося в массиве, может быть изменено. Вы должны сделать его неизменным, чтобы не допустить модификаций.

Ответы на вопрос(12)

final гарантирует, что вы не сможете переназначить эту ссылку на объект после ее назначения. Как вы упомянули, вы все еще можете использовать эти методы для внесения изменений.

Если вы объединяетеfinal ключевое слово с использованием Collections.unmodifiableList, вы получаете поведение, которого, вероятно, пытаетесь достичь, например:

final List fixedList = Collections.unmodifiableList(someList);

Это приводит к тому, что в списке указанfixedList нельзя изменить. Остерегайтесь, однако, что это все еще может быть изменено черезsomeList ссылка (поэтому убедитесь, что она не входит в область действия после этого присвоения.)

применяться к переменным-членам, методам, классам и локальным переменным в Java. Как только вы сделаете ссылку final, вам не разрешено изменять эту ссылку, и компилятор проверит это и выдаст ошибку компиляции, если вы попытаетесь повторно инициализировать final переменные в java.

final имеет много последствий при многопоточности.

JMM четко определяетfinal завершение инициализации поля гарантируется.

Что неясно определено:

Компиляторы могут свободно переупорядочивать их через барьеры памяти. Компиляторы всегда могут прочитать кэшированную копию.

Пример. В сочетании с реализацией неизменяемого списка вы получаете надежных членов, которых вы можете сделать общедоступными.

Пример: когда вы полагаетесь на эту ссылку не меняется, вам нужно окончательное. Это верно в сценариях синхронизации, например.

Там может быть гораздо больше примеров. Это хороший способ объявить участников окончательными, если вы вообще не собираетесь менять ссылку.

Решение Вопроса

Это означает, что вы не можете перепривязать переменную, чтобы указывать на другую экземпляр коллекции:

final List<Integer> list = new ArrayList<Integer>();
list = new ArrayList<Integer>(); // Since `list' is final, this won't compile

По стилю я объявляю большинство ссылок, которые не собираюсь менять, какfinal.

Я все еще могу добавлять в ArrayList новые элементы, удалять элементы и обновлять их.

Если вы хотите, вы можете предотвратить вставку, удаление и т. Д. С помощьюCollections.unmodifiableList():

final List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>(...));
 Peter Lawrey25 мая 2012 г., 10:19
+ 1 Использование заключительных полей может улучшить ясность, поскольку классы могут быть довольно длинными. Я не использую final в методах так часто, как пытаюсь разбить длинные методы.

что вы не можете переназначить его ссылку. Попытка сделать что-то подобное ниже приведет к ошибке компилятора.

final List<String> list = new ArrayList<String>();

list = new LinkedList<String>();
     ^
     Compiler error here

Если вы действительно хотите неизменный список, вы должны использоватьCollections.unmodifiableList() метод.

вам придется делать глубокие копии содержимого списка. UnmodifiableList только сделает список ссылок несколько неизменным. Теперь создание глубокой копии списка или массива будет не по размерам увеличиваться в памяти. Вы можете использовать сериализацию / десериализацию и сохранить глубокую копию массива / списка во временном файле. Сеттер не будет доступен, так как член varaible должен быть неизменным. Получатель должен сериализовать переменную-член в файл, а затем десализовать его, чтобы получить глубокую копию. Seraialization имеет врожденную природу проникновения в глубины дерева объектов. Это обеспечит полную неизменность при некоторых затратах на производительность.

 package com.home.immutable.serial;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public final class ImmutableBySerial {

    private final int num;
    private final String str;
    private final ArrayList<TestObjSerial> immutableList;

    ImmutableBySerial(int num, String str, ArrayList<TestObjSerial> list){
        this.num = num;
        this.str = str;
        this.immutableList = getDeepCloned(list);
    }

    public int getNum(){
        return num;
    }

    public String getStr(){
        return str;
    }

    public ArrayList<TestObjSerial> getImmutableList(){
        return getDeepCloned(immutableList);
    }

    private ArrayList<TestObjSerial> getDeepCloned(ArrayList<TestObjSerial> list){
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        ArrayList<TestObjSerial> clonedObj = null;
        try {
             fos = new FileOutputStream(new File("temp"));
             oos = new ObjectOutputStream(fos);
             oos.writeObject(list);
             fis = new FileInputStream(new File("temp"));
             ois = new ObjectInputStream(fis);
             clonedObj = (ArrayList<TestObjSerial>)ois.readObject();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                oos.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return clonedObj;
    }
}

что вы можете сделать с ArrayList, как вы правильно заметили - сам ArrayList все еще изменчив. Вы только что сделали ссылку неизменной.

Но создание переменной final имеет и другие преимущества:

Это предотвращает изменение переменной, если ожидается, что она останется постоянной. Это может помочь предотвратить будущие ошибки. Создание переменныхfinal может помочь компилятору оптимизировать производительность.

В общем, чем больше вещей, которые вы делаете неизменными, тем лучше. Таким образом, сделать ссылки окончательными (даже если они являются ссылками на изменяемые объекты), как правило, хорошая идея.

final, чтобы избавить пользователей моего класса от проверки, является ли он нулевым или нет. Это работает, потому что, как только значение уже присвоено окончательной переменной, оно никогда не может быть переназначено другому значению, включая null.

вы пытаетесь добиться того, чтобы сделать список неизменным, я думаю. Однако когда вы помечаете ссылку на список как окончательную, это означает, что ссылка не может быть указана на любой другой объект списка, кроме этого.

Если вы хотите, чтобы окончательный (неизменяемый) ArrayList вместо этого использовал служебный метод класса Collections Collections.unmodifaibleList (list).

кодировал и пример, чтобы добавить к объяснению еще один аспект.

Окончательный список массивов все еще можно изменить, обратитесь к приведенному ниже примеру и запустите его, чтобы убедиться в этом.

Вот неизменяемый класс с неизменным объявлением List:

public final class ImmutableClassWithArrayList {
 final List<String> theFinalListVar = new ArrayList<String>();
}

А вот и драйвер:

public class ImmutableClassWithArrayListTester {
public static void main(String[] args) {
    ImmutableClassWithArrayList immClass = new ImmutableClassWithArrayList();
    immClass.theFinalListVar.add("name");
    immClass.theFinalListVar.forEach(str -> System.out.println(str));
 }
}

Как видите, основным методом является добавление (изменение) списка. Поэтому единственное, на что следует обратить внимание, это то, что «ссылка» на объект типа коллекции не может быть переназначена другому такому объекту. Как и в ответе adarshr выше, вы не можете сделать immClass.theFinalListVar = new ArrayList (); в основном методе здесь.

Модификация действительно помогла мне понять это и надеюсь, что это поможет таким же образом.

new ArrayList например

Ваш ответ на вопрос