Как я могу вызвать метод для объекта null?

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, потому что метод main вызывает метод get () на локальная переменная, которая инициализируется значение null, и вы не можете вызвать метод на null.

но если вы запустите эту программу, вы увидите, что она печатает "я Java puzzler".

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

9 ответов


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

public static String get() // belongs globally to class, no instance required
public String get() // belongs to instance

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

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

это означает, что не имеет значения, если javaPuzzler экземпляр имеет значение null-метод "принадлежит" классу, а не пример.


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


ваш метод статичен. Поэтому его можно было назвать только статическим способом.

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


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


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

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

читать здесь дополнительные ссылки


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

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

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

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


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

...
 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
...

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

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

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