[英]Use Class parameter for generic type (e.g ArrayList)
我正在尝试创建一个通用方法来处理 Java 中不同类型的 ArrayList。 这些类型完全不同,但都包含一个相同的参数,我想在此方法中对其进行评估。
但是我无法使用给定的类信息创建正确的ArrayList<type>
。
我究竟做错了什么?
private String test(ArrayList<?> list, Class<?> type) {
for(type i : list){ // for (type i : (ArrayList<type>) list){
// do something
}
return "xxx"
}
private void init() {
ArrayList<Type_1> a1 = new ArrayList<>();
ArrayList<Type_2> a2 = new ArrayList<>();
String s1 = test(a1, Type_1.class);
String s2 = test(a2, Type_2.class);
}
更新找到解决方案
private String test(ArrayList<?> list) {
for (Object i : list){
try {
Method m = i.getClass().getMethod("getName", null);
System.out.println(m.invoke(i));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//Handle Exception
}
}
}
您需要声明一个显式类型参数:
private <T> String test(ArrayList<T> list, Class<T> type) {
for (T i : list) {
// do something with 'i'
}
return "xxx"
}
如果您不需要Class<T>
参数,则可以将其省略; 例如
private <T> String test(ArrayList<T> list) {
for (T i : list) {
// do something
}
return "xxx"
}
如果您打算创建该类的实例...或该类的数组,您通常只需要传递一个Class<T> type
的对象。
注释掉的代码版本不会编译,因为它混合了编译时和运行时类型。 在
for (type i : (ArrayList<type>) list) {
编译器需要在编译时知道类型代表什么type
。 但它是一个运行时变量。 但这甚至在此之前也是无效的,因为 Java 语法在那时需要类型的标识符......而不是变量的标识符。
我创建了一个与这两种解决方案相关的混合答案:
第一个是通过一个简单的接口MyType
完成的,该接口定义了Type_1
和Type_2
类的契约方法。 这是干净且正确的 Java 方式。 这样编译器就会告诉你是否可以执行某些操作。 这也表明初学者在实施想法的概念上存在问题。
缺点是所有类都必须实现该接口(可以在其继承层次结构的任何地方定义)。
但是 Java 完全是关于类型安全和编译器警告的优势。 所以这显然是首选方式。
可以使用反射来完成这项任务,是的。 但不一定是个好主意。 使用反射,存在多个问题:
因此,如果远离反射是可能且容易的,您应该避开。 特别是如果这有一个如此简单的适当解决方案。
(我还用反射清理了你的代码,那里有一些小的不一致,不会让它编译)
package stackoverflow;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class SimpleInterfacing {
interface MyType {
String getName();
}
static class Type_1 implements MyType {
@Override public String getName() {
return "This is type 1";
}
}
static class Type_2 implements MyType {
@Override public String getName() {
return "This is type 2";
}
}
private String test(final ArrayList<? extends MyType> list) {
String returnValue = null;
for (final MyType t : list) {
// do something
System.out.println("Got name: " + t.getName());
returnValue = t.getName();
}
return returnValue; // returns last value, null is lists are empty
}
private void init() {
final ArrayList<Type_1> a1 = new ArrayList<>();
a1.add(new Type_1());
final ArrayList<Type_2> a2 = new ArrayList<>();
a2.add(new Type_2());
{
final String s1 = test(a1);
System.out.println("s1 is " + s1);
}
{
final String s2 = test(a2);
System.out.println("s2 is " + s2);
}
{
test_reflection(a1);
test_reflection(a2);
}
}
public static void main(final String[] args) {
new SimpleInterfacing().init();
}
private String test_reflection(final ArrayList<?> list) {
for (final Object i : list) {
try {
final Method m = i.getClass().getMethod("getName");
System.out.println("Invoked: " + m.invoke(i));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//Handle Exception
ex.printStackTrace();
}
}
return null;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.