有没有办法检查对象是 Java 中的列表还是列表列表
Is there a way to check if object is List or List of Lists in Java
我有一个接收列表类型对象的方法。
它可以是字符串列表或字符串列表列表。
在Java中有没有办法区分这两种对象?
我已经看到 this 问题,但在我的情况下 AFAIK 在这两种情况下对象都是 instanceof List
.
我还在 Python 中看到了几个关于列表列表的类似问题,比如 this.
但是还是没看到Java.
中区分List of Strings和List of Lists of Strings的方法
没有。具体来说,所有列表都只是列表,在 运行 时间,泛型 消失了 。如果编译器/编辑器不能告诉你,那么你也无能为力,它会在 运行 时间告诉你。
为了更具体一点,这两者之间存在 零 区别:
void example() {
List<String> list1 = new ArrayList<String>();
List<List<String>> list2 = new ArrayList<List<String>>();
}
100% 相同 - 您不可能以任何方式或形式对这些列表进行任何操作来区分它们。
你可以绕过它 - 例如,给定一个 List<?>
,如果你 运行 .get(0)
并且你得到的是 List
(再次,无法判断它是 List<String>
还是 List<WhoKnowsWhat>
,只是它是某个列表),那么显然它不是字符串列表。可以是对象列表,也可以是字符串到整数映射列表的列表。无从得知。
如果列表为空,则此 hack 不起作用。这不是个好主意。
那么解决方案是什么?
修正你的代码。在第一种情况下,您不应该出现在场景中。在代码库的某处,您创建一个字符串列表或一个字符串列表列表,然后 return 它。不要这样做,而是想出另一种方法。例如,使用类型层次结构:
public interface FullName {
public List<String> allNames();
public String rendered();
public List<String> get(int idx);
}
然后为每个 'forms' 编写实现。这是给定输入 List<String>
:
的实现
private class SimpleName implements FullName {
private final List<String> name;
public SimpleName(List<String> name) {
this.name = name;
}
@Override public List<String> allNames() {
return name;
}
@Override public String rendered() {
return name.stream().collect(Collectors.joining(" "));
}
@Override public List<String> get(int idx) {
if (idx == 0) return name;
throw new IndexOutOfBoundsException();
}
}
主要是与这些交互的代码不需要关心你有什么样的名字;您可以想象对 'a name' 执行的任何操作都应该封装在此接口中,并且不同的实现可以包含关于如何执行这些任务的所有相关知识(以代码表示)。在调用代码确实需要知道的特殊情况下,它们可以 - 公开方法,或者只进行 instanceof 检查。
我有一个接收列表类型对象的方法。
它可以是字符串列表或字符串列表列表。
在Java中有没有办法区分这两种对象?
我已经看到 this 问题,但在我的情况下 AFAIK 在这两种情况下对象都是 instanceof List
.
我还在 Python 中看到了几个关于列表列表的类似问题,比如 this.
但是还是没看到Java.
没有。具体来说,所有列表都只是列表,在 运行 时间,泛型 消失了 。如果编译器/编辑器不能告诉你,那么你也无能为力,它会在 运行 时间告诉你。
为了更具体一点,这两者之间存在 零 区别:
void example() {
List<String> list1 = new ArrayList<String>();
List<List<String>> list2 = new ArrayList<List<String>>();
}
100% 相同 - 您不可能以任何方式或形式对这些列表进行任何操作来区分它们。
你可以绕过它 - 例如,给定一个 List<?>
,如果你 运行 .get(0)
并且你得到的是 List
(再次,无法判断它是 List<String>
还是 List<WhoKnowsWhat>
,只是它是某个列表),那么显然它不是字符串列表。可以是对象列表,也可以是字符串到整数映射列表的列表。无从得知。
如果列表为空,则此 hack 不起作用。这不是个好主意。
那么解决方案是什么?
修正你的代码。在第一种情况下,您不应该出现在场景中。在代码库的某处,您创建一个字符串列表或一个字符串列表列表,然后 return 它。不要这样做,而是想出另一种方法。例如,使用类型层次结构:
public interface FullName {
public List<String> allNames();
public String rendered();
public List<String> get(int idx);
}
然后为每个 'forms' 编写实现。这是给定输入 List<String>
:
private class SimpleName implements FullName {
private final List<String> name;
public SimpleName(List<String> name) {
this.name = name;
}
@Override public List<String> allNames() {
return name;
}
@Override public String rendered() {
return name.stream().collect(Collectors.joining(" "));
}
@Override public List<String> get(int idx) {
if (idx == 0) return name;
throw new IndexOutOfBoundsException();
}
}
主要是与这些交互的代码不需要关心你有什么样的名字;您可以想象对 'a name' 执行的任何操作都应该封装在此接口中,并且不同的实现可以包含关于如何执行这些任务的所有相关知识(以代码表示)。在调用代码确实需要知道的特殊情况下,它们可以 - 公开方法,或者只进行 instanceof 检查。