Подтвердить что ты не робот

Если статические методы не могут быть переопределены, как это работает здесь (для Java)?

Я понял, что статические переменные и статические методы относятся к классу, а не к объектам класса. Поэтому Override статического метода не будет работать в Java, так как для переопределения нам нужен экземпляр класса, который будет создан. Но сегодня я что-то пробовал, что противоречило моим знаниям Java.

Пожалуйста, следуйте этому коду:

class Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{    
   public static void doIt(){
      System.out.println("In static method 'doit' of class Child ");
   }
}

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

Результат реализации выше:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Child

Из этого вывода я могу понять, что, хотя класс Child расширяет класс Parent, методы doit являются индивидуальными для каждого класса, так как они static. Поэтому не допускается их переопределение.

Теперь, пожалуйста, следуйте приведенному ниже коду, где @Override добавляется к методу child doit:

class Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{    
   @Override // Adding this annotation here
   public static void doIt(){
      System.out.println("In static method 'doit' of class Child ");
   }
}

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

Результат приведенного выше кода дает ошибку компиляции следующим образом:

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:31: error: method does not override or implement a method from a supertype
    @Override
    ^
1 error

Здесь ясно сказано, что аннотация Override не может применяться в методах static, поскольку они не становятся переопределенными.

Теперь, пожалуйста, следуйте приведенному ниже коду, где Child не имеет метода doit:

class Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{ /* no doIt method */ }

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

Вывод:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Parent

Почему этот код компилируется и запускается? Я ожидал ошибку компиляции для метода doit для класса Child, и я ожидал, что "Метод не найден". Я не понимаю.

Также следуйте приведенному ниже коду. Здесь метод doit в Parent теперь final.

class Parent{
   public static final void doIt(){ // now final
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

Выход после запуска вышеуказанного кода выглядит следующим образом:

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:30: error: doIt() in Child cannot override doIt() in Parent
    public static void doIt(){
                       ^
  overridden method is static,final
 1 error

 D:\Rahul Shivsharan\MyPractise\JAVA>

Я ожидал, что вышеприведенный код должен работать нормально, поскольку методы doit являются статичными в каждом классе, поэтому даже ключевое слово final не должно компилировать ошибку, поскольку метод static.

Пожалуйста, объясните мне, как метод переопределяет работу в статических классах на Java.

  • Можно ли переопределить статические методы? Если да, то как закончится аннотация @Override?
  • Если статические методы не могут быть переопределены, тогда как мой третий блок кода работает нормально?
  • Если статические методы не могут быть переопределены, то почему ключевое слово final имеет значение?
4b9b3361

Ответ 1

Прежде всего, здесь задействованы различные механизмы: Переопределение и тени (также называемое скрытием).

1) Статические методы не могут быть переопределены, поскольку они привязаны к классу, в котором они определены. Однако вы можете shadow/hide статический метод, как вы это делаете, с классом Parent/Child. Это означает, что метод заменяется в классе Child, но по-прежнему доступен из класса Parent.

Более очевидно, что вы не переопределяете, когда вызываете статические методы из экземпляров этих классов (и не используете вызов Class.staticMethod()).

Parent parent = new Parent();
Child child1 = new Child();
Parent child2 = new Child();

parent.StaticMethod();
child1.StaticMethod();
child2.StaticMethod();

вывод

Static method from Parent
Static method from Child
Static method from Parent

Ответ - это отправка методов. Здесь вы можете взять исходный код

2) Отправка находит метод в классе Parent. Динамической отправки нет, так как тип runtime используется для поиска дескриптора метода. Он использует тип времени компиляции. Напомним: вызов статических методов из экземпляров считается плохой практикой, поскольку такие вещи, как описано выше, могут быть пропущены.

3) С помощью final вы заявляете, что метод не может быть переопределен и не скрыт/скрыт.

Ответ 3

Хотя в одном сообщении не рекомендуется задавать 3 вопроса, я все еще готов ответить на них.

  • Статические методы не могут быть переопределены, потому что нет смысла делать это. В вашем случае, если вы хотите переопределить статический метод, вы можете просто вызвать этот метод и добавить его после этого или просто создать другой метод.

  • Итак, теперь вы знаете, что статические методы нельзя переопределить. Но вы спрашиваете, почему работает третий код? Третий код - это код с

    Открытый класс Child extends Parent {}

правильно? Хотя статические методы нельзя переопределить, их можно унаследовать. То, что вы делаете, наследует Parent, так что это нормально!

  1. Теперь позвольте мне сказать вам, что в первом примере кода вы скрываете метод в классе Parent, а не переопределяете. Вот почему вы получаете результат. Ключевое слово final означает, что метод может никогда не меняться, даже не скрываться. Поэтому почему.