In C++, I can write 2 template classes, like:
#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");
}
};
so that it can accept arbitrary custom object type and vector
in vector
in vector
... (infinity nested 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;
}
provided the custom object Student
and Teacher
has getValue()
function.
But in Java, how can I write something like above that accepts both
ArrayList<Student > v2;
and
ArrayList<ArrayList<Teacher> > v3;
(and also ArrayList
in ArrayList
in ArrayList
in...) in generic way?
Few problems occurs when I tried to convert the code, first, the generic object method cannot compile:
public static void <T> print(T t){
System.out.print(t.getValue());
}
and I don't know how to convert std::vector< T , Alloc >
in to Java because ArrayList
only accepts 1 template parameter.
Note: I want vector to be the specialized template because when I want to add support of int
:
std::vector<int> v1={1,2};
Printer<std::vector<int> >::print(v1);
I can just add
template <>
class Printer<int>{
public:
static void print(int& v){
printf("%d ",v);
}
};
to the code.
You can do it with instanceof
checks:
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);
}
}
But of course you can not use a method T.getValue()
if it is not defined anywhere in an interface or somewhere. If T
is an interface
public interface T {
String getValue();
}
then you have something like this
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.
}
}
But it is then attached to your Interface T
. The Problem is really that you can't access methods, which are not defined, at least not without Reflections. How does C++ do this anyway?
EDIT: This will of course not work, if you have an implementation of T
which also implements the List
interface.