【问题标题】:Making abstract method parameters final in Java在Java中使抽象方法参数最终化
【发布时间】:2013-07-17 04:37:37
【问题描述】:

我有一个带有抽象方法的抽象类,我希望将其参数设置为final - 也就是说,我不想让抽象类和方法的实现重新分配参数。

编辑:这样做的动机本身并不是不变性,这更多地与对象的设计有关。 (事实上​​,在我的用例中,参数是集合,它将在抽象方法的实现中发生变化。)相反,我想与任何实现我的抽象类/方法的人沟通,这些变量不应该被重新分配。我知道我可以通过 java-doc 进行沟通,但我一直在寻找更具合同性的东西——他们必须遵循,而不仅仅是被引导遵循。

在非抽象方法中,我可以使用 final 关键字来执行此操作 - 例如:

public class MyClazz {
  public void doSomething(final int finalParameter){
    finalParameter++; // compile error - cannot assign a value to final variable
  }
}

但是,如果我在抽象方法中使用 final 关键字,这不构成合同的一部分 - 也就是说,抽象方法的实现不需要 final 关键字,并且可以重新分配参数:

public abstract class MyAbstractClazz {
  public abstract void doSomething(final int finalVariable);
}

public class MyExtendedClazz extends MyAbstractClazz {
  @Override
  public void doSomething(int finalVariable) { // does not require final keyword
    finalVariable++; // so the variable is modifiable
  }
}

正如SO Question 的答案中所指出的,final 关键字不构成方法签名的一部分,这就是抽象类的实现不需要它的原因。

那么,有两个问题:

  1. 为什么final 关键字不是方法签名的一部分?我明白不是, 但我想知道是否有特殊原因。

  2. 鉴于final 关键字不是方法签名的一部分,是否有另一种方法可以使抽象方法中的参数不可赋值?

其他研究:

  • 这个SO question 涉及相同的问题,但我的两个问题都没有。事实上,第二个问题是明确提出的,但没有得到答案。

  • 关于最终关键字的大量问题/博客等请参阅"the final word"。但是,关于这个问题,相关评论如下(虽然有用,但并没有解决我的两个问题):

请注意,最终参数不被视为方法签名的一部分,并且在解析方法调用时会被编译器忽略。参数可以声明为 final(或不声明),而不影响方法的覆盖方式。

【问题讨论】:

  • 但是即使一个方法重新分配了传递给它的变量,它对调用者没有任何影响,因为对象引用是按值传递的。如果您通过修改对象的状态来更改对象,事情会变得更加糟糕。
  • 您到底想完成什么?不变性?
  • @ErikPragt-修正了关于动机的问题。

标签: java abstract final


【解决方案1】:

我有一个带有抽象方法的抽象类,我希望参数是最终的 - 也就是说,我不想让抽象类和方法的实现重新分配参数。

为什么不呢?这是一个实现细节。调用代码无法观察到它,因此抽象方法没有理由指定它。这就是为什么它也不是方法签名的一部分 - 就像 synchronized 不是一样。

方法应该实现其记录在案的契约 - 但它如何选择这样做取决于它。由于 Java 总是使用按值传递,因此合约不能说明参数的最终确定性。

【讨论】:

  • 好的,谢谢 - 这说明了为什么它不是签名的一部分。我已经根据我的动机编辑了我的问题,但我希望我能做的最好的事情就是在文档中指出预期的实现。
  • @amaidment:我认为你没有抓住重点——为什么有人会关心方法实现是否改变了参数的值?这对外界完全隐藏。您说“不应重新分配这些变量”-您为什么关心该方法的实现方式?如果一个实现在重新分配参数时恰好更干净,你为什么要阻止这种情况?
  • 这些问题很好,很有帮助……我意识到,所有这些问题的答案都是“我不应该”。
  • @amaidment:非常好:)
  • "Java 总是使用按值传递",如果你接受对象,传递的是一个指向对象的指针(你不必做任何魔法使用) .
【解决方案2】:

参数是按值传递的,如果你使用某个变量调用方法,即使你在方法内部重新分配参数,这个变量也不会被修改,这就是为什么它对final没有意义成为合同的一部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 2017-10-28
    相关资源
    最近更新 更多