Rom*_*man 31 java final unmodifiable
我可以看到Collections.unmodifiableSet返回给定集合的不可修改的视图但我不明白为什么我们不能只使用final修饰符来完成此操作.
在我的理解中,final声明一个常量:无法修改的东西.因此,如果将一个集合声明为常量,则无法修改它:无法从集合中删除任何内容,也无法添加任何内容.
我们为什么需要Collections.unmodifiableSet?
Rob*_*Rob 65
final 声明一个无法修改的对象引用,例如
private final Foo something = new Foo();
Run Code Online (Sandbox Code Playgroud)
创建一个新的Foo并将引用放入something.此后,不可能something改为指向不同的实例Foo.
这并不能防止对象的内部状态的修改.我仍然可以调用Foo相关范围可访问的任何方法.如果这些方法中的一个或多个修改了该对象的内部状态,那么final就不会阻止它.
因此,以下内容:
private final Set<String> fixed = new HashSet<String>();
Run Code Online (Sandbox Code Playgroud)
并没有创建一个Set不能被添加到或以其他方式改变; 它只意味着fixed只会引用该实例.
相比之下,做:
private Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
Run Code Online (Sandbox Code Playgroud)
创建一个实例,如果一个人试图调用Set它将抛出UnsupportedOperationException,fixed.add()或者fixed.remove()例如 - 对象本身将保护其内部状态并防止它被修改.
为了完整起见:
private final Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
Run Code Online (Sandbox Code Playgroud)
创建一个Set不允许更改其内部状态的实例,也意味着fixed只会指向该集的实例.
final可用于创建基元常量的原因是基于无法更改值的事实.请记住,fixed上面只是一个引用 - 一个包含无法更改的地址的变量.好吧,对于原始人,例如
private final int ANSWER = 42;
Run Code Online (Sandbox Code Playgroud)
值ANSWER是42.因为ANSWER不能改变,它只会有42的值.
模糊所有线条的一个例子是:
private final String QUESTION = "The ultimate question";
Run Code Online (Sandbox Code Playgroud)
根据上述规则,QUESTION包含实例的地址String代表"最终问题",并且该地址不能更改.这里要记住的一点是,String本身是不可变的-你不能做任何事情的一个实例,String从而改变它,任何操作,否则这样做(如replace,substring等)返回引用的完全不同的情况String.
小智 15
final只保证对变量所代表的对象的引用不能被改变,它不会对该对象的实例及其可变性做任何事情.
final Set s = new Set();只是保证你不能再做s = new Set();了.它不会使集合不可修改,如果你开始时无法添加任何内容.因此,为了使其真正清楚,final只影响变量引用而不是引用指向的对象.
我可以做以下事情:
final List<String> l = new ArrayList<String>();
l.add("hello");
l.add("world");
l.remove(0);
Run Code Online (Sandbox Code Playgroud)
但我不能这样做.
l = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)
再次因为final我无法修改l指向的变量.
您必须执行以下三项操作之一才能使Collection容器线程安全.
java.util.Collections.syncronizedXXX();
Run Code Online (Sandbox Code Playgroud)
要么
java.util.Collections.unmodifiableXXX();
Run Code Online (Sandbox Code Playgroud)
或者使用其中一个合适的容器java.util.concurrency.* package.
如果我有一个Person对象并且final Person p = new Person("me");这意味着我无法重新分配p指向另一个Person对象.我仍然可以p.setFirstName("you");
令人困惑的是这种情况
final int PI = 3.14;
final String greeting = "Hello World!";
Run Code Online (Sandbox Code Playgroud)
看起来像const在C++中,实际上它们指向的对象本质上是不可变的/不可修改的.具有可以改变对象内部状态的mutator方法的容器或对象const不仅仅是对这些对象的引用,final而且不能重新分配以引用另一个对象.
| 归档时间: |
|
| 查看次数: |
35416 次 |
| 最近记录: |