通过使ArrayList(或其他Collection)最终获得哪些优点/缺点?我仍然可以添加ArrayList新元素,删除元素并更新它。但是什么影响使它成为最终的?
答案 0 :(得分:120)
但是它的最终效果是什么呢?
这意味着您无法重新绑定变量以指向其他集合实例:
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>(...));
答案 1 :(得分:14)
这只是意味着您无法重新分配其参考。尝试执行以下操作会导致编译器错误。
final List<String> list = new ArrayList<String>();
list = new LinkedList<String>();
^
Compiler error here
如果你真的想要一个不可变列表,你应该使用Collections.unmodifiableList()
方法。
答案 2 :(得分:8)
例如,您将无法使用new ArrayList
修改其引用。
答案 3 :(得分:5)
创建变量final
可确保在分配后不能重新分配该对象引用。如您所述,您仍然可以使用该列表方法进行更改。
如果您将final
关键字与Collections.unmodifiableList的使用结合起来,那么就可以了解您可能尝试实现的行为,例如:
final List fixedList = Collections.unmodifiableList(someList);
这导致fixedList
指向的列表无法更改。但要注意它仍然可以通过someList
引用进行更改(因此请确保在此对齐后它超出范围。)
答案 4 :(得分:5)
final
在多线程下会产生很多后果。
final
字段的初始化完成得到保证。没有明确定义的是:
答案 5 :(得分:3)
正如您正确观察到的那样,它不会影响您对ArrayList所能做的事情 - ArrayList本身仍然是可变的。您刚刚将引用设为不可变。
但是制作变量最终确实还有其他好处:
final
可以帮助编译器进行某些性能优化。一般来说,你制作不变的东西越多越好。因此,使引用最终(即使它们是对可变对象的引用)通常是一个好主意。
答案 6 :(得分:1)
Final是java中的关键字或保留字,可以应用于 Java中的成员变量,方法,类和局部变量。一旦您 作出参考最后你不能改变那个参考 如果你尝试,编译器将验证这一点并引发编译错误 重新初始化java中的最终变量。
答案 7 :(得分:1)
你不能像aix所说的那样将它重新绑定到不同的集合中。
实施例: 与不可变列表实现相结合,您将获得可以公开使用的安全成员。
实施例: 当你依赖那个参考不改变你需要最终。例如,在同步方案中也是如此。
可能还有更多例子。如果您根本不打算更改引用,那么声明成员final是一种很好的方式。
答案 8 :(得分:1)
我个人将我的类的collections字段标记为final
,以保存我的类的用户不检查它是否为null。这是有效的,因为一旦将值分配给最终变量,就永远不会将其重新分配给另一个值,包括null。
答案 9 :(得分:1)
要获得真正不可变的列表,您必须制作列表内容的深层副本。 UnmodifiableList只会使引用列表有些不可变。 现在制作List或数组的深层副本对于内存越来越大而言将是艰难的。 您可以使用序列化/反序列化并将数组/列表的深层副本存储到临时文件中。由于成员变量需要不可变,因此setter将不可用。 getter会将成员变量序列化为一个文件,然后对其进行desialize以获得一个深层副本。 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;
}
}
答案 10 :(得分:0)
基本上你在这里想要实现的是让我觉得列表不可变。但是,当您标记列表引用final时,它意味着引用不能指向除此之外的任何其他列表对象。
如果你想要一个final(不可变)ArrayList,那就去找Collections类的实用工具方法Collections.unmodifaibleList(list)。
答案 11 :(得分:0)
我开始考虑同样的问题,编码和例子从另一个角度添加到解释中。
最终的arrayList仍然可以修改,请参考下面的示例并运行它以查看您的自己。
这是具有不可变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));
}
}
如您所见,主要方法是添加(修改)列表。因此,唯一需要注意的是&#34;参考&#34;对于集合类型的对象,不能重新分配给另一个这样的对象。正如上面的adarshr的回答,你不能做immClass.theFinalListVar = new ArrayList();在这里的主要方法。
修改部分确实帮助我理解了这一点,并希望它有同样的帮助。