Breakdown object in java

I have a huge object, I have its class, of course, I extract some values ​​from it, but since it is really big, I don’t know which list or where the value I'm looking for is.

Is there a way to create some kind of routing of breakdowns of the object and search for each part for the expected value, and it is hidden somewhere in the object, I just can not find it in eclipse too nested.

I thought about using reflection for all fields of the object class and searching for the values ​​inside each field (fields inside lists (list of lists, etc.)). Any other ideas?

Unfortunately, none of these answers help me, I begin generosity

+6
java
source share
11 answers

I assume that you just want to find a specific value and trace its source. And all this, you want to do in debug time. I would suggest two options.

Option1 Use JSON . Serialize the object into a json string and do a manual search for the text by the result. You can use json.jar (or any other parser) for this.

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

Which will create something like that. (I mimicked this by creating an object with some nested fields, lists, maps)

 { "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 / Serialize the object to XML . Use XStream for this, which will be the easiest parser available. With just two lines of code,

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

What will produce

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

Any of the above approaches allows you to print the result on the console or in a file and check it manually. Alternatively, you can also use reflection, in which case you will have to write a lot of code and a significant amount of time when testing it.

+6
source share

How to use ToStringBuilder from Jakarta-Commons org.apache.commons.lang.builder package .

 System.out.println ( ToStringBuilder.reflectionToString( YOUR_OBJECT ) ); 
+4
source share

Create some static method, assuming:

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

And implement it (for example) as data extraction. Using org.apache.pivot.beans.BeanAdapter - for example, can help you treat a bean like a regular map, or (as you wrote - you need to go deep) use recursion to group all properties into one big map.

Another useful signature:

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

where the second parameter is used to search for a substring of values ​​from the Map of first method.

Why is this useful? Since you can use the eclipse inspector to calculate the result of this method at any time during debugging

+2
source share

If the class is Serializable, I often use XStream to dump an object in xml.

If not, here is some code, maybe you will start in reflection mode. This is not as recursive as you need, but can be easily modified.

 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 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); } 
+1
source share

I think you need to use reflection to get the data. Here is the code that should run you:

 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
source share

Some tips -

1) You can use shift and click on a variable / method / class, this will lead you to this correctly.

2) Right-click - The hierarchy of open calls will show you exactly where the variable is being called.

3) Team and O will show you the class diagram so that you can move quickly

4) The fast Hierchy type will show you how / where your variable sits in a grandiose class scheme.

Hope that helps

0
source share

It often helps to print the values ​​of a large object so that you can carefully view them. In Java and C ++, I wrote functions for printing the entire contents of an object, along with recursion for processing embedded objects. Debugging a hard copy of object variables is an old fashion, but for very complex situations this will lead to additional discoveries.

0
source share

Maybe a completely different approach. Try putting your object (after decomposition) into the in-memory data store (see http://www.google.de/search?hl=en&q=java+inmemory+data+store+search ), and then use its search functions. After conducting the tests, you should feel that in your case it will be better. If you are intensively reading an object, it might be even better to use a database in memory.

0
source share

I think you should use the Java Reflection API. Take a look here: http://java.sun.com/developer/technicalArticles/ALT/Reflection/

0
source share

Disclaimer: The code is rude and very ugly. I just want to demonstrate the ability to do what the OP wants with these basic ideas:

  • Reflection
  • Recursion
  • Field#setAccessible
  • Special Cases for Array, Iterable , Enumeration , Primitive Shell Class and String

@ Thomas Muller's answer contains elements of these, but my # 3 and # 4 are a little more reliable. And its code doesn't seem to work with my curved test classes. However, I probably still missed some corner cases. Please do not send this to my Java teacher.

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

Output:

  |count_s:3 |a:a |obj: TestClass2@6e1408 |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:[ Z@19ee1ac |c:[(Boolean)true |c:[(Boolean)false |list:[ TestClass@1befab0 ] |list:[(TestClass) |count_s:3 |list:[(TestClass) |a:a |list:[(TestClass) |obj: TestClass2@13c5982 |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:[ Z@14b7453 |list:[(TestClass) |c:[(Boolean)true |list:[(TestClass) |c:[(Boolean)false |list:[(TestClass) |list:[ TestClass@c21495 ] |list:[(TestClass) |list:[(TestClass) |count_s:3 |list:[(TestClass) |list:[(TestClass) |a:a |list:[(TestClass) |list:[(TestClass) |obj: TestClass2@1d5550d |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:[ Z@15b7986 |list:[(TestClass) |list:[(TestClass) |c:[(Boolean)true |list:[(TestClass) |list:[(TestClass) |c:[(Boolean)false |list:[(TestClass) |list:[(TestClass) |list:[] 
0
source share

well, if a complex object consists of Java objects, such as strings, lists, maps, etc., you can iterate over them by reflection, and when you find that the “object” you are looking at is a string or int (and such) calling toString

This does not work if your source object contains a "custom" object

-one
source share

All Articles