Почему статический метод переопределяется в следующем примере? [Дубликат]

11
задан Mr_and_Mrs_D 29 September 2013 в 15:04
поделиться

7 ответов

Вызов статических методов разрешается во время компиляции (без динамической отправки).

class main {
    public static void main(String args[]) {
            A a = new B();
            B b = new B();
            a.foo();
            b.foo();
            a.callMe();
            b.callMe();
    }
}
abstract class A {
    public static void foo() {
        System.out.println("I am superclass");
    }

    public void callMe() {
        foo(); //no late binding here; always calls A.foo()
    }
}

class B extends A {
    public static void foo() {
        System.out.println("I am subclass");
    }
}

дает

I am superclass
I am subclass
I am superclass
I am superclass
18
ответ дан Artefacto 17 August 2018 в 19:13
поделиться
  • 1
    Я передумал и написал «динамическую отправку», поскольку это общая концепция. – Artefacto 14 May 2010 в 05:56
  • 2
    Вы вообще не используете callMe () ... – RCIX 14 May 2010 в 07:10
  • 3
    Правильными терминами являются «суперкласс». и "подкласс", а не "базовый класс" и "дочерний класс". – Jesper 14 May 2010 в 09:25
  • 4
    Я только что скопировал вопрос MartinDenny2069. Я изменил сообщение, чтобы отразить ваши предложения. – Artefacto 14 May 2010 в 14:30

В Java статические поиски методов определяются во время компиляции и не могут адаптироваться к подклассам, которые загружаются после компиляции.

4
ответ дан Chris Ballance 17 August 2018 в 19:13
поделиться

Нет. Это невозможно.

Некоторые аналогичные (не то же) вопросы здесь и здесь .

0
ответ дан Community 17 August 2018 в 19:13
поделиться

В двух словах статический метод переопределения не является полиморфизмом, он «скрывает метод». Когда вы переопределяете статический метод, у вас не будет доступа к методу базового класса, поскольку он будет скрыт производным классом. Использование super () приведет к ошибке времени компиляции.

0
ответ дан Koushik Balaji Venkatesan 17 August 2018 в 19:13
поделиться

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

A.foo();

или

 A a = new A();
 a.foo();
0
ответ дан Phani 17 August 2018 в 19:13
поделиться

Can I override a static method?

Многие слышали, что вы не можете переопределить статический метод. Это правда - вы не можете. Однако можно написать такой код:

class Foo {
    public static void method() {
        System.out.println("in Foo");
    }
}

class Bar extends Foo {
    public static void method() {
        System.out.println("in Bar");
    }
}

Это компилируется и выполняется просто отлично. Разве это не пример статического метода, который переопределяет другой статический метод? Ответ - нет - это пример статического метода, скрывающего другой статический метод. Если вы попытаетесь переопределить статический метод, компилятор фактически не остановит вас - он просто не делает то, что вы думаете.

Итак, какая разница?

Коротко , когда вы переопределяете метод, вы все равно получаете преимущества полиморфизма во время выполнения, а когда вы скрываете, вы этого не делаете. Так что это значит? Взгляните на этот код:

class Foo {
    public static void classMethod() {
        System.out.println("classMethod() in Foo");
    }

    public void instanceMethod() {
        System.out.println("instanceMethod() in Foo");
    }
}

class Bar extends Foo {
    public static void classMethod() {
        System.out.println("classMethod() in Bar");
    }

    public void instanceMethod() {
        System.out.println("instanceMethod() in Bar");
    }
}

class Test {
    public static void main(String[] args) {
        Foo f = new Bar();
        f.instanceMethod();
        f.classMethod();
    }
}

Если вы запустите это, выход будет

instanceMethod () в Bar classMethod () в Foo

Почему мы получаем instanceMethod из Bar, но classMethod () из Foo? Разве мы не используем один и тот же экземпляр f для доступа к ним обоих?

Поскольку instanceMethod () - это (барабан, пожалуйста, ...) метод экземпляра, в котором Bar отменяет метод от Foo во время выполнения JVM использует фактический класс экземпляра f для определения того, какой метод запускать. Хотя f был объявлен как Foo, фактический экземпляр, который мы создали, был новым Bar (). Таким образом, во время выполнения JVM обнаруживает, что f является экземпляром Bar, и поэтому он вызывает instanceMethod () в Bar, а не в Foo. Так Java обычно работает, например, методами.

Однако с классомMethod (). поскольку (гм) это метод класса, компилятор и JVM не ожидают, что для вызова метода будет задействован фактический экземпляр. И даже если вы предоставите один (который мы сделали: экземпляр, упомянутый f), JVM никогда не будет смотреть на него. Компилятор будет рассматривать только объявленный тип ссылки и использовать этот объявленный тип для определения во время компиляции метода для вызова. Поскольку f объявлен как тип Foo, компилятор просматривает f.classMethod () и решает, что это означает Foo.classMethod. Не имеет значения, что экземпляр, присвоенный f, фактически является баром - для статических методов компилятор использует только объявленный тип ссылки. Это то, что мы имеем в виду, когда мы говорим, что статический метод не имеет полиморфизма во время выполнения.

Поскольку методы экземпляров и методы класса имеют это важное различие в поведении, мы используем разные термины - «переопределение», например, методов и «скрывать» для методов класса - различать эти два случая. И когда мы говорим, что вы не можете переопределить статический метод, это означает, что даже если вы пишете код, который выглядит как переопределяющий статический метод (например, первый Foo и Bar в верхней части этой страницы) - это не будет ведут себя как переопределенный метод. для более ссылки это

25
ответ дан Rupesh Yadav 17 August 2018 в 19:13
поделиться

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

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

1
ответ дан Ukko 17 August 2018 в 19:13
поделиться
Другие вопросы по тегам:

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