在Java中,是否可以编写单个函数或类来处理任意多维ArrayList?

In Java, is writing a single function or class to handle arbitrary multidimensional ArrayList possible?

本文关键字:处理 任意多 ArrayList 函数 单个 Java 是否      更新时间:2023-10-16

在C++中,我可以编写 2 个模板类,例如:

#include <stdio.h>
#include <vector>
template <typename T>
class Printer{
public:
static void print(T& v){
printf("%d ",v.getValue());
}
};
template <typename T,typename Alloc>
class Printer<std::vector<T,Alloc> >{
public:
static void print(std::vector<T,Alloc>& v){
for(T& e : v){
Printer<T>::print(e);
}
printf("n");
}
};

以便它可以接受任意自定义对象类型并在vectorvectorvector...(无穷大嵌套vector):

class Student{
public:
int value;
Student(int value){ this->value=value; }
int getValue() const { return this->value; }
};
class Teacher{
public:
int value;
Teacher(int value){ this->value=value; }
int getValue() const { return this->value*10; }
};
int main(){
std::vector<Student> v2 = {Student(10),Student(20)};
Printer<std::vector<Student> >::print(v2);
std::vector<std::vector<Teacher> > v3 = {{Teacher(30),Teacher(40)},{Teacher(50),Teacher(60),Teacher(70)}};
Printer<std::vector<std::vector<Teacher> > >::print(v3);
return 0;
}

前提是自定义对象StudentTeacher具有getValue()功能。

但是在 Java 中,我怎么能写出像上面这样接受两者的东西

ArrayList<Student > v2;

ArrayList<ArrayList<Teacher> > v3;

(也ArrayListArrayListArrayList中......)以通用方式?

当我尝试转换代码时,很少出现问题,首先,泛型对象方法无法编译:

public static void <T> print(T t){
System.out.print(t.getValue());
}

而且我不知道如何将std::vector< T , Alloc >转换为 Java,因为ArrayList只接受 1 个模板参数。

注意:我希望vector成为专用模板,因为当我想添加对int的支持时:

std::vector<int> v1={1,2};
Printer<std::vector<int> >::print(v1);

我可以添加

template <>
class Printer<int>{
public:
static void print(int& v){
printf("%d ",v);
}
};

到代码。

有一个简单但非常丑陋的解决方案:转向原始类型,或者因为这是非常糟糕的做法,那就去? extends Object

。你看,最后,Java 泛型根本不是现代C++模板的匹配。泛型不是模板 - 例如:不能将它们用于基元类型,例如int。您只能使用List<Integer>。或者一些T extends Number,当你需要一个需要双精度、浮点数、...对象也是如此。

关键是:最终,在运行时,所有这些"泛型"都消失了。所有这些列表都只包含对象

所以,从理论上讲,如果你真的想要一个"解决方案",那么你可以选择

void foo(List<? extends Object> thingies) 

避免所有类型的信息...并在运行时执行反射魔术,以确定如何处理该列表的确切内容。

"更多Java"解决方案需要您退后一步。如前所述,Java并不C++,所以你根本不应该期望Java具有相同水平的"表现力"。

相反:学习如何正确使用Java泛型和Java类型系统;并基于这些知识构建解决方案*。

或者换句话说:如果您需要C++解决方案,请使用C++。Java永远不会满足这个要求(至少不是100%)。

您可以通过instanceof检查来做到这一点:

public static <T> void print(List<? extends T> list) {
for (final T t : list) {
if (t instanceof List) print((List) t);
else System.out.println(t);
}
}

但是,当然,如果方法未在接口中的任何位置或某处定义,则不能T.getValue()使用方法。如果T是接口

public interface T {
String getValue();
}

那么你有这样的东西

public static void print(List<? extends Object> list) {
for (Object t : list) {
if(t instanceof T) System.out.println(((T)t).getValue());
else if (t instanceof List) print((List) t);
else continue; // I don't know this type.
}
}

但它随后会附加到您的接口T。问题实际上在于您无法访问未定义的方法,至少没有反射。C++到底是怎么做到的?

编辑:这当然是行不通的,如果你有一个T的实现,它也实现了List接口。