Путаница с уровнем класса и уровнем экземпляра - PullRequest
3 голосов
/ 18 февраля 2010

У меня есть следующий класс:

public class B {

    public void print() {
    }

    public static void main(String[] args) {
        B B = new B();
        B.print();
    }

}

Мне было интересно, почему компилятор не выдал ошибку, говоря, что это не статический метод.Как он будет различать уровень класса и уровень экземпляра, когда у нас будет объект с тем же классом?

Ответы [ 5 ]

5 голосов
/ 18 февраля 2010

Поскольку вы обращаетесь к методу в экземпляре класса. Кстати, имя экземпляра совпадает с именем класса, но поскольку у вас нет статического метода с этим именем, компилятор принимает правильный - то есть метод экземпляра.

Если вы определите метод как static, тогда он снова примет единственно возможную вещь - вызов метода static для класса B, потому что экземпляр не имеет такого метода.

И, в конечном итоге, вы не можете иметь как static, так и не static метод с одинаковым именем.

3 голосов
/ 18 февраля 2010

JLS обсуждает и определяет приоритет правил определения области действия для таких случаев:

6.3.2 Скрытые декларации

Простое имя может встречаться в тех случаях, когда оно потенциально может быть истолковано как имя переменной, типа или пакет. В этих ситуациях правила §6.5 определяют, что переменная будет выбран в предпочтении введите , и этот тип будет выбран в предпочтении к пакету. Таким образом, это это иногда может быть невозможно обратитесь к видимому типу или упаковке объявление через его простое имя. Мы сказать, что такое заявление затемняется.

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

class Test {
        static int x = 1;
        public static void main(String[] args) {
                int x = 0;
                System.out.print("x=" + x);
                System.out.println(", Test.x=" + Test.x);
        }
}

Опять же, компилятор следует JLS и разрешает имя в соответствии со спецификацией. Компилятор не умный и ничего не "вычисляет", он просто следует спецификации.

2 голосов
/ 18 февраля 2010

Ваш вопрос о методе print ()? Это работает, потому что имя вашей переменной «скрывает» имя типа, поэтому, когда вы делаете B.print (), он смотрит на переменную B, которая является экземпляром класса B.

Вы действительно не должны называть вашу переменную тем же именем, что и класс, по крайней мере, не в том же регистре. Для вас все будет яснее, если вы переименуете переменную, даже если просто "b". Итак:

public class B{

  public void print(){

  }

  public static void main(String[] args){

    B b = new B();

    b.print(); // This works
    B.print(); // this fails

  }

}
0 голосов
/ 18 февраля 2010

Я предполагаю, что имена классов и переменные экземпляров не разделяют одно и то же пространство имен; компилятору ясно, что B.print() вызывается в экземпляре, а не в классе.

Нет необходимости говорить, что это сбивает с толку, и его следует избегать в реальном коде;)

0 голосов
/ 18 февраля 2010

Потому что в этом примере print() является методом экземпляра. Он вызывается из экземпляра класса B. Если ваш main выглядел так:

public static void main(String[] args){
       print():
       }

тогда print() должен быть статическим методом.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...