我有巨大的對象,我有它的課程,我從中提取一些值,但因爲它真的很大,我不知道在哪個列表或我在找什麼值因爲是。在java中的擊穿對象
有沒有辦法創建某種對象分解路由和搜索每個部分的值我期待,它是隱藏在對象的某個地方,我只是無法找到它在eclipse中它的嵌套。
我想過使用反射去低谷對象類的所有領域,並搜索每個領域內的值(列表內的列表(列表等列表))中的值。任何其他想法?
遺憾的是沒有這些答案幫助我,我開始賞金
我有巨大的對象,我有它的課程,我從中提取一些值,但因爲它真的很大,我不知道在哪個列表或我在找什麼值因爲是。在java中的擊穿對象
有沒有辦法創建某種對象分解路由和搜索每個部分的值我期待,它是隱藏在對象的某個地方,我只是無法找到它在eclipse中它的嵌套。
我想過使用反射去低谷對象類的所有領域,並搜索每個領域內的值(列表內的列表(列表等列表))中的值。任何其他想法?
遺憾的是沒有這些答案幫助我,我開始賞金
我假設你只是想找到一個特定的值並追蹤它的來源。而這一切,你想在調試時做。我會建議兩個選項。
選項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"
]
}
1選項 轉換/序列化對象到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)您可以使用移動和點擊變量/方法/類,這將帶來你對它正確。
2)右鍵單擊 - 打開呼叫層次結構將顯示您確切地調用變量的位置。
3)命令和O會告訴你德班的輪廓讓你可以快速瀏覽
4)快速型Hierchy會告訴你如何/在哪裏你的變量在課堂上坐着的宏偉計劃。
希望幫助
它常常有助於打印出一個大對象的值,這樣你就可以查看他們仔細。在Java和C++中,我編寫了函數來打印對象的所有內容,以及用於處理嵌入對象的遞歸。調試對象變量的硬拷貝是舊式的,但對於非常複雜的情況,它會導致更多的發現。
'它通常有助於打印出一個大對象的值,以便您可以仔細查看它們這就是我之後 – ant 2010-08-10 14:45:43
如果該類是可序列化的,我經常使用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);
}
好的解決方案太糟糕了,它不能正常工作 – ant 2010-08-13 12:45:02
創建一些靜態方法,假設:
Map<String, Object> DebugHelper.breakDown(Object bean)
並執行它(例如)作爲數據挖掘。 org.apache.pivot.beans.BeanAdapter的用法 - 例如可以幫助您將bean視爲普通Map,或者(如您所寫 - 您需要深入挖掘)使用遞歸將所有屬性分組爲單個大Map
另一個有用的簽名:
Map<String, Object> DebugHelper.breakDown(Object bean, String lookFor)
其中用於從地圖第一種方法的發現價值的子串第二個參數。
這對您有幫助嗎?因爲您可以使用eclipse的檢查器在任何時間調試時計算此方法的結果
如何使用Jakarta-Commons的ToStringBuilder org.apache.commons.lang.builder package
。
System.out.println (ToStringBuilder.reflectionToString(YOUR_OBJECT));
我認爲你需要使用反射來獲取數據。下面是一些代碼,應該讓你開始:
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);
}
}
}
}
}
}
}
以及如果複雜的對象是像字符串,列表,地圖,這樣的java對象組成, 可以通過反射在它們之間迭代,當你發現「對象」你看到的是一個字符串或INT(並且這樣的)調用的toString
如果你的出發對象包含一個「自定義」對象
也許完全不同的方法這不會工作。嘗試將對象(分解後)放入內存數據存儲區(請參閱http://www.google.de/search?hl=en&q=java+inmemory+data+store+search),並使用其搜索功能。進行測試後,您應該會感覺到它在您的情況下表現更好。如果您仔細閱讀對象,那麼使用內存數據庫可能會更好。
我認爲你必須使用Java反射API。看看這裏: http://java.sun.com/developer/technicalArticles/ALT/Reflection/
聲明:該代碼是蠻力和非常醜陋的。我只是想證明做什麼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:[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:[]
看看是否有幫助:http://stackoverflow.com/questions/301536/what-is-the-java-equivalent-of-php-var-轉儲 – 2010-08-10 11:54:19
聽起來像你需要重構和重新設計這個對象。 – Oded 2010-08-10 11:54:38
既然你在這裏問,我假設「問發明家」的答案已經被追究或者是不可能的? – Carl 2010-08-10 11:55:51