Почему я получил исключение NullPointerException, когда я не использовал setter в основном методе? - PullRequest
0 голосов
/ 10 января 2020

У меня есть вопрос об использовании геттеров и сеттеров, и исключение нулевого указателя.

Я в основном вызвал простую функцию getSlope() для объекта Line, l, в моей программе, которая имеет Line и Point классы.

Когда я позвонил l.getSlope() с Point p1 = new Point(0.0, 3.0); Point p2 = new Point(5.0, 5.0); Line l = new Line(p1, p2);, это дало мне исключение нулевого указателя.

Однако, когда я позвонил l.getSlope() с Line l = new Line(); l.setP1(0.0, 3.0); l.setP2(5.0, 5.0);, он НЕ дал мне исключение нулевого указателя.

Почему это? Спасибо за помощь. Код для классов Point и Line приведен ниже для вашей информации.

Point:

public class Point {
    private double x;
    private double y;

    public Point() {
        this.x = 0.0;
        this.y = 0.0;
    }
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public void setX(double x) {
        this.x = x;
    }
    public void setY(double y) {
        this.y = y;
    }
    public double getX() {
        return this.x;
    }
    public double getY() {
        return this.y;
    }
    public String toString() {
        return "(" + this.x + ", " + this.y + ")";
    }
    public static void main(String[] args) {
        Point p = new Point(1.5, 3);
            System.out.println(p.toString());
    }
}

Line:

public class Line {
    private Point p1;
    private Point p2;

    public Line() {
        p1 = new Point(0,0);
        p2 = new Point(0,0);
    }

    public Line(Point p1, Point p2) {
        p1 = new Point(p1.getX(), p1.getY());
        p2 = new Point(p2.getX(), p2.getY());
    }
    public Point getP1() {
        return this.p1;
    }
    public Point getP2() {
        return this.p2;
    }
    public void setP1(double x, double y) {
        this.p1 = new Point (x, y);
    }
    public void setP2(double x, double y) {
        this.p2 = new Point(x, y);
    }
    public double getSlope() {
        return ((p2.getY() - p1.getY()) / (p2.getX() - p1.getX()));
    }
    public static void main(String[] args) {
//      Point p1 = new Point(0.0, 3.0);
//      Point p2 = new Point(5.0, 5.0);
//      Line l = new Line(p1, p2);
//      System.out.println(l.getSlope()); // These 4 lines produced errors
        Line l = new Line();
        l.setP1(0.0, 3.0);
        l.setP2(5.0, 5.0);
        System.out.println(l.getSlope());  // These 4 lines worked!
    }
}

1 Ответ

1 голос
/ 10 января 2020

Я поставлю это в реальном ответе, поэтому у меня будет больше возможностей для работы.

Проблема здесь в вашем Line конструкторе. Вы сталкиваетесь с чем-то, что называется «затенение переменных».

public Line(Point p1, Point p2) {
    p1 = new Point(p1.getX(), p1.getY());
    p2 = new Point(p2.getX(), p2.getY());
}

Вы передаете переменные в этот конструктор с именами p1 и p2:

public Line(Point p1, Point p2) // Here are p1 and p2 being passed into the constructor

Теперь вы также имеют p1 и p2, определенные на уровне класса, например:

private Point p1;
private Point p2;

Что вы хотите сделать, это создать новые очки на основе p1 и p2 передаются в конструктор и сохраняют эти новые точки в этих переменных уровня класса.

Но поскольку конструктор имеет локальные переменные с тем же именем, что и переменные уровня класса, локальные переменные имеют приоритет, и " скрыть "переменные уровня класса. Это известно как «затенение».

Так что в конструкторе, когда вы хотите получить доступ к этим переменным уровня класса, вы должны ссылаться на них как this.p1 и this.p2, так как p1 и p2 см. Параметры конструктора.

public Line(Point p1, Point p2) {
    p1; // <-- This is the p1 being passed into the constructor
    this.p1; // <-- This is the class-level variable with the same name
}

Когда вы используете this. для получения правильных переменных, код должен выглядеть следующим образом:

public Line(Point p1, Point p2) {
    this.p1 = new Point(p1.getX(), p1.getY());
    this.p2 = new Point(p2.getX(), p2.getY());
}

Краткий визуальный справочник:

private Point p1; // <------------------+
private Point p2; //                    |      
//                                      |
//                +--------------- +    |
//                |                |    |
//                v                |    |
public Line(Point p1, Point p2) {
//                                 |    |
    p1; // <--these are the same---+    |
    this.p1; // <--these are the same---+
}
...