如何确定 Java 方法是否修改作为参数传递的对象

2022-09-01 09:37:41

我来自C++背景,目前正在学习Java。当我尝试使用一些第三方库时,出现了一个问题。如何确定对以对象引用为参数的方法的调用是否修改了对象?在C++由于使用了const关键字,这一点很清楚。如果方法签名为:

void foo(Boo& boo);

我知道引用的对象可能会被修改,而如果方法签名是:

void foo(const Boo& boo);

编译器保证引用的对象不被修改。

我没有在Java中看到类似的东西,因为只有引用本身可以被声明为final,而不是被引用的对象,并且最终的参数首先没有多大意义,因为它无论如何都是通过值传递的。因此,当我看到这样的方法时:

void foo(Boo boo) {...}

如何确定boo引用的对象是否在函数体内进行了修改(可能使用注释)?如果没有办法知道,是否有一些广泛使用的约定或一些最佳实践来避免混淆和错误?


答案 1

如何确定boo引用的对象是否在函数体内被修改(可能使用注释)?

不幸的是,唯一的方法是阅读代码。

如果没有办法知道,是否有一些广泛使用的约定或一些最佳实践来避免混淆和错误?

常见的约定是传递一个无法修改的对象,如果需要,可以使用包装器。这可确保类无法修改对象。

List<String> readOnly = Collections.unmodifiableList(list);

如果对象是可克隆的,您也可以使用,但另一种常见的方法是使用副本。clone()

List<String> readOnly = new ArrayList<>(list);

如果您关心此类行为,单元测试可以显示方法是否修改对象。如果您已经有了单元测试,通常需要额外一到两行来检查这一点。


答案 2

不幸的是,该语言中没有内置这样的工具。一个好的防御做法是将你传递的数据对象定义为不可变的(即,没有任何允许修改其状态的公共方法)。如果您真的担心这一点,则可以在将对象传递给您不信任的方法之前复制/克隆该对象,但这通常是一种多余的预防措施。