当前位置:  开发笔记 > 编程语言 > 正文

为什么不通过实例调用静态方法为Java编译器的错误?

如何解决《为什么不通过实例调用静态方法为Java编译器的错误?》经验,为你挑选了4个好方法。

我相信你们都知道我的意思 - 代码如下:

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

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

编辑:

要明确:问题与Threads无关.我意识到在讨论这个问题时经常给出Thread示例,因为它们可能真的搞砸了它们.但问题确实是这样的使用总是无稽之谈,你不能(胜任地)写出这样的电话并且意味着它.这种类型的方法调用的任何例子都是barmy.这是另一个:

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

这使得它看起来好像每个String实例都带有"String valueOf(int i)"方法.



1> Jon Skeet..:

基本上我认为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完全被忽略.


@Jon:我进行了类似的测试并证实了你的发现.基于此,我同意Java允许从实例var调用静态方法是错误的.没有能力(正如我原先想的那样),但是混乱或错误的可能性增加了.

2> Bill the Liz..:

为什么会出错呢?该实例可以访问所有静态方法.静态方法不能改变实例的状态(努力一个编译错误).

您提供的众所周知的示例的问题非常特定于线程,而不是静态方法调用.它看起来好像你正在获取所activeCount()引用的线程thread,但你真的得到了调用线程的计数.这是程序员正在制作的逻辑错误.在这种情况下,编译器发出警告是适当的.由您来注意警告并修复您的代码.

编辑:我意识到语言的语法是允许你编写误导性代码的,但请记住,编译器及其警告也是语言的一部分.该语言允许您执行编译器认为可疑的操作,但它会向您发出警告,以确保您意识到它可能会导致问题.


它与*instance*无关.唯一的是变量的*声明类型*.对于语言设计师IMO来说,这是一个可怕的,可怕的错误和错误.
@Bill:这样说吧 - 如果Java*没有允许它,有人建议它*应该*允许它,你的反应是什么?你真的会赞成它吗?或者你会争辩(就像我一样)这是一个毫无意义的功能,不必要地允许误导代码?
我不买"编译时"的原因 - 很明显你是通过参考查找方法; 然后检查它是否静止需要多长时间?我认为将它视为语言设计错误更容易.

3> Thilo..:

它们不再是一个错误,因为已经存在的所有代码.

我和你在一起,这应该是一个错误.也许应该有一个选项/配置文件供编译器将某些警告升级为错误.

更新:当他们在1.4中引入assert关键字时,它与旧代码具有类似的潜在兼容性问题,只有在您明确将源模式设置为"1.4"时才使其可用.我想在新的源模式"java 7"中可能会出现错误.但我怀疑他们会这样做,考虑到它会造成的所有麻烦.正如其他人所指出的那样,并不是必须阻止您编写令人困惑的代码.Java的语言更改应限制在此时严格必要.



4> PaulJWilliam..:

简短的回答 - 语言允许它,所以它不是一个错误.

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有