Объект разбивки в java

У меня есть огромный объект, у меня есть его класс, конечно, я извлекаю из него некоторые значения, но поскольку он действительно большой, я не знаю, в каком списке или где значение, которое я ищу, есть.

Есть ли способ создать какую-то маршрутизацию пробоев объекта и выполнить поиск каждой части для ожидаемого значения, и она скрыта где-то в объекте, я просто не могу найти ее в eclipse слишком вложенной.

Я подумал об использовании рефлексии для всех полей класса объектов и поиска значения внутри каждого поля (поля внутри списков (список списков и т.д.)). Любые другие идеи?

К сожалению, ни один из этих ответов не помогает мне, я начинаю щедрость

11 ответов

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

Option1 Используйте JSON. Сериализуйте объект в строку json и выполните ручной поиск текста по результату. Для этого вы можете использовать json.jar(или любой другой парсер).

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

Что создаст нечто подобное. (Я имитировал это, создав объект с некоторыми вложенными полями, списками, картами)

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

Option2 Преобразовать/Сериализовать объект на XML. Используйте XStream для этого, который будет самым простым из всех доступных парсеров. Имея всего две строки кода,

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

Что будет производить,

<com.kmg.jsontools.test.jstest>
<stringlist>
 <string>String1</string>
 <string>String2</string>
 <string>String3</string>
</stringlist>
<strprop>123</strprop>
<**********>12.2</**********>
<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>

Любой из приведенных выше подходов позволяет напечатать результат на консоли или в файле и проверить его вручную. В качестве альтернативы вы также можете использовать отражение, и в этом случае вам придется писать много кода и значительное количество времени при его тестировании.


Как использовать ToStringBuilder из Jakarta-Commons org.apache.commons.lang.builder package.

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


Создайте некоторый статический метод, предполагая:

Map<string, object=""> DebugHelper.breakDown(Object bean)
</string,>

И реализуйте его (например) как выделение данных. Использование org.apache.pivot.beans.BeanAdapter - например, может помочь вам обработать bean как обычную карту, или (как вы написали - вам нужно углубленно) использовать рекурсию для группировать все свойства в одну большую карту.

Другая полезная подпись:

Map<string, object=""> DebugHelper.breakDown(Object bean, String lookFor)
</string,>

где второй параметр используется для поиска подстроки значения из Map of first method.

Почему это полезно? Поскольку вы можете использовать инспектор eclipse для вычисления результата этого метода в любое время отладки


Если класс Serializable, я часто использую XStream, чтобы сбрасывать объект в xml.

Если нет, вот какой-то код, возможно, вы начнете в режиме отражения. Это не так рекурсивно, как вам нужно, но может быть легко изменено.

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


Думаю, вам нужно использовать отражение, чтобы получить данные. Вот код, который должен вас запустить:

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


Он часто помогает распечатать значения большого объекта, чтобы вы могли тщательно их просматривать. В Java и С++ я написал функции для печати всего содержимого объекта вместе с рекурсией для обработки внедренных объектов. Отладка печатной копии объектных переменных - старая мода, но для очень сложных ситуаций это приведет к дополнительным открытиям.


Может быть, совсем другой подход. Попробуйте поместить свой объект (после разложения) в хранилище данных в памяти (см. http://www.google.de/search?hl=en&q=java+inmemory+data+store+search), а затем использовать его функции поиска. После проведения тестов вы должны почувствовать, что в вашем случае это будет лучше. Если вы интенсивно читаете объект, возможно, будет еще лучше использовать базу данных в памяти.


Я думаю, вы должны использовать API Java Reflection. Посмотрите здесь: http://java.sun.com/developer/technicalArticles/ALT/Reflection/


Некоторые советы -

1) Вы можете использовать shift и щелкнуть по переменной/методу/классу, это приведет вас к этому правильно.

2) Щелкните правой кнопкой мыши - Иерархия открытых вызовов покажет вам, где именно вызывается переменная.

3) Команда и O покажут вам схему класса, чтобы вы могли быстро перемещаться

4) Быстрый тип Hierchy покажет вам, как/где ваша переменная сидит в грандиозной схеме класса.

Надеюсь, что поможет


Отказ от ответственности: код грубый и очень уродливый. Я просто хочу продемонстрировать возможность делать то, что хочет OP с этими основными идеями:

  • Отражение
  • Рекурсия
  • Field#setAccessible
  • Специальные случаи для массива, Iterable, Enumeration, примитивный класс оболочки и String

@Ответ Томаса Мюллера содержит элементы этих, но мои # 3 и # 4 немного более надежны. И его код, похоже, не работает с моими кривыми тестовыми классами. Тем не менее я, вероятно, все еще пропустил некоторые угловые случаи. Пожалуйста, не отправляйте это моему преподавателю 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(******.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);
}
</testclass></testclass></class<?></class<?></void>

Вывод:

|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:[]


хорошо, если сложный объект состоит из объектов Java, таких как строки, списки, карты и т. вы можете путем отражения перебрать их, и когда вы обнаружите, что "объект", на который вы смотрите, является строковым или int (и таким) вызовом toString

Это не работает, если ваш исходный объект содержит "пользовательский" объект

licensed under cc by-sa 3.0 with attribution.