Java 中的常量函数参数?

问题描述 投票:0回答:3

有没有办法在Java中实现类似C++的

const
的功能?具体来说,我有一个类似的功能

private static Vector2 sum(Vector2 vec1, Vector2 vec2) {
    return vec1.cpy().add(vec2);
}

我想要

  1. 在签名中明确表示它不会修改其参数,
  2. 强制它不修改其参数(最好是在编译时,但插入运行时断言也可以)。

现在我知道Java是严格的按引用传递(我只是开玩笑,我知道它是按值传递,或者当然是按复制引用传递)。我的意思是,在Java中,当你调用一个方法时,引用会被复制,但该引用指向相同的对象内容。如果类具有公共字段或设置器,则被调用的方法始终可以修改传递对象的内容。有没有例如像

@NotNull
这样的注释或防止这种情况的工具?我刚刚找到了像
@Contract(pure = true)
这样的 JetBrains 注释,但我认为它们没有提供任何检查。

java const-correctness
3个回答
4
投票

您不能保证该方法不会更改参数。如果你想避免改变对象,你应该让它不可变。您可以使用一些包装类在内部传递,而不需要提供设置器。或者,如果您需要调用某些包本地方法,您可以使您的设置器成为包本地的,并在同一包中使用一些访问帮助器类。


4
投票

在 Java 中,做到这一点的唯一方法是拥有一个只读接口和一个可变接口。 这并不容易维护,并且

const
会更好,但它不可用。可以写

interface ReadOnlyVector<T> {
    int size();
    // getter methods
    T get(int n);

    default ReadOnlyVector<T> add(ReadOnlyVector<T> v) { 
        // add two vectors and create a new one.
    }
}

interface Vector<T> extends ReadOnlyVector<T> {
    // mutating methods.
    void add(T t);
}

2
投票

您可以将

final
添加到参数中,但这只会阻止这些参数的初始化,您仍然可以调用方法和设置器来修改
Vector
的内容。

如果您需要限制对这些内容的访问,您可能需要创建一个隐藏

Vector
包装器的不可变类。基本上,它只会重定向那些通过隐藏 setter 并将 getter 限制为原始值来防止任何更新的方法,返回一个实例可以更改其中的值。

当然,还有一些彻底的解决方案,你可以克隆 Vector 及其内容。即使有人尝试更新某些值,也能保证实例的安全。这只会在调用期间出现问题,使用错误的值,但会保持原始实例不变。

或者您可以使用这两种解决方案,创建一个返回克隆实例的包装器(只需要提供一个返回克隆的 get(int index) )。该解决方案是内存消耗(仅克隆需要的实例)和限制性 getter 之间的折衷方案。

© www.soinside.com 2019 - 2024. All rights reserved.