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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions