2010-08-10 44 views
6

Tengo un gran objeto, tengo su clase por supuesto, estoy extrayendo algunos valores, pero como es muy grande no sé en qué lista o dónde estoy buscando el valor para es.desglose objeto en java

¿Hay alguna manera de crear algún tipo de enrutamiento de desglose de objetos y buscar en cada parte el valor que estoy esperando, y está escondido en algún lugar del objeto, simplemente no puedo encontrarlo en eclipse está anidado demasiado.

Pensé en usar la reflexión para recorrer todos los campos de la clase de objetos y buscar el valor dentro de cada campo (campos dentro de las listas (lista de listas, etc.)). ¿Alguna otra idea?

Desafortunadamente ninguna de estas respuestas me ayude, estoy empezando una recompensa

+1

ver si ayuda: http://stackoverflow.com/questions/301536/what-is-the-java-equivalent-of-php-var- volcado –

+3

Parece que necesita refactorizar y rediseñar este objeto. – Oded

+0

Como usted está preguntando aquí, supongo que la respuesta "pregunte al inventor" ya se ha llevado a cabo o es imposible. – Carl

Respuesta

6

Supongo que solo quiere encontrar un valor específico y rastrear su origen. Y todo esto, quieres hacerlo en el momento de la depuración. Sugeriría dos opciones.

Option1 Uso JSON - serializar el objeto de cadena JSON y hacer una búsqueda de texto manual en el resultado. Necesitarás json.jar (o cualquier otro analizador) para esto.

try { 
     System.out.println(new JSONObject(new YourHugeObject()).toString(5)); 
    } catch (JSONException e) { 
     log(e); 
    } 

Que producirá algo como esto. (He simulado mediante la creación de un objeto con algunos campos anidados, listas, mapas)

{ 
"ct": { 
     "a": 1, 
     "b": "sdf", 
     "f": 12, 
     "nested": { 
      "key1": { 
       "kk": "kk", 
       "ssdf": 123 
      }, 
      "onemorekey": { 
       "kk": "kk", 
       "ssdf": 123 
      } 
     } 
}, 
"doubleProp": 12.2, 
"lngprop": 1232323, 
"strProp": "123", 
"stringlist": [ 
     "String1", 
     "String2", 
     "String3" 
] 
} 

Option2 Convert/serializar el objeto a XML. Use XStream para esto, que será el más fácil de todos los analizadores disponibles. Con sólo dos líneas de código,

XStream stream = new XStream(); 
    System.out.println(stream.toXML(new YourHugeObject())); 

que producirá,

<com.kmg.jsontools.test.JSTest> 
<stringlist> 
<string>String1</string> 
<string>String2</string> 
<string>String3</string> 
</stringlist> 
<strProp>123</strProp> 
<doubleProp>12.2</doubleProp> 
<lngprop>1232323</lngprop> 
<ct> 
<a>1</a> 
<b>sdf</b> 
<f>12.0</f> 
<nested> 
    <entry> 
    <string>key1</string> 
    <com.kmg.jsontools.test.Type1> 
     <kk>kk</kk> 
     <ssdf>123</ssdf> 
    </com.kmg.jsontools.test.Type1> 
    </entry> 
    <entry> 
    <string>onemorekey</string> 
    <com.kmg.jsontools.test.Type1> 
     <kk>kk</kk> 
     <ssdf>123</ssdf> 
    </com.kmg.jsontools.test.Type1> 
    </entry> 
</nested> 
</ct> 
</com.kmg.jsontools.test.JSTest> 

Cualquiera de los enfoques anteriores, se puede imprimir el resultado a la consola o en un archivo e inspeccionar manualmente. Como alternativa, también puede usar la reflexión, en cuyo caso también deberá escribir una gran cantidad de código y una gran cantidad de tiempo para probarlo.

0

Algunos consejos -

1) Usted puede utilizar el cambio y hacer clic en la variable/método/clase, esto traerá lo haces correctamente

2) Haga clic con el botón derecho - Abrir jerarquía de llamadas le mostrará exactamente dónde se llama la variable.

3) Comando y O le mostrará un resumen de teh clase para que pueda navegar rápidamente

4) Tipo rápida hierchy le mostrará cómo/donde la variable se encuentra en el gran esquema de la clase.

Espero que ayude

0

Suele ser útil para imprimir los valores de un objeto grande para que pueda mirar por encima de ellos con cuidado. Tanto en Java como en C++ he escrito funciones para imprimir todo el contenido de un objeto, junto con la recursión para manejar objetos incrustados. La depuración de una copia impresa de las variables del objeto es anticuada, pero para situaciones muy complejas generará descubrimientos adicionales.

+0

'A menudo es útil imprimir los valores de un objeto grande para que pueda examinarlos detenidamente' esto es lo que estoy buscando – ant

1

Si la clase es Serializable, a menudo uso XStream para volcar un objeto a xml.

Si no es así, aquí hay un código que quizás lo ayude a comenzar en el modo de reflexión. No es tan recursivo como necesitas, pero podría modificarse con bastante facilidad.

public static void debugPrint(Object o1) 
{ 
    if(o1 == null) 
    { 
     System.out.println(o1); 
     return; 
    } 

    Class c = o1.getClass(); 
    do 
    { 
     printFields(c, o1); 
     c = c.getSuperclass(); 
    } 
    while(c != null); 
} 

private static void printFields(Class c, Object o1) 
{ 
    Field[] fields = c.getDeclaredFields(); 
    for(Field field : fields) 
    { 
     printField(field, o1); 
    } 
} 

private static void printField(Field field, Object o1) 
{ 
    try 
    { 
     if(Modifier.isFinal(field.getModifiers())) return; //Skip this guy, he's trouble! 

     field.setAccessible(true); 

     Object val = field.get(o1); 

     System.out.println(field.getName() + ":" + toString(val)); 
    } 
    catch(IllegalAccessException ex) 
    { 
     System.out.println("Could not access field" + field.getName()); 
     ex.printStackTrace(); 
    } 
} 

private static String toString(Object o) 
{ 
    if(o instanceof Object[]) 
     return Arrays.toString((Object[])o); 
    else 
     return String.valueOf(o); 
} 
+0

buena solución, lástima que no funcione – ant

2

crear algún método estático, asumiendo:

Map<String, Object> DebugHelper.breakDown(Object bean) 

y aplicarlo (por ejemplo) como la extracción de datos. Uso de org.apache.pivot.beans.BeanAdapter - por ejemplo, puede ayudarlo a tratar el bean como un mapa simple, o (como ha escrito, necesita el mío en profundidad) use la recursividad para agrupar todas las propiedades en un solo mapa grande

Otra firma útil:

Map<String, Object> DebugHelper.breakDown(Object bean, String lookFor) 

en segundo parámetro utilizado para encontrar subcadena del valor de de Mapa de primer método.

¿Por qué es esto útil? Debido a que puede usar el inspector de eclipse para calcular el resultado de este método en cualquier momento de depuración

+0

puede dar un ejemplo del método estático al que se refiere a realmente no entiendo su punto en la mayoría del caso – ant

+0

@ c0mrade aquí está: http://ideone.com/BjygK colocando a DebugHelper.breakDown (someInstance, "3.14") - usted puede encontrar propiedades de bean con extracción recursiva que (por ejemplo) devuelve el valor de Pi. Puede cambiar la política de minería como desee. Y tenga en cuenta que esto utiliza utilidades comunes de frijol de Apache – Dewfy

4

¿Qué le parece usar el ToStringBuilder de Jakarta-Commons org.apache.commons.lang.builder package.

System.out.println (ToStringBuilder.reflectionToString(YOUR_OBJECT)); 
1

Creo que necesita utilizar la reflexión para obtener los datos. Aquí hay un código que debe empezar:

static String search(Object o, final String search) { 
    try { 
     inspect(new HashSet<Object>(), o, new StringWriter() { 
      public void write(String s) { 
       System.out.println(s); 
       if (s.indexOf(search) >= 0) { 
        throw new RuntimeException(s) { 
         public Throwable fillInStackTrace() { return null; } }; 
       } 
      } 
     }); 
     return "not found"; 
    } catch (Exception e) { 
     return e.getMessage(); 
    } 
} 

