Нахождение нуля в цепочке вызова метода - PullRequest
5 голосов
/ 01 февраля 2012

Я ищу быстрый способ выяснить, какая часть цепочки равна нулю.

Пример для иллюстрации:

public class Chain {
    private Chain chain;

    public Chain returnChain() {
        return chain;
    }

    public void addChain(Chain chain) {
        this.chain=chain;
    }

    public String toString() {
        return "Hello!";
    }

    public static void main(String[] args) {
        Chain c1 = new Chain();
        c1.addChain(new Chain());

        System.out.println(c1.returnChain().returnChain().returnChain().returnChain());
    }
}

Это, очевидно, выбросит NullPointerException.(Я знаю, как изменить код, чтобы было понятно, какая часть цепочки выкинула NullPointerException, но я бы хотел как-то выяснить это с помощью существующего кода.)

Ответы [ 5 ]

2 голосов
/ 01 февраля 2012

Для конкретного фрагмента кода, который у вас есть, попробуйте добавить следующий класс в ваш Chain класс:

    public static Chain checkChainSequence(Chain first, int count) {
        Chain thisChain = first;
        StringBuilder out = new StringBuilder("firstChain");
        for (int i = 0; i < count; i++) {
            Chain nextChain = thisChain.returnChain();
            out.append(".returnChain()");
            if (nextChain == null) {
                out.append(" returned null");
                System.out.println(out);
                return null;
            }
            thisChain = nextChain;
        }
        return thisChain;
    }

Вы можете использовать его следующим образом:

    Chain c1 = new Chain();
    c1.addChain(new Chain());

    // To check c1.returnChain().returnChain().returnChain():
    Chain.checkChainSequence(c1, 3);

Это напечатало бы:

    firstChain.returnChain().returnChain() returned null
2 голосов
/ 01 февраля 2012

В трассировке стека для типичного NPE вам дается номер строки, на которой он произошел.Таким образом, предполагая, что System.out.println(c1.returnChain().returnChain().returnChain().returnChain()); находится на строке 144 (только что выбранный случайным образом), ваша трассировка стека NPE должна выглядеть примерно так:

java.lang.NullPointerException
  at your.package.Chain(Chain.java:144)

Итак, если вы помещаете свой цепной вызов в несколько строк, он должен показать вамисключение:

Я написал этот маленький пример:

package bla;

public class Something {
    public static int count = 0;
    public Something get() {
        if(count == 2) {
            return null;
        }
        ++count;
        return new Something();
    }

    public static void main(String[] args){
        Something something = new Something();
        Something test = something.get()
                                .get()
                                    .get()
                                        .get() // Should throw NPE
                                            .get()
                                                .get();
    }
}

И он дал мне NPE говорит: в bla.Something.main (Something.java:18) - именно там, гдеNPE произошел в цепочке.

Снимок экрана ...

Showing what this would look like...

0 голосов
/ 01 февраля 2012

Не изменяя класс Chain, вы можете сделать это, чтобы узнать, какая часть имеет значение null:

Chain c1 = new Chain();
c1.addChain(new Chain());
Chain preNullChain = c1;
Chain returnedChained = null;

while ((returnedChained = preNullChain.returnChain()) != null) {
    preNullChain = returnedChained;
}
//here, preNullChain is the last Chain that is not null

Или вы можете просто перехватить исключение нулевого указателя, чтобы напечатать null

Chain returnedChain = null;
Chain c1 = new Chain();
c1.addChain(new Chain());
try {
returnedChain = c1.returnChain().returnChain().returnChain().returnChain();
} catch (NullPointerException e) {
}
System.out.println(returnedChain); //now here will print null as what you asked for    
0 голосов
/ 01 февраля 2012

Вы можете добавить к Chain переменную класса, например position, для определения положения элемента в цепочке:

public class Chain {
    private Chain chain;
    private int position;

    public Chain returnChain() {
        if (chain == null) {
            System.out.println(position + " chain is null");
        } else {
            chain.position = position + 1;
        }
        return chain;
    }

    public void addChain(Chain chain) {
        this.chain=chain;
    }

    public String toString() {
        return "Hello!";
    }

    public static void main(String[] args) {
        Chain c1 = new Chain();
        c1.addChain(new Chain());
        c1.position = 0;
        System.out.println(c1.returnChain().returnChain().returnChain().returnChain());
    }
}

Конечно, это не безопасно для потоков и выглядит странно.Но стоит написать нулевую позицию.Более простая версия:

public int findPositionOfNullChain(Chain chain) {
     int position = 0;
     while (chain != null) {
         chain = chain.returnChain();
         position++;
     }
     return position;
}
0 голосов
/ 01 февраля 2012

Может быть, я не понимаю, но как насчет returnChain() == null?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...