Почему вызов не является статическим методом посредством экземпляра ошибка для компилятора Java?

String text = errors.toString().replace("[", "").replace("]", "");//remove brackets([) convert it to string
75
задан tmtest 5 March 2009 в 13:59
поделиться

11 ответов

В основном я полагаю, что разработчики 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 полностью проигнорировано.

78
ответ дан Jon Skeet 7 November 2019 в 07:23
поделиться

Почему это должна быть ошибка? Экземпляр имеет доступ ко всем статическим методам. Статические методы не могут измениться, состояние экземпляра (пробующий к ошибка компиляции).

проблема с известным примером, который Вы даете, очень характерна для потоки , не вызовы статического метода. Выглядит, как будто Вы добираетесь activeCount() для потока, упомянутого thread, но Вы действительно получаете счет для вызывающего потока. Это - логическая ошибка, которую Вы как программист совершаете. Издание предупреждения является соответствующей вещью для компилятора, чтобы сделать в этом случае. Вам решать учесть предупреждение и зафиксировать Ваш код.

РЕДАКТИРОВАНИЕ: Я понимаю, что синтаксис языка - то, что разрешение Вы, чтобы написать вводящий в заблуждение код, но помнить, что компилятор и его предупреждения являются частью языка также. Язык позволяет Вам делать что-то, что компилятор считает сомнительным, но он дает Вам предупреждение удостовериться, что Вы знаете, что он мог вызвать проблемы.

13
ответ дан Bill the Lizard 7 November 2019 в 07:23
поделиться

Они не могут сделать это ошибкой больше из-за всего кода, который уже является там.

я с Вами, на которых это должна быть ошибка. Возможно, должна быть опция/профиль для компилятора для обновления некоторых предупреждений ошибкам.

Обновление: , Когда они представили эти , утверждают ключевое слово в 1,4, который имеет подобные потенциальные проблемы совместимости со старым кодом, они сделали его доступным, только если Вы явно устанавливаете исходный режим на "1,4" . Я предполагаю, что можно было сделать это ошибкой в новом исходном режиме "java 7". Но я сомневаюсь, что они сделали бы это, полагая, что вся стычка это вызовет. Как другие указали, не строго необходимо препятствовать тому, чтобы Вы писали запутывающий код. И изменения языка в Java должны быть ограничены строго необходимым в этой точке.

9
ответ дан Thilo 7 November 2019 в 07:23
поделиться

Короткий ответ - язык позволяет его, таким образом, не ошибка.

6
ответ дан PaulJWilliams 7 November 2019 в 07:23
поделиться

Вероятно, для того же, логичного, который делает это не ошибкой:

public class X
{
    public static void foo()
    {
    }

    public void bar()
    {
        foo(); // no need to do X.foo();
    }
}
2
ответ дан TofuBeer 7 November 2019 в 07:23
поделиться

Действительно важная вещь, с точки зрения компилятора, состоит в том, что она в состоянии разрешить символы. В случае статического метода это должно знать, какой класс заглянуть для него - так как это не связано ни с каким конкретным объектом. Разработчики Java, очевидно, решили, что, так как они могли определить класс объекта, они могли также разрешить класс любого статического метода для того объекта от любого экземпляра объекта. Они принимают решение позволить этому - поколебленный, возможно, наблюдением @TofuBeer - давать программисту некоторое удобство. Другие разработчики языка сделали различный выбор. Я, вероятно, попал бы в последний лагерь, но дело не в этом большой из соглашения мне. Я, вероятно, позволил бы использование, которое упоминает @TofuBeer, но позволявший его моя позиция по не предоставлению доступа от переменной экземпляра менее надежна.

2
ответ дан tvanfosson 7 November 2019 в 07:23
поделиться

Это не ошибка, потому что это - часть спецификации, но Вы, очевидно, спрашиваете об объяснении, которое мы можем все предположить.

Мое предположение - то, что источник этого должен на самом деле позволить методу в классе вызывать статический метод в том же классе без стычки. Начиная с вызова x () законно (даже без сам имя класса), звонить this.x () должно быть законным также, и поэтому звонящий через любой объект был сделан законным также.

Это также помогает поощрить пользователей поворачивать закрытые функции в помехи, если они не изменяют состояние.

Кроме того, компиляторы обычно стараются не объявлять ошибки, когда нет никакого способа, которым это могло привести к прямой ошибке. Так как статический метод не изменяет состояние или заботу об объекте вызова, это не заставляет фактическую ошибку (просто беспорядок) позволять это. Предупреждение достаточно.

2
ответ дан Uri 7 November 2019 в 07:23
поделиться

Цель ссылки переменной экземпляра только для предоставления типа, который включает помехи. Если Вы смотрите на код байта, вызывающий помехи через instance.staticMethod, или EnclosingClass.staticMethod производит то же, вызывают байт-код статического метода. Никакая ссылка на экземпляр не появляется.

ответ как также, почему это там, хорошо это просто. Пока Вы используете класс. а не через экземпляр Вы поможете избежать беспорядка в будущем.

2
ответ дан mP. 7 November 2019 в 07:23
поделиться

Вероятно, можно изменить его в IDE (в Предпочтениях Eclipse-> Java-> Компилятор-> Ошибки/Предупреждения)

1
ответ дан Dutow 7 November 2019 в 07:23
поделиться

Я просто рассматриваю это:

instanceVar.staticMethod();

, чтобы быть сокращением от этого:

instanceVar.getClass().staticMethod();

, Если всегда необходимо было делать это:

SomeClass.staticMethod();

тогда Вы не были бы в состоянии усилить наследование для статических методов.

таким образом, путем вызова статического метода через экземпляр Вы не должны знать, какой реальный класс экземпляр во время компиляции, только что он реализует staticMethod () где-нибудь вдоль цепочки наследования.

РЕДАКТИРОВАНИЕ: Этот ответ является неправильным. См. комментарии для деталей.

-9
ответ дан 2 revs 7 November 2019 в 07:23
поделиться

Нет опции для него. В Java (как многие другой Ленг.) у Вас может быть доступ ко всем статическим членам класса через его имя класса или объект экземпляра того класса. Это было бы ваше дело и Ваш случай и программный продукт, какой необходимо использовать, который дает Вам больше удобочитаемости.

0
ответ дан Pooria 7 November 2019 в 07:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: