从包含不同 类 对象的列表的每个对象中检索实例变量的特定值
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
会给出错误,因为我不知道 list_containing_different_objects
中的确切索引(因为每次都可能不同),其中 A、B、C、D、E、 F 被存储。另外,如果我知道索引,我无法理解 it.Can 有人能帮我解决这个问题吗?
这取决于class是A
、B
、C
、D
、E
、F
和 G
有共同的基础 class 或接口。
普通基础类型
如果没有,您可以创建一个如下所示的界面:
interface Nameable {
String getName();
}
然后让每个 classes 实现这个接口。然后您可以轻松地在每个对象上调用 getName()
方法:
for (Nameable nameable : listContainingDifferentObjects) {
str.add(nameable.getName());
}
instanceof
否则,如果 classes 不会或不能实现公共接口或扩展基础 class,则 classes 无关,尽管有一个同名字段。
在那种情况下,您最终必须检查每种类型,转换它并使用字段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
}
如果您的 classes 没有实现通用类型,但仍然有一个同名字段,我会重新考虑设计。
反思
vsfDawg 想出了使用反射来动态调用 getName()
方法或访问 name
字段。虽然一个 确实可以 使它工作,但如果可能的话,你应该避免使用它,并且只有在没有其他方法的情况下才使用它。 ➤ More details
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
}
有关详细信息,请参阅 this article。
使用反射
假设 classes 不共享包含方法的公共基础 class 或接口,您可以使用反射来调用方法。有很多错误处理可以使其正常工作,但下面的示例将错误处理掉并强制调用者处理它。
public String getName(Object named)
throws NoSuchMethodException,
SecurityException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
{
Method method = named.getClass().getMethod("getName");
return (String) method.invoke(named);
}
下面遍历一个List of objects并调用上面的方法。由于异常正在渗透,因此此方法必须处理它们。您可以在此处捕获异常,但为了完整起见,我保留了完整列表。
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,这是要走的路。
但是,如果您没有那个通用的 class 并且无法更改代码。
可以使用反射来实现所需要的。
下面的代码甚至不需要 getter (getName()),它只需要一个 'name' 字段。
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
希望对您有所帮助。
我有一个列表,其中包含不同 类 的对象,例如 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
会给出错误,因为我不知道 list_containing_different_objects
中的确切索引(因为每次都可能不同),其中 A、B、C、D、E、 F 被存储。另外,如果我知道索引,我无法理解 it.Can 有人能帮我解决这个问题吗?
这取决于class是A
、B
、C
、D
、E
、F
和 G
有共同的基础 class 或接口。
普通基础类型
如果没有,您可以创建一个如下所示的界面:
interface Nameable {
String getName();
}
然后让每个 classes 实现这个接口。然后您可以轻松地在每个对象上调用 getName()
方法:
for (Nameable nameable : listContainingDifferentObjects) {
str.add(nameable.getName());
}
instanceof
否则,如果 classes 不会或不能实现公共接口或扩展基础 class,则 classes 无关,尽管有一个同名字段。
在那种情况下,您最终必须检查每种类型,转换它并使用字段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
}
如果您的 classes 没有实现通用类型,但仍然有一个同名字段,我会重新考虑设计。
反思
vsfDawg 想出了使用反射来动态调用 getName()
方法或访问 name
字段。虽然一个 确实可以 使它工作,但如果可能的话,你应该避免使用它,并且只有在没有其他方法的情况下才使用它。 ➤ More details
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
}
有关详细信息,请参阅 this article。
使用反射
假设 classes 不共享包含方法的公共基础 class 或接口,您可以使用反射来调用方法。有很多错误处理可以使其正常工作,但下面的示例将错误处理掉并强制调用者处理它。
public String getName(Object named)
throws NoSuchMethodException,
SecurityException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
{
Method method = named.getClass().getMethod("getName");
return (String) method.invoke(named);
}
下面遍历一个List of objects并调用上面的方法。由于异常正在渗透,因此此方法必须处理它们。您可以在此处捕获异常,但为了完整起见,我保留了完整列表。
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,这是要走的路。 但是,如果您没有那个通用的 class 并且无法更改代码。 可以使用反射来实现所需要的。
下面的代码甚至不需要 getter (getName()),它只需要一个 'name' 字段。
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
希望对您有所帮助。