Java Final arraylist
Мой вопрос в том, чтобы объявить arraylist окончательным. Я знаю, что как только я напишу окончательный ArrayList list = new ArrayList();
, я могу добавить, удалить объекты из этого списка, но я не могу list = new ArrayList()
или list = list1
. Но что будет использовать объявление arraylist как
Private static final ArrayList list = new ArrayList();
. И помимо разницы, о которой я упомянул выше, какая разница между двумя декларациями:
1. ArrayList list = new ArrayList()
2. private static final ArrayList list = new ArrayList();
Ответы
Ответ 1
Вы правы, что объявление окончания list
означает, что вы не можете переназначить переменную list
на другой объект.
Другой вопрос (я думаю) был
public class SomeClass {
private static final ArrayList list = new ArrayList();
}
против
public class SomeClass {
ArrayList list = new ArrayList();
}
пусть поочередно принимать каждый модификатор.
private
Значит, только этот класс (SomeClass
) может получить доступ к list
static
Указывает, что для всех экземпляров SomeClass
существует только один экземпляр переменной list
. Экземпляр списка связан с классом SomeClass, а не с каждым новым экземпляром SomeClass. Если переменная нестатическая, она считается переменной экземпляра
final
, как вы знаете, означает, что вы не можете переназначить переменную списка другим значением.
Во втором объявлении нет модификаторов, поэтому переменная является переменной экземпляра, и она также получает защиту от доступа к пакету (иногда называется защитой по умолчанию). Это означает, что этот класс (SomeClass
) и другие классы в одном пакете могут получить доступ к переменной.
Вы можете узнать больше о public
, private
и package-private
здесь: Контроль доступа
Вы можете узнать больше о final
и static
здесь: Переменные класса
Ответ 2
Чтобы "принести немного воды на мельницу", вы поймете интерес к финалу, когда захотите сделать свой список общедоступным, но не поддающимся редактированию.
В java можно сделать список немодифицированным с Collections.unmodifiableList(modifiableList).
Теперь взгляните на следующий код:
public class MyClass{
public static List<String> MY_PUBLIC_LIST;
static{
ArrayList<String> tmp = new ArrayList<String>();
tmp.add("a");
tmp.add("b");
tmp.add("c");
MY_PUBLIC_LIST = tmp;
}
}
Ну, в любом классе, в любом месте вашего кода вы можете сделать что-то вроде этого
MyClass.MY_PUBLIC_LIST = null;
MyClass.MY_PUBLIC_LIST = new ArrayList<String>();
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
Когда вы добавляете ключевое слово final в свою переменную, первая буксировка не будет разрешена
public static final List<String> MY_PUBLIC_LIST;
Но вы все равно сможете изменить содержимое списка:
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
Добавив Collections.unmodifiableList(modifiableList) в конце статического блока, вы тоже это предотвратите:
MY_PUBLIC_LIST = Collections.unmodifiableList(tmp);
Хорошо, мы почти там. Просто чтобы убедиться, что вы получите всю картину, сохраните Collections.unmodifiableList(modifiableList), но позвольте мне удалить последний модификатор
public class MyClass{
public static List<String> MY_PUBLIC_LIST;
static{
ArrayList<String> tmp = new ArrayList<String>();
tmp.add("a");
tmp.add("b");
tmp.add("c");
MY_PUBLIC_LIST = Collections.unmodifiableList(tmp);
}
}
Что вы можете сделать в этом случае?
...
...
Ну, вы можете делать все, что хотите, как в первом случае (учитывая, что вы сначала назначаете новый список):
MyClass.MY_PUBLIC_LIST = null;
MyClass.MY_PUBLIC_LIST = new ArrayList<String>();
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
Ответ 3
Когда вы говорите
final ArrayList list = new ArrayList();
это означает, что переменная list
всегда будет указывать на тот же объект ArrayList
. Есть две ситуации, в которых это может быть полезно.
- Вы хотите удостовериться, что no-one переназначает вашу переменную
list
после ее получения. Это может уменьшить сложность и помочь в понимании семантики вашего класса/метода. В этом случае вам обычно выгоднее использовать хорошие соглашения об именах и сокращать длину метода (класс/метод уже слишком сложный, чтобы его было легко понять).
- При использовании внутренних классов вам необходимо объявить переменные как
final
в охватывающей области, чтобы вы могли получить к ним доступ во внутреннем классе. Таким образом, Java может скопировать вашу переменную final
во внутренний объект класса (она никогда не изменит ее значение), а внутреннему объекту класса не нужно беспокоиться о том, что происходит с внешним объектом класса, пока объект внутреннего класса жив и нуждается для доступа к значению этой переменной.
Вторая часть вашего вопроса касается разницы между
ArrayList list = new ArrayList();
и
private static final ArrayList list = new ArrayList();
Разница, конечно, является модификаторами. private
означает, что он не виден вне класса, static
означает, что он определен на уровне класса и не нужен экземпляр для существования, а final
обсуждается выше. Никакие модификаторы не означают пакетный или стандартный доступ.
Ответ 4
Вы говорите: "Я могу добавлять, удалять (и находить) объекты", но кто I?
Различие между двумя вашими случаями связано с тем, из какого кода можно вызвать эти операции списка.
В общем, вам нужно рассмотреть область применения декларации, вы значительно увеличите удобство обслуживания кода, если уменьшите видимость переменных. Если у вас есть класс:
Public Class MyThing {
public int importantValue;
// more code
}
Это важное значение может быть изменено любым другим кодом в любом другом месте приложения. Если вместо этого вы сделаете его приватным и предоставите аксессуар для чтения:
Public Class MyThing {
private int importantValue;
public int getImportantValue(){
return importantValue;
}
// more code
}
Теперь вы знаете, что только сам класс может изменить значение - для больших приложений это значительно увеличивает ремонтопригодность. Таким образом, объявление частного списка ограничивает, какой код может видеть, и изменять содержимое списка.
Использование static делает список общим для всех экземпляров класса, а не для каждого экземпляра, получающего его копию ovn.