Ita*_*key 32 java immutability
我来自C++背景,目前我正在学习Java.当我尝试使用某些第三方库时出现了一个问题.如何确定对作为参数的对象引用的方法的调用是否修改了对象?在C++中,由于使用了const关键字,因此很清楚.如果方法签名是:
void foo(Boo& boo);
Run Code Online (Sandbox Code Playgroud)
我知道引用的对象可能会被修改,而如果方法签名是:
void foo(const Boo& boo);
Run Code Online (Sandbox Code Playgroud)
编译器保证不会修改引用的对象.
我没有在Java中看到类似的东西,因为只有引用本身可以被声明为final,而不是引用的对象,并且最终的参数在第一个地方没有多大意义,因为它无论如何都是通过值传递的.因此,当我看到一个方法,如:
void foo(Boo boo) {...}
Run Code Online (Sandbox Code Playgroud)
如何确定boo引用的对象是否在函数体内修改(可能使用注释)?如果没有办法知道,是否有一些广泛使用的约定或一些最佳实践来避免混淆和错误?
Pet*_*rey 26
如何确定boo引用的对象是否在函数体内修改(可能使用注释)?
唯一的方法是不幸地读取代码.
如果没有办法知道,是否有一些广泛使用的约定或一些最佳实践来避免混淆和错误?
常见的惯例是在需要时使用包装器传递无法修改的对象.这样可以确保类无法修改对象.
List<String> readOnly = Collections.unmodifiableList(list);
Run Code Online (Sandbox Code Playgroud)
如果对象是Cloneable,您也可以使用,clone()但另一种常见方法是使用副本.
List<String> readOnly = new ArrayList<>(list);
Run Code Online (Sandbox Code Playgroud)
如果您关心此类行为,单元测试可以显示方法是否修改了对象.如果您已经进行了单元测试,通常需要一两行来检查.
Mur*_*nik 14
不幸的是,这种语言没有内置这种设施.一个好的防御性做法是将您传递的数据对象定义为不可变的(即,没有任何允许修改其状态的公共方法).如果你真的关心这个问题,你可以在将对象传递给你不信任的方法之前复制/克隆一个对象,但这通常是一个多余的预防措施.
注意:这个答案是更详细的版本
在编译时可以通过注释检查的各种事物之间存在Checker Framework是IJG Immutablity检查器.此检查器允许您使用@Immutable或注释对象引用@ReadOnly.
问题是您经常需要自己注释库.为了简化您的任务,Checker Framework可以自动推断部分注释; 你仍然需要自己做很多事情.