Skip to content

Move Instance Method changes field null-check semantics and introduces NullPointerException #4460

Description

@zmjjcxy8

Description

Move Instance Method changes the behavior of the program when moving the instance method process() from class A to class C.

Before refactoring, process() checks whether the field c is null. Since a.c is null in the original program, the method safely returns 0.

After moving the instance method process() to class C, VS Code Java changes the call site from:

a.process()

to:

a.c.process()

However, a.c is null, so the refactored program throws NullPointerException before the moved method is entered.

In addition, the original condition:

if (c != null) return 2;

is rewritten as:

if (this != null) return 2;

This is not semantically equivalent. The original condition checks whether the source object's field c is null, while this != null is effectively always true once the instance method is entered.

Code before refactoring

public class t {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.process());
    }
}

class A {
    C c;

    // Move Instance Method target method
    int process() {
        if (c != null) return 2;
        return 0;
    }
}

class B extends A { }

class C extends B { }

Before refactoring, the program prints:

0

Refactoring operation

Apply Move to method A.process() and move it to class C.

Code after refactoring

public class t {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.c.process());
    }
}

class A {
    C c;
}

class B extends A { }

class C extends B {
    int process() {
        if (this != null) return 2;
        return 0;
    }
}

After refactoring, running the program throws:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "C.process()" because "<local1>.c" is null
    at t.main(t.java:4)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions