Окончательный статический метод экзамен

Я изучал для своего курса по разработке программного обеспечения и наткнулся на вопрос из примера:

"Почему нет смысла иметь как статические, так и окончательные модификаторы перед методом Java?"

У меня было немного исследований, и везде я говорю, что это не плохая практика, и есть веские причины для этого - например, этот вопрос о stackoverflow: Неплохо ли объявлять окончательный статический метод?

Итак, этот вопрос сам по себе бессмыслен или есть законный ответ на этот вопрос?

(Нет данных решений для этой типовой статьи)

Ответ 1

static методы не могут быть переопределены, поскольку они связаны не с экземпляром класса, а с самим классом. Например, так вы обычно называете метод static:

  MyClass.myStaticMethod()

И вот как вы вызываете метод экземпляра:

  new MyClass().myInstanceMethod()
Модификатор

final используется с методами, запрещающими их переопределение в расширяющих классах.

Ответ 2

Потому что метод static не может быть переопределен. Поэтому нет смысла отмечать его final.

Обратите внимание, что static final переменные (которые, как ни странно, поэтому НЕ переменные, потому что они не могут измениться) очень полезны, потому что их значения могут быть встроены компилятором.

Ответ 3

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

Ответ 4

Из Java Language Spec:

Метод класса всегда вызывается без ссылки на конкретный объект. Ошибка компиляции, чтобы попытаться ссылаться на текущий объект, используя ключевое слово this или ключевое слово super.

Таким образом, вы не можете переопределить статический метод, потому что он не принадлежит экземпляру. Таким образом, ключевые слова this и super недоступны, и вы не можете использовать вызов виртуального метода. И если вы не можете использовать вызов виртуального метода, последнее ключевое слово бесполезно.

Мне нравится думать, что компилятор видит объявления методов следующим образом:

public class SomeClass{

    // public static classMethod() becomes
    public static [final] void classMethod(){
        //...
    }

    // and public void instanceMethod() becomes
    public void instanceMethod(SomeClass this, Object super){
        //....
    }

}

public class SomeOtherClass extends SomeClass{

    // overrides
    @Override
    public void instanceMethod(SomeOtherClass this, SomeClass super){
        //...
    }
}

И вы вызываете SomeClass instance = new SomeOtherClass().instanceMethod();, затем его вызываете instanceMethod() из SomeOtherClass.

Поэтому компилятору не нужно копировать методы bodys и просто передавать ссылку на текущий объект в потоке. Таким образом, когда вы используете вызов виртуального метода, на самом деле вы вызываете instanceMethod со ссылкой на текущий объект (this), и метод body текущего класса - это то, что вызывается.