Получение NullPointerException в расширенных методах - Java

Есть 4 класса в моем UiAutomator тестовый проект:

1:

public class A {
protected E e;
public T t = null;
protected String m ,v;
protected long L;

public A(){
    t = new T();
}

public A(E e, String m, String v, String tf)
{
    this.e = e;
    this.m = m;
    this.v = v;
    t = t.loadXML(tf);
}

2:

public class B extends A {

public B(E e, String m, String v, String tf)
{
    this.e = e;
    this.m = m;
    this.v = v;
    t = t.loadXML(tf);
}

3:

public class C {
private B b = null;
private D d = null;
private E e = null;

public C(B b, E e, D d)
{
    this.b = b;
    this.e = e;
    this.d = d;
}

4:

public class D extends B{

public D (E e, String m, String v, String tf)
{
    super(e, m, v, tf);
    this.e = e;
    this.m = m;
    this.v = v;
    t = t.loadXML(tf);
}

Я получаю NullPointerException когда программа пытается использовать методы класса D (у класса C есть метод, который использует A, B, D).
Там нет проблем в A, B, C.
Методы в D вызывают методы из B, и я думаю, что у меня есть некоторые проблемы с расширением? Кроме того, как я могу использовать методы B в D без расширения класса? Спасибо!

2 ответа

Решение

Несколько вещей: несмотря на t будучи общим, вы предполагаете, что T есть метод loadXML(); тем не менее, нет никаких ограничений на то, что T может быть.

Кроме того, вот где ваш NullPointerException является:

D конструктор вызывает конструктор для B, но конструктор для B не вызывает конструктор по умолчанию для A, который инициализирует T, поскольку t не инициализируется, вы получаете NullPointerException,

Посмотрите Конструкторы по умолчанию и наследование в Java для получения дополнительной информации о конструкторах по умолчанию и наследовании в Java.

Я не уверен, что вы делаете, чтобы получить исключение NullPointerException, но я укажу на ошибки, которые я заметил до сих пор.

В конструкторе А вы пишете:

t = t.loadXML(tf);

в этот момент t еще не инициализирован, поэтому он равен null, и попытка вызвать метод для него вызовет исключение NullPointerException. Это не должно вызывать исключение NullPointerException в D в вашем коде, как это происходит в настоящее время (поскольку B вызывает конструктор A по умолчанию, который инициализирует t; см. Пояснения ниже). Есть 2 способа решить эту проблему (в зависимости от того, что вы хотели, чтобы произошло): 1. Вызвать другой конструктор А (который инициализирует t):

public A(E e, String m, String v, String tf)
{
    this();
    this.e = e;
    this.m = m;
    this.v = v;
    t = t.loadXML(tf);
}
  1. Передайте аргумент t типа T в конструктор и используйте его, чтобы помочь инициализировать t

    public A (E e, Строка m, Строка v, Строка tf, T прошло T) { this(); this.e = e; this.m = m; this.v = v; t = passT.loadXML(tf); }

Другие заметки. Вы можете сэкономить некоторую работу в B, вызвав конструктор A:

public B(E e, String m, String v, String tf)
{
    super(e,m,v,tf)
}

Это будет делать все те же назначения, которые вы в настоящее время делаете в конструкторе B, так как он вызывает конструктор A и выполняет там код. В настоящее время конструктор B будет беззвучно вызывать конструктор A по умолчанию (без аргументов). Явно это выглядит так:

public B(E e, String m, String v, String tf)
{
    super();
    this.e = e;
    this.m = m;
    this.v = v;
    t = t.loadXML(tf);
}

Я предполагаю, что вы добавили оператор super в D, потому что в противном случае возникла ошибка: B не определил конструктор без аргументов, поэтому D не может вызвать его и выдаст ошибку компиляции. При этом конструктор D также может быть упрощен до:

public D (E e, String m, String v, String tf)
{
    super(e, m, v, tf);
}

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

Чтобы ответить на ваш последний вопрос, вы можете использовать методы B в D, просто вызывая их, как если бы они были определены в самом D. Пример:

public class B extends A {
    //I left out your constructors for readability
    public String getMAndV(){
       return m + v;
    }
}

public class D extends B {
    //I left out your constructors for readability
    public String getGivenStringAndMAndV(String givenString){
       return givenString + getMAndV(); //so just call it as if it's defined in the class itself
    }
}
Другие вопросы по тегам