java中的const函数参数?

时间:2016-12-28 11:34:56

标签: java const-correctness

有没有办法在Java中实现类似于C ++的const的东西?具体来说,我有一个像

这样的功能
private static Vector2 sum(Vector2 vec1, Vector2 vec2) {
    return vec1.cpy().add(vec2);
}

我想要

  1. 在签名中明确说明它不会修改它的论点,
  2. 强制它不修改它的参数(最好是在编译时,但插入运行时断言也可以)。
  3. 现在我知道java严格按引用传递(我只是戏弄,当然我知道it is pass-by-value or rather pass-by-copying-a-reference)。我的意思是,在Java中,当您调用方法时,将复制引用,但该引用指向相同的对象内容。如果类具有公共字段或setter,则被调用的方法始终可以修改传递的对象的内容。有没有例如像@NotNull这样的注释或防止这种情况的工具?我刚刚找到了像@Contract(pure = true)这样的JetBrains注释,但我认为它们不提供任何检查。

3 个答案:

答案 0 :(得分:3)

您无法保证该方法不会更改参数。如果要避免更改对象,则应使其不可变。您可以使用一些包装类在内部传递,而不提供setter。或者你可以让你的setter包本地,并在你需要调用一些package-local方法时在同一个包中使用一些访问助手类。

答案 1 :(得分:2)

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

如果您需要限制对这些内容的访问权限,则可能需要创建隐藏Vector包装器的不可变类。基本上,它将仅通过隐藏setter来重定向阻止任何更新的方法,并将getter限制为原始值,返回实例可以更改其中的值。

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

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

答案 2 :(得分:1)

在Java中,唯一的方法是使用只读接口和可变接口。这不容易维护,const会更好,但它不可用。你可以写

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

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

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