private static void inspect(HashSet<Object> ignore, Object o, Writer w) 
     throws Exception { 
    if (o == null) { 
     return; 
    } 
    for (Class<?> c = o.getClass(); c != null ; c = c.getSuperclass()) { 
     if (c.isArray()) { 
      int len = Array.getLength(o); 
      for (int i=0; i<len; i++) { 
       inspect(ignore, Array.get(o, i), w); 
      } 
     } else if (c.isPrimitive()) { 
      w.write(o.toString()); 
     } else { 
      for (Field f : c.getDeclaredFields()) { 
       if (!Modifier.isStatic(f.getModifiers())) { 
        f.setAccessible(true); 
        if (f.getType().isPrimitive()) { 
         w.write(f.getName() + ": " + f.get(o)); 
        } else { 
         if (!ignore.contains(o)) { 
          ignore.add(o); 
          w.write(f.getName()); 
          inspect(ignore, f.get(o), w); 
         } 
        } 
       } 
      } 
     } 
    } 
} 
-1

bien si el objeto complejo está compuesto por objetos Java, como cadenas, listas, mapas, y tal, se puede por iterate reflexión sobre ellos y cuando se encuentra la "objeto" que está viendo es una cadena o int (y tal) llamada toString

Esto no trabajará si el objeto de partida contiene una "costumbre" objeto

0

