Java method invocation order

2019-07-15 08:15发布

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);
     }

}

This code snippet gives NullPointerException, causing initMe() is invoked before getint is invoked. What would be the root cause of this problem? Is JAVA pass-by-value so reference updation is not affected.

Give me the proper reason behind it.

7条回答
Rolldiameter
2楼-- · 2019-07-15 08:46

As specified in

JLS section 15.12. Method Invocation Expressions

A method invocation expression is used to invoke a class or instance method.

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

Resolving a method name at compile time is more complicated than resolving a field name because of the possibility of method overloading. Invoking a method at run time is also more complicated than accessing a field because of the possibility of instance method overriding.

Determining the method that will be invoked by a method invocation expression involves several steps. The following three sections describe the compile-time processing of a method invocation; the determination of the type of the method invocation expression is described in §15.12.3.

Now you see to identiry which method is to be called involves type identification. As java supports method overriding hence you can have different types implementing same method. So before resolving the method arguments instance type is identified which in your case turns out to be null and results in NPE.

Hope it helps.

查看更多
The star\"
3楼-- · 2019-07-15 08:53

main is the first method called, initialize m, before calling initMe of MyClass. Like

private static MyClass m = new MyClass();

See, m.initMe(getint()); invokes initMe() on m, but you have not initialized m as this is the first line of main method, so m = null, hence exception.

查看更多
你好瞎i
4楼-- · 2019-07-15 08:55

m.initMe(getint());

When m.initMe() is called, m is still uninitialized. It gets initialized in the getint() only. Therefore, you need to initialized your m before you could use it call a method using it.

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;
}

or else you can initialize it just before calling initMe() as well in the main() method.

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;
}
查看更多
冷血范
5楼-- · 2019-07-15 08:57

Without instantiating MyClass, you have invoked its method initMe. So, since the object is not instantiated, you are getting this exception Change this to:

 private static MyClass m = new MyClass();
查看更多
Emotional °昔
6楼-- · 2019-07-15 09:05

A compiler could generate what you have in mind

  • execute the code for each parameter
  • put the result on the stack
  • call the method (m would be initialized)

But the Java specifications describe several steps that are necessary before evaluating the parameters. The JVM has to be able to identify the type of the object (the runtime type) before knowing how to handle the parameters.

This is the bytecode which is generated

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        

As you can see the first step is to load m on the stack. It will load null. Then getint is invoked, it will set m but the value used by invokevirtual will be the one already loaded on the JVM stack.

查看更多
聊天终结者
7楼-- · 2019-07-15 09:05

First you have to initialize the 'm'

private static MyClass m = new MyClass();

Java does manipulate objects by reference and all object variables are references. Java doesn't pass method arguments by reference but by value.

查看更多
登录 后发表回答