有没有办法检查对象是 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 检查。