Как я могу вызвать метод для нулевого объекта? - PullRequest
10 голосов
/ 21 декабря 2011
public class JavaPuzzler {

    public static void main(String[] args) {
    JavaPuzzler javaPuzzler = null;
    System.out.println(javaPuzzler.get());
    }

    private static String get(){
        return "i am a java puzzler";
    }
}

Вы можете подумать, что он должен выдавать исключение NullPointerException, потому что основной метод вызывает метод get () для локальной переменной, которая инициализируется до нуля , и вы не можете вызвать метод для нуля.

Но если вы запустите эту программу, вы увидите, что она печатает «Я - головоломка Java».

Может кто-нибудь дать мне ответ. Заранее спасибо.

Ответы [ 9 ]

6 голосов
/ 21 декабря 2011

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

public static String get() // belongs globally to class, no instance required
public String get() // belongs to instance
4 голосов
/ 21 декабря 2011

Это потому, что метод является статическим, и хотя вы ссылаетесь на экземпляр, экземпляр не является необходимым.Спецификация языка Java объясняет, почему в разделе 8.4.3.2 :

Метод, объявленный статическим, называется методом класса.Метод класса всегда вызывается без ссылки на конкретный объект.

Это означает, что не имеет значения, является ли javaPuzzler экземпляр нулевым - метод «принадлежит» классу, а не экземпляру.

3 голосов
/ 21 декабря 2011

Метод get является статическим, что означает, что фактическая ссылка в javaPuzzler игнорируется в этом вызове, используется только тип переменной.

1 голос
/ 21 декабря 2011

Как все упоминают здесь, это работает, потому что get() - статический метод. Вот способ, которым вы можете думать об этом:

Когда вы определяете класс в Java, вы по сути дела определяете данные, которые будет содержать объект, и набор методов, которые работают с этими данными. Теперь, когда вы можете иметь тысячи и тысячи объектов, не имеет смысла иметь копии всех методов для каждого из них. В результате класс сохраняет методы, которые вы определили, и выполняет их в scope объекта, для которого вы вызываете метод. Если вы попытаетесь вызвать эти методы для неинициализированного объекта, объект все еще существует, а метод все еще существует, но у него нет действительной области действия для работы, что дает вам NullPointerException.

Исключением из этого правила являются статические методы, которые не требуют области видимости - они не ссылаются на данные, специфичные для объекта. Вот почему они могут работать независимо от того, инициализирован объект или нет.

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

1 голос
/ 21 декабря 2011

Если мы попытаемся вызвать метод с использованием объекта NULL, он выдаст NullPointerException, если метод не является статическим.

Если метод статический, он будет работать.

Читать ЗДЕСЬ для получения дополнительной справки

1 голос
/ 21 декабря 2011

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

1 голос
/ 21 декабря 2011

Ваш метод статичен. Так что он может быть вызван только статически.

Таким образом, даже если вы указываете его как javaPuzzler.get (), фактическим вызовом будет JavaPuzzler.get () и, следовательно, печать !!

0 голосов
/ 15 мая 2013

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

Поскольку static, JavaPuzzler.get ());выдаст вывод, а не исключение нулевого указателя.

Было бы выдано исключение нулевого указателя в случае, если метод get () был бы нестатическим.

0 голосов
/ 21 декабря 2011

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

...
 public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 8 L0
    ACONST_NULL
    ASTORE 1
   L1
    LINENUMBER 9 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    INVOKESTATIC JavaPuzzler.get()Ljava/lang/String;
    INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
   L2
    LINENUMBER 11 L2
    RETURN
   L3
    LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
    LOCALVARIABLE javaPuzzler LJavaPuzzler; L1 L3 1
    MAXSTACK = 2
    MAXLOCALS = 2
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...