![](/img/trans.png)
[英]How to retrieve a Set of String from the field of each element in a List of objects that is contained in an object?
[英]Retrieve specific values of instance variable from each object of a list containing Objects of different classes
我有一個列表,其中包含不同類的對象,比如 A、B、C、D、E、F、G。每個對象(A、B、C、D、E、F、G)都有一個實例變量“name “ 在里面。 我想遍歷列表並檢索存儲在每個對象的名稱變量中的值。
我試過下面的代碼
List<String> str = new ArrayList<String>();
for(Object obj: list_containing_different_objects) {
str.add(obj.name) or str.add(obj.getName());
}
但是obj.name
會出錯,因為我不知道存儲 A、B、C、D、E、F 的list_containing_different_objects
中的確切索引(因為每次都可能不同)。 另外,如果我知道該索引,我將無法找到任何解決方案。有人可以幫助我嗎?
這取決於類A
、 B
、 C
、 D
、 E
、 F
和G
是否具有公共基類 class 或接口。
如果沒有,您可以創建一個如下所示的界面:
interface Nameable {
String getName();
}
然后讓每個類實現這個接口。 然后您可以輕松地在每個對象上調用getName()
方法:
for (Nameable nameable : listContainingDifferentObjects) {
str.add(nameable.getName());
}
instanceof
否則,如果這些類不會或不能實現公共接口或擴展基類 class,那么這些類是不相關的,盡管有一個同名的字段。
在這種情況下,您最終必須檢查每種類型,對其進行轉換並使用字段1 :
for (Nameable nameable : listContainingDifferentObjects) {
if (obj instanceof A) {
str.add(((A) obj).name);
}
else if (obj instanceof B) {
str.add(((B) obj).name);
}
// et cetera
}
如果你的類沒有實現通用類型,但仍然有一個同名的字段,我會重新考慮設計。
vsfDawg 提出了使用反射來動態調用getName()
方法或訪問name
字段的方法。 雖然確實可以讓它發揮作用,但如果可能的話,您應該避免使用它,並且只有在沒有其他方法的情況下才使用它。 ➤ 更多細節
1從版本 16 開始,Java 支持模式匹配,簡化了檢查類型、轉換和使用值的過程。 例如:
for (Object obj : listContainingDifferentObjects) {
if (obj instanceof A a) {
str.add(a.name());
}
else if (obj instanceof B b) {
str.add(b.name());
}
// et cetera
}
有關更多詳細信息,請參閱本文。
使用反射
假設這些類不共享一個公共基礎 class 或包含您可以使用反射調用該方法的方法的接口。 有很多錯誤處理可以使其正常工作,但下面的示例將錯誤處理掉並強制調用者處理它。
public String getName(Object named)
throws NoSuchMethodException,
SecurityException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
{
Method method = named.getClass().getMethod("getName");
return (String) method.invoke(named);
}
以下迭代對象列表並調用上述方法。 由於異常正在滲透,因此此方法必須處理它們。 您可以在此處捕獲異常,但為了完整起見,我保留了完整列表。
public void printNames(List<Object> namedObjects) {
for (Object obj : namedObjects) {
try {
System.out.println(getName(obj));
} catch (NoSuchMethodException |
SecurityException |
IllegalAccessException |
IllegalArgumentException |
InvocationTargetException e) {
System.err.println("Failed to invoke getName on object - skipping");
}
}
}
我喜歡'MC Emperor's answer about common base class,這是通往go的方式。但是,如果你沒有那個公共class並且無法更改代碼。 可以使用反射來實現所需要的。
下面的代碼甚至不需要 getter (getName()),它只需要一個“名稱”字段。
class A {
public A(String aName) {
name = aName;
}
public String name;
}
class B {
public B(String aName) {
name = aName;
}
public String name;
}
class C {
public C(String aName) {
name = aName;
}
public String name;
}
@Test
public void testClasses() {
List<String> str = new ArrayList<>();
List<? extends Object> list_containing_different_objects = Lists.list(new A("a"), new B("b"),
new C("c"), new A("aa"));
for (Object commonObj : list_containing_different_objects) {
try {
Field field = commonObj.getClass().getField("name");
String nameValue = (String) field.get(commonObj);
str.add(nameValue);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
// print the results
str.forEach(System.out::println);
}
此測試執行的結果如下所示:
a
b
c
aa
我希望這可以幫到你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.