2013-10-28 5 views
2
public class MyClassTest { 

    private static MyClass m; 

    public static void main(String[] args) { 
     m.initMe(getint()); 
    } 

    public static int getint() { 
     m = new MyClass(); 
     return (int) Math.random()*100; 
    } 

} 

class MyClass{ 

    int i; 

    void initMe(int i) { 
     this.i = i; 
     System.out.println(this.i); 
    } 

} 

Этот фрагмент кода дает NullPointerException, в результате чего initMe() вызывается перед getint вызывается. Какова будет основная причина этой проблемы? Является ли JAVA передачей по значению, поэтому эта ссылка не влияет.Java вызов метода заказа

Дайте мне правильную причину.

+0

main - это первый вызванный метод, инициализирующий m, перед вызовом initMe MyClass. – Batty

+0

@Batty да, вы правы, если я сначала вызываю 'getint', тогда код работает отлично ... Но я спрашиваю, что будет причиной, поэтому мой код дает мне исключение. – Mitesh

ответ

2

компилятор может генерировать то, что вы имеете в виду

  • выполнить c ода для каждого параметра
  • поместить результат в стек
  • вызова метода (m будет инициализирован)

Но Java specifications описать несколько шагов, которые необходимы перед вычислением параметров. JVM должен иметь возможность идентифицировать тип объекта (тип времени выполнения), прежде чем знать, как обрабатывать параметры.

Это байткод, который генерируется

public static void main(java.lang.String[]); 
    Code: 
    0: getstatic  #2     // Field m:LMyClass; 
    3: invokestatic #3     // Method getint:()I 
    6: invokevirtual #4     // Method MyClass.initMe:(I)V 
    9: return   

Как вы можете видеть, что первый шаг должен загрузить m в стеке. Он будет загружать нуль. Затем вызывается getint, он установит m, но значение, используемое invokevirtual, будет уже загружено в стек JVM.

0

main - это первый вызванный метод, инициализирующий m, перед вызовом initMe MyClass. Как

private static MyClass m = new MyClass(); 

Престола, m.initMe(getint()); вызывает initMe() на т, но не инициализируется м, поскольку это первая линия основного метода, так m = null, следовательно, исключение.

0

Без создания экземпляра MyClass вы использовали его метод initMe. Таким образом, так как объект не создается экземпляр, вы получаете это исключение Измените это:

private static MyClass m = new MyClass(); 
0

m.initMe(getint());

Когда m.initMe() называется, m это еще не инициализирована. Он инициализируется только в getint(). Поэтому вам нужно инициализировать свой m, прежде чем вы сможете использовать его, чтобы вызвать метод, используя его.

private static MyClass m = new MyClass(); // Declared and initialized 
public static void main(String[] args) { 
    m.initMe(getint()); // Thus, its safe here to call a method now 
} 
public static int getint() { 
    return (int) Math.random()*100; 
} 

или же вы можете инициализировать его как раз перед вызовом initMe(), а в методе main().

private static MyClass m; // Declared here 
public static void main(String[] args) { 
    m = new MyClass(); // initialized here 
    m.initMe(getint()); // Thus, its safe here to call a method now 
} 
public static int getint() { 
    return (int) Math.random()*100; 
} 
0

Сначала вы должны инициализировать «т»

private static MyClass m = new MyClass(); 

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

0

Вы создаете MyClassobject в getint() метода

public static int getint() { 
    m = new MyClass(); 
    return (int) Math.random()*100; 
    } 

Вам нужно создать MyClass object в main(String[] args) метод

public static void main(String[] args) { 
    m = new MyClass(); 
    m.initMe(getint()); 
} 
1

Как указан в

JLS section 15.12. Method Invocation Expressions

Выражение вызова метода используется для вызова метода класса или экземпляра.

MethodInvocation: 
    MethodName (ArgumentListopt) 
    Primary . NonWildTypeArgumentsopt Identifier (ArgumentListopt) 
    super . NonWildTypeArgumentsopt Identifier (ArgumentListopt) 
    ClassName . super . NonWildTypeArgumentsopt Identifier (ArgumentListopt) 
    TypeName . NonWildTypeArguments Identifier (ArgumentListopt) 

The definition of ArgumentList from §15.9 is repeated here for convenience: 


ArgumentList: 
    Expression 
    ArgumentList , Expression 

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

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

Теперь вы видите, что метод, который должен называться, включает идентификацию типа. Поскольку java поддерживает метод overriding, следовательно, у вас могут быть разные типы, реализующие один и тот же метод. Поэтому перед тем, как разрешить аргумент метода, будет найден тип экземпляра, который в вашем случае окажется равным нулю и приведет к NPE.

Надеюсь, это поможет.

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