Evg*_*eev 16 java immutability
这个Java教程 说不可变对象在创建后不能改变它的状态.
java.lang.String 有一个领域
/** Cache the hash code for the string */
private int hash; // Default to 0
Run Code Online (Sandbox Code Playgroud)
在hashCode()方法的第一次调用时初始化,因此它在创建后更改:
String s = new String(new char[] {' '});
Field hash = s.getClass().getDeclaredField("hash");
hash.setAccessible(true);
System.out.println(hash.get(s));
s.hashCode();
System.out.println(hash.get(s));
Run Code Online (Sandbox Code Playgroud)
产量
0
32
Run Code Online (Sandbox Code Playgroud)
调用Stringimmutable 是否正确?
Sle*_*led 13
更好的定义不是对象不会改变,而是不能观察到它已被改变.它的行为永远不会改变:.substring(x,y)将始终为该字符串同样返回相同的东西equals以及所有其他方法.
该变量在您第一次调用时计算,.hashcode()并在进一步调用时进行缓存.这基本上就是他们在函数式编程语言中所谓的" memoization ".
反射不是真正的"编程"工具,而是元编程(即用于生成程序的编程程序),因此它并不真正重要.它相当于使用内存调试器更改常量值.
"不可变"一词含糊不清,不允许精确定义.
我建议从Eric Lippert的博客中阅读各种不可变性.虽然它在技术上是一篇C#文章,但它与提出的问题非常相关.特别是:
观察不变性:
假设你有一个具有属性的对象,每次你调用一个方法,查看一个字段等,你会得到相同的结果.从调用者的角度来看,这样的对象将是不可变的.但是你可以想象,在幕后,对象正在进行延迟初始化,在哈希表中记忆函数调用的结果等.对象的"胆量"可能完全是可变的.
有什么关系?真正深度不可变的对象根本不会改变它们的内部状态,因此本质上是线程安全的.在幕后可变的对象可能仍然需要具有复杂的线程代码,以便在"同时"在两个线程上调用对象时保护其内部可变状态免于损坏.
| 归档时间: |
|
| 查看次数: |
574 次 |
| 最近记录: |