2012-01-31 17 views
5

Estoy buscando una forma rápida de averiguar qué parte de un chain es nulo.Encontrar el nulo en una cadena de invocación de método

Un ejemplo Para ilustrar este punto:

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()); 
    } 
} 

Esto, obviamente, lanzar una NullPointerException. (Sé cómo alterar el código para que sea obvio qué parte de la cadena arrojó el NullPointerException, pero me gustaría alguna forma de resolverlo con el código existente.)

+1

¿Qué quieres como salida? Hashcode de la cadena que contiene nulo? –

+0

Quiero algo como "c1.returnChain(). ReturnChain() devuelto nulo". –

+0

@ChristianJonassen: ¿Estás buscando una solución para esta pieza de código en particular o para algo más genérico en el que estás realizando una secuencia de llamadas a funciones arbitrarias? – Dawood

Respuesta

2

En el seguimiento de la pila para una NPE típica, que está dado el número de línea que se produjo el. Así que asumiendo System.out.println(c1.returnChain().returnChain().returnChain().returnChain()); está en la línea 144 (acaba de recoger que al azar) NPE seguimiento de la pila debe ser algo como:

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

Por lo tanto, si usted pone su llamada cadena en varias líneas, es preciso que muestran que la excepción es.

escribí este pequeño ejemplo:

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(); 
    } 
} 

y me dio la NPE dice: en bla.Something.main (Something.java:18) - exactamente donde el NPE se produjo en la cadena.

Captura de pantalla ...

Showing what this would look like...

+0

¡Intenté lo mismo pero no funcionó para mí! Inicié la primera línea de la construcción donde se arroja el NPE. – thermz

+0

¿Alguien quiere explicar el voto a la baja? No me importa si estoy equivocado sobre algo, pero al menos me gustaría una explicación. – Dave

+0

@thermz, ¿podría publicar el código de cuando intentó esto y no funcionó? – Dave

0

Tal vez no lo estoy obteniendo, pero ¿qué sobre solo returnChain() == null?

0

se pueden agregar a Chain variable de clase como position para la posición del elemento en la cadena determing:

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()); 
    } 
} 

Por supuesto que no es hilo de seguridad y se ve raro. Pero debe escribir la posición de nulo. versión más simple:

public int findPositionOfNullChain(Chain chain) { 
    int position = 0; 
    while (chain != null) { 
     chain = chain.returnChain(); 
     position++; 
    } 
    return position; 
} 
+3

No creo que Christian Jonassen necesite una solución para este código en particular (que es claramente un ejemplo), creo que está buscando una solución para encontrar siempre un NPE en una llamada de métodos "encadenada" ... algo como 'this.getTown(). getAvenue(). getNumber(). getFloor()' si avenue es nulo, no hay una buena solución para encontrar siempre donde se lanza NPE ... a menos que no quieras probar y atrapar cada llamada ... – thermz

+0

Para ese escenario, puede usar 'npe.getStackTrace() [0] .getMethodName()'. No ayuda aquí, por supuesto. –

+0

Desafortunadamente no, en esta situación (el propietario del código de la pregunta), llamar a 'npe.getStackTrace() [0] .getMethodName()' devolverá "main" – thermz

2

Para la pieza de código que usted tiene, trate de añadir el siguiente método a la clase 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; 
    } 

Usted puede usarlo como sigue:

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

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

Esto pr Int:

firstChain.returnChain().returnChain() returned null 
0

Sin modificar la clase de la cadena, se puede hacer esto para saber qué parte es nulo:

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 

o simplemente puede detectar la excepción de puntero nulo para imprimir nula

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  
Cuestiones relacionadas