2015-04-28 10 views
6

У меня есть следующие 2 класса:Что означает назначение объекта Java?

class Animal { 
    public static void staticMethod(int i) { 
     System.out.println("Animal : static -- " + i); 
    } 

    public void instanceMethod(int i) { 
     System.out.println("Animal : instance -- " + i); 
    } 
} 

class Cat extends Animal { 
    public static void staticMethod(int i) { 
     System.out.println("Cat : static -- " + i); 
    } 

    public void instanceMethod(int i) { 
     System.out.println("Cat : instance -- " + i); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.staticMethod(1);      // Cat : static -- 1 
     myCat.instanceMethod(2);      // Cat : instance -- 2 
     System.out.println(""); 

     Animal myAnimal = myCat; 
     Animal.staticMethod(3);      // Animal : static -- 3 
     myAnimal.staticMethod(4);     // Animal : static -- 4 [ ? ] 
     System.out.println(""); 

     myAnimal.instanceMethod(5);     // Cat : instance -- 5 
    } 
} 

И когда я бегу Cat, я получил следующие результаты:

Cat : static -- 1 
Cat : instance -- 2 

Animal : static -- 3 
Animal : static -- 4 

Cat : instance -- 5 

Я могу понять, 1,2,3 и 5, но почему # 4 не является: «Кошка: статическая - 4»? Мое понимание было бы так:

myAnimal = myCat означает «myAnimal» теперь точно так же, как «myCat», так что в любом месте «myAnimal» apears, вы можете заменить его на «myCat» и получить тот же результат, потому что все внутри myAnimal такое же, как и все внутри myCat, поэтому «myAnimal.staticMethod (4)» должен быть таким же, как «myCat.staticMethod (4)», а вывод должен быть: «Cat: static - 4», аналогичный на «myCat.staticMethod (1)» выше.

Но это, похоже, не так, почему?

+0

Вот затмение, говорящее мне: «Статический метод staticMethod (int) из типа« Animal »должен быть доступен статическим образом», поскольку он является статическим методом, тогда он ограничен только родительскому объекту, когда вы вызываете его obj, который это «Животное». –

+0

Статика связана во время компиляции. Это то, что мешает им переоценить – njzk2

+0

Его дублирующий вопрос, заданный во много раз – madz

ответ

2

От Oracle docs:

8.4.8.2. Скрытие (методы класса)

Если класс С объявляет или наследует статический метод м, то м называются шкуры любого метод м», где подпись М является подсигнатурой (§8.4.2) сигнатуры m ', в суперклассах и суперинтерфейсы C, которые в противном случае были бы доступны для кода в C.

Пример 8.4.8.2-1. Вызов методов скрытого класса

Скрытый класс (статический) метод может быть вызван с помощью ссылки , тип которой является классом, который фактически содержит объявление метода . В этом отношении скрытие статических методов отличается от переопределения методов экземпляра.Пример:

class Super { 
      static String greeting() { return "Goodnight"; } 
      String name() { return "Richard"; } 
     } 
     class Sub extends Super { 
      static String greeting() { return "Hello"; } 
      String name() { return "Dick"; } 
     } 
     class Test { 
      public static void main(String[] args) { 
       Super s = new Sub(); 
       System.out.println(s.greeting() + ", " + s.name()); 
      } 
     } 

производит выход:

ночь, Дик

, потому что вызов приветствия использует тип S, а именно супер, , чтобы выяснить, во время компиляции время, метод класса которого вызывается, тогда как вызов имени использует класс s, а именно Sub, для определения, во время выполнения, для которого используется метод экземпляра.

2

Причина в том, что Java разрешает статические методы, основанные на типе самой ссылочной переменной, а не полиморфно во время выполнения, как это происходит с методами экземпляра.

Чтобы развернуть немного, когда вы делаете Animal myAnimal = myCat, вы назначаете ссылку Cat на ссылку Animal. Это приемлемо, потому что Cat также является Animal, поэтому все, что может сделать Animal, может также сделать Cat.

Кроме того, если вы звоните экземпляр (то есть, не статический) метод с помощью myAnimal ссылки, а также метод переопределен в Cat, то версия методы Cat называется, потому что именно поэтому этот метод был переопределен в первое место. С другой стороны, статические методы никогда не преувеличиваются. Вот почему они «статичны», как в «нединамическом». Это означает, что статические методы могут быть разрешены компилятором вместо того, чтобы полагаться на среду выполнения.

3

Вы объявляете myAnimal как Animal. Поэтому из этого класса вызывается статический метод.

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

1

Статический означает именно это: вызов разрешен статический (в вашем случае она будет решена на основе объявленного типа переменной и переменное время компиляции объект).

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

1

Когда вы устанавливаете myAnimal = myCat, указатель myAnimal указывает на объект cat, но когда вы пытаетесь получить доступ к статическому методу с помощью указателя myAnimal, он обращается к статическому методу из класса, объявленного myAnimal.

Смежные вопросы