1. ホーム
  2. java

インスタンスを経由して静的メソッドを呼び出すと、Javaコンパイラのエラーにならないのはなぜですか?

2023-07-22 07:29:50

質問

皆さんは私が言っている動作がわかると思いますが、次のようなコードです。

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

はコンパイラの警告を引き起こします。 なぜエラーにならないのでしょうか?

EDITです。

明確には、質問はスレッドとは関係ありません。 スレッドで物事を本当に混乱させる可能性があるため、これを議論するときにスレッドの例がしばしば示されることは承知しています。 しかし、本当に問題なのは、そのような使い方が 常に であり、そのような呼び出しを書いてそれを意味することは(有能な)できません。 この種のメソッド呼び出しのどんな例も、ばかげたものでしょう。 ここに別のものがあります。

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

これは、各Stringインスタンスが"String valueOf(int i)"メソッドを持っているように見せかけます。

どのように解決するのですか?

基本的に、私は、Java の設計者が言語を設計したときに間違いを犯したと信じています。はい、それは非常に誤解を招くコードにつながる可能性があります。はい、避けるべきでしょう。IDEがこれをエラーとして扱うように設定されていることを確認する必要があります。自分で言語を設計することがあれば、避けるべきものの例として心に留めておいてください :)

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 は完全に無視されます。