【问题标题】:Const function arguments in java?java中的const函数参数?
【发布时间】:2016-12-28 11:34:56
【问题描述】:

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

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

我想要

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

现在我知道 java 是严格按引用传递的(我只是在开玩笑,我当然知道 it is pass-by-value or rather pass-by-copying-a-reference)。我的意思是,在 Java 中,当您调用方法时,会复制引用,但该引用指向相同的对象内容。如果类具有公共字段或设置器,则被调用的方法始终可以修改传递对象的内容。有没有例如@NotNull 之类的注释或防止这种情况的工具?我刚刚找到了像 @Contract(pure = true) 这样的 JetBrains 注释,但我认为它们没有提供任何检查。

【问题讨论】:

  • 您可以将final 添加到参数中,但这只会阻止这些参数的初始化,您仍然可以调用方法和setter 来修改Vector 的内容。如果您需要限制对这些的访问,您可能需要创建一个隐藏Vector 的不可变类。基本上它会编写所有方法来防止更新(隐藏 setter 并将 getter 限制为原始值)

标签: java const-correctness


【解决方案1】:

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

【讨论】:

  • 小心getter,这可能会返回一个可以更新的POJO;)我们基本上添加了相同的想法
  • @AxelH 是的,这是实现的细节,我只是提供了一个通用的方法:)
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

    在 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-13
      • 1970-01-01
      • 2015-04-04
      • 2012-06-14
      • 1970-01-01
      相关资源
      最近更新 更多