tal vez un enfoque totalmente diferente. Intente colocar su objeto (después de la descomposición) en el almacén de datos en memoria (consulte http://www.google.de/search?hl=en&q=java+inmemory+data+store+search) y luego use su función de búsqueda. Después de realizar las pruebas, debe sentirse si funciona mejor en su caso. Si lees el objeto de forma intensiva, tal vez sea mejor utilizar una base de datos en memoria.

0

Descargo de responsabilidad: el código es de fuerza bruta y muy feo.Sólo quiero demostrar la posibilidad de hacer lo PO quiere con estas ideas básicas:

  1. Reflexión
  2. recursividad
  3. Field#setAccessible
  4. casos especiales de matriz, Iterable, Enumeration, clase contenedora primitivo y String

@Thomas Mueller's answer tiene elementos de estos pero mis # 3 y # 4 son un poco más robustos. Y su código no parece funcionar con mis clases de prueba torcidas. Sin embargo, probablemente todavía me perdí algunos casos de esquina. Por favor, no envíe esto a mi tutor de Java.

import java.lang.reflect.Array; 
import java.lang.reflect.Field; 
import java.security.AccessController; 
import java.security.PrivilegedAction; 
import java.util.*; 

public class BreakDown 
{ 
    public static void main(String[] args) 
    { 
     printFields(new TestClass(), ""); 
    } 

    private static void printFields(final Object obj, final String prefix) 
    { 
     if(basics.contains(obj.getClass())) 
     { 
      System.out.println(prefix + obj); 
      return; 
     } 
     for(final Field f : obj.getClass().getDeclaredFields()) 
     { 
      try 
      { 
       try 
       { 
        printOneField(f, obj, prefix); 
        continue; 
       } 
       catch(SecurityException e) {} 
       catch(IllegalAccessException e) {} 
       AccessController.doPrivileged(new PrivilegedAction<Void>() 
       { 
        public Void run() 
        { 
         try 
         { 
          printOneField(f, obj, prefix); 
         } 
         catch(Exception e) 
         { 
          e.printStackTrace(); 
         } 
         return null; 
        } 
       }); 
      } 
      catch(Exception e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    } 

    private static void printOneField(Field f, Object obj, String prefix) throws Exception 
    { 
     f.setAccessible(true); 
     System.out.println(prefix + " |" + f.getName() + ":" + (obj = f.get(obj))); 
     if(obj == null) 
      return; 

     if(obj.getClass().isArray()) 
     { 
      for(int i = 0; i < Array.getLength(obj); ++i) 
       printObj(Array.get(obj, i), prefix, f.getName()); 
     } 
     else if(obj instanceof Iterable) 
     { 
      Iterator<?> it = ((Iterable<?>)obj).iterator(); 
      for(; it.hasNext();) 
       printObj(it.next(), prefix, f.getName()); 
     } 
     else if(obj instanceof Enumeration<?>) 
     { 
      Enumeration<?> e = (Enumeration<?>)obj; 
      for(; e.hasMoreElements();) 
       printObj(e.nextElement(), prefix, f.getName()); 
     } 
     else if(!basics.contains(obj.getClass())) 
      printFields(obj, prefix + " |" + f.getName() + ":" + obj.getClass().getCanonicalName()); 
    } 

    private static void printObj(Object o, String prefix, String name) 
    { 
     printFields(o, " " + prefix + " |" + name + ":[(" + o.getClass().getSimpleName() + ")"); 
    } 

    private static final Set<Class<?>> basics = new HashSet<Class<?>>(); 
    static 
    { 
     basics.add(Integer.class); 
     basics.add(Long.class); 
     basics.add(Double.class); 
     basics.add(Float.class); 
     basics.add(Boolean.class); 
     basics.add(Character.class); 
     basics.add(Byte.class); 
     basics.add(Void.class); 
     basics.add(Short.class); 
     basics.add(String.class); 
    } 
} 

class TestClass 
{ 
    public TestClass() 
    { 
     if(++count_s < 3) 
      list.add(new TestClass()); 
    } 

    private static int count_s = 0; 
    public final String a = "a"; 
    final TestClass2 obj = new TestClass2(); 
    final TestClass2[] objArray = new TestClass2[]{new TestClass2(), new TestClass2()}; 
    private final int b = count_s; 
    private final boolean[] c = new boolean[]{true, false}; 
    private final List<TestClass> list = new ArrayList<TestClass>(); 
} 

class TestClass2 
{ 
    private static int count_s = 0; 
    private final float d = 1.5f * (++count_s); 
} 

La salida es:

|count_s:3 
    |a:a 
    |obj:[email protected] 
    |obj:TestClass2 |count_s:9 
    |obj:TestClass2 |d:1.5 
    |objArray:[LTestClass2;@5483cd 
    |objArray:[(TestClass2) |count_s:9 
    |objArray:[(TestClass2) |d:3.0 
    |objArray:[(TestClass2) |count_s:9 
    |objArray:[(TestClass2) |d:4.5 
    |b:0 
    |c:[[email protected] 
    |c:[(Boolean)true 
    |c:[(Boolean)false 
    |list:[[email protected]] 
    |list:[(TestClass) |count_s:3 
    |list:[(TestClass) |a:a 
    |list:[(TestClass) |obj:[email protected] 
    |list:[(TestClass) |obj:TestClass2 |count_s:9 
    |list:[(TestClass) |obj:TestClass2 |d:6.0 
    |list:[(TestClass) |objArray:[LTestClass2;@1186fab 
     |list:[(TestClass) |objArray:[(TestClass2) |count_s:9 
     |list:[(TestClass) |objArray:[(TestClass2) |d:7.5 
     |list:[(TestClass) |objArray:[(TestClass2) |count_s:9 
     |list:[(TestClass) |objArray:[(TestClass2) |d:9.0 
    |list:[(TestClass) |b:1 
    |list:[(TestClass) |c:[[email protected] 
     |list:[(TestClass) |c:[(Boolean)true 
     |list:[(TestClass) |c:[(Boolean)false 
    |list:[(TestClass) |list:[[email protected]] 
     |list:[(TestClass) |list:[(TestClass) |count_s:3 
     |list:[(TestClass) |list:[(TestClass) |a:a 
     |list:[(TestClass) |list:[(TestClass) |obj:[email protected] 
     |list:[(TestClass) |list:[(TestClass) |obj:TestClass2 |count_s:9 
     |list:[(TestClass) |list:[(TestClass) |obj:TestClass2 |d:10.5 
     |list:[(TestClass) |list:[(TestClass) |objArray:[LTestClass2;@c2ea3f 
     |list:[(TestClass) |list:[(TestClass) |objArray:[(TestClass2) |count_s:9 
     |list:[(TestClass) |list:[(TestClass) |objArray:[(TestClass2) |d:12.0 
     |list:[(TestClass) |list:[(TestClass) |objArray:[(TestClass2) |count_s:9 
     |list:[(TestClass) |list:[(TestClass) |objArray:[(TestClass2) |d:13.5 
     |list:[(TestClass) |list:[(TestClass) |b:2 
     |list:[(TestClass) |list:[(TestClass) |c:[[email protected] 
     |list:[(TestClass) |list:[(TestClass) |c:[(Boolean)true 
     |list:[(TestClass) |list:[(TestClass) |c:[(Boolean)false 
     |list:[(TestClass) |list:[(TestClass) |list:[]