我有一个巨大的对象,我当然有它的类,我从中提取一些值,但由于它非常大,我不知道在哪个列表或我正在寻找的值是什么。< / p>
有没有办法创建某种对象分解路由并搜索每个部分以获取我期望的值,并且它隐藏在对象的某个地方,我只是在eclipse中找不到它太嵌套了。 / p>
我想过使用反射来遍历对象类的所有字段并搜索每个字段内的值(列表中的字段(列表列表等))。还有其他想法吗?
不幸的是,这些答案都没有帮助我,我正在开始赏金
答案 0 :(得分:6)
我假设你只是想找到一个特定的值并追踪它的来源。而这一切,你想在调试时做。我建议两种选择。
<强>选项1 使用 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
}
}
},
"doubleProp": 12.2,
"lngprop": 1232323,
"strProp": "123",
"stringlist": [
"String1",
"String2",
"String3"
]
}
<强>选项2 将对象转换/序列化为 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>
<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>
上述任何一种方法,您都可以将结果打印到控制台或文件并手动检查。 或者,您也可以使用反射,在这种情况下,您还必须编写大量代码并花费大量时间进行测试。
答案 1 :(得分:4)
如何使用Jakarta-Commons org.apache.commons.lang.builder package
中的ToStringBuilder。
System.out.println ( ToStringBuilder.reflectionToString( YOUR_OBJECT ) );
答案 2 :(得分:2)
创建一些静态方法,假设:
Map<String, Object> DebugHelper.breakDown(Object bean)
并将其(例如)实现为数据挖掘。 org.apache.pivot.beans.BeanAdapter的用法 - 例如可以帮助您将 bean 视为普通Map,或者(如您所写 - 您需要深入了解)使用递归来分组所有属性为单个大地图
另一个有用的签名:
Map<String, Object> DebugHelper.breakDown(Object bean, String lookFor)
其中第二个参数用于从第一个方法的Map中查找值的子串。
为什么这有用?因为您可以使用eclipse的检查器在任何调试时间计算此方法的结果
答案 3 :(得分:1)
如果类是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'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);
}
答案 4 :(得分:1)
我认为您需要使用反射来获取数据。以下是一些可以帮助您入门的代码:
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);
}
}
}
}
}
}
}
答案 5 :(得分:0)
一些提示 -
1)你可以使用shift并点击变量/ method / class,这样你就可以正确使用它。
2)右键单击 - 打开调用层次结构将显示调用变量的确切位置。
3)Command和O将向您显示课程大纲,以便您快速导航
4)快速类型Hierchy将向您展示变量在类的宏方案中的位置/位置。
希望有所帮助
答案 6 :(得分:0)
打印出大对象的值通常很有帮助,因此您可以仔细查看它们。在Java和C ++中,我编写了用于打印对象的所有内容的函数,以及用于处理嵌入对象的递归。调试对象变量的硬拷贝是旧时尚,但对于非常复杂的情况,它将导致更多的发现。
答案 7 :(得分:0)
也许是一种完全不同的方法。尝试将对象(分解后)放入内存数据存储(请参阅http://www.google.de/search?hl=en&q=java+inmemory+data+store+search),然后使用其搜索功能。在进行测试后,您应该感觉它是否在您的情况下表现更好。如果你仔细阅读对象,也许使用内存数据库会更好。
答案 8 :(得分:0)
我认为你必须使用Java Reflection API。看看这里: http://java.sun.com/developer/technicalArticles/ALT/Reflection/
答案 9 :(得分:0)
免责声明:代码蛮力且非常丑陋。我只是想展示一下OP想要用这些基本想法做什么的可能性:
Field#setAccessible
Iterable
,Enumeration
,原始包装类和String
@Thomas Mueller's answer包含这些元素,但我的#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(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);
}
输出结果为:
|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:[]
答案 10 :(得分:-1)
如果复杂对象由字符串,列表,地图等java对象组成, 你可以通过反射迭代它们,当你发现你正在看的“对象”是一个String或int(等)调用toString
如果您的起始对象包含“自定义”对象
,则此方法无效