声明最终的静态方法是否是一个坏主意?

2022-09-01 02:22:59

我理解,在此代码中:

class Foo {
    public static void method() {
        System.out.println("in Foo");
    }
} 

class Bar extends Foo {
    public static void method() {
        System.out.println("in Bar");
    }
}

..中的静态方法“隐藏”中声明的静态方法,而不是在多态性意义上重写它。BarFoo

class Test {
    public static void main(String[] args) {
        Foo.method();
        Bar.method();
    }
}

...将输出:

(福
因巴尔)

重新定义 如 in 将禁用 隐藏它的功能,重新运行将输出:method()finalFooBarmain()

(福
因福)

编辑:当您将方法标记为最终版本时,编译失败,并且仅在我删除Bar.method()时再次运行)

如果静态方法阻止子类有意或无意地重新定义方法,那么将静态方法声明为 是否被视为不好的做法?final

(这是对使用行为的一个很好的解释..)final


答案 1

我不认为将方法标记为 .staticfinal

正如您发现的那样,将防止该方法被子类隐藏,这是非常好的消息。final

我对你的说法感到非常惊讶:

在 Foo 中将 method() 重新定义为 final 将禁用 Bar 隐藏它的功能,重新运行 main() 将输出:

(福
因福)

否,将方法标记为 in 将阻止编译。至少在Eclipse中,我得到了:finalFooBar

线程“main” java.lang.错误中的异常:未解决的编译问题:无法覆盖 Foo 中的最终方法

另外,我认为人们应该总是调用方法,即使在类本身中也用类名来限定它们:static

class Foo
{
  private static final void foo()
  {
    System.out.println("hollywood!");
  }

  public Foo()
  {
    foo();      // both compile
    Foo.foo();  // but I prefer this one
  }
}

答案 2

静态方法是Java最令人困惑的功能之一。最佳实践可以解决此问题,而制作所有静态方法是这些最佳实践之一!final

静态方法的问题在于

  • 它们不是类方法,而是以类名为前缀的全局函数
  • 奇怪的是,它们被“继承”到子类
  • 令人惊讶的是,它们不能被覆盖而是被隐藏
  • 完全可以将它们作为接收器调用的实例是完全破碎的

因此,您应该

  • 始终以他们的类作为接收者调用它们
  • 始终仅使用声明类作为接收方调用它们
  • 始终使它们(或声明类)final

你应该

  • 切勿使用实例作为接收方调用它们
  • 切勿使用声明类的子类作为接收方调用它们
  • 永远不要在子类中重新定义它们

 

注意:程序的第二个版本应该无法通过编译错误。我猜想你的IDE正在向你隐瞒这个事实!


推荐