一尘不染

为什么通过实例调用静态方法对于Java编译器来说不是错误?

java

我确定大家都知道我的意思-代码如下:

Thread thread = new Thread();
int activeCount = thread.activeCount();

引发编译器警告。为什么不是错误?

编辑:

需要明确的是:问题与线程无关。我意识到在讨论此问题时通常会给出线程示例,因为有可能将它们弄乱。但是,真正的问题在于,这种用法永远都是胡说八道,你不能(适当地)写这样的电话并表达自己的意思。这种方法调用的任何示例都是barmy。这是另一个:

String hello = "hello";
String number123AsString = hello.valueOf(123);

这使得每个String实例看起来都带有“ String valueOf(int i)”方法。


阅读 317

收藏
2020-03-01

共1个答案

一尘不染

基本上,我相信Java设计人员在设计语言时犯了一个错误,并且由于涉及到兼容性问题,现在修复它为时已晚。是的,它可能导致非常误导的代码。是的,你应该避免这种情况。是的,你应该确保将IDE配置为将其视为错误,IMO。如果你曾经亲自设计过一种语言,请记住它作为避免这种情况的示例:)

只是为了回应DJClayworth的观点,这是C#所允许的:

public class Foo
{
    public static void Bar()
    {
    }
}

public class Abc
{
    public void Test()
    {
        // Static methods in the same class and base classes
        // (and outer classes) are available, with no
        // qualification
        Def();

        // Static methods in other classes are available via
        // the class name
        Foo.Bar();

        Abc abc = new Abc();

        // This would *not* be legal. It being legal has no benefit,
        // and just allows misleading code
        // abc.Def();
    }

    public static void Def()
    {
    }
}

为什么我会误导我?因为如果我看一下代码,someVariable.SomeMethod()我希望它使用的值someVariable。如果SomeMethod()是静态方法,则该期望无效;代码欺骗了我。怎么能说有可能是一个很好的事情吗?

奇怪的是,Java不允许你使用可能未初始化的变量来调用静态方法,尽管事实上它将要使用的唯一信息是变量的声明类型。这是一个前后矛盾,毫无用处的混乱局面。为什么允许它?

编辑:此编辑是对Clayton答案的回应,声称它允许继承静态方法。没有。静态方法并不是多态的。这是一个简短但完整的程序,以证明这一点:

class Base
{
    static void foo()
    {
        System.out.println("Base.foo()");
    }
}

class Derived extends Base
{
    static void foo()
    {
        System.out.println("Derived.foo()");
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Base b = new Derived();
        b.foo(); // Prints "Base.foo()"
        b = null;
        b.foo(); // Still prints "Base.foo()"
    }
}

如你所见,的执行时间值b被完全忽略。

2020-03-01