Java反射,传入对象的调用方法';s级

Java反射,传入对象的调用方法';s级,java,reflection,Java,Reflection,刚刚开始学习和了解java反射,如果您能在这个问题上提供帮助,我们将不胜感激 我正在尝试编写一个方法,它如下所示: private void myMethod(列表testSub){ testSub.forEach(s->assertEquals(s.getSource(),“TEST”); } 但是它显示了一个错误,因为java不知道testSub的类是否有getSource()这个方法,它希望我将s.getSource()强制转换为一个已知的类 我想让java知道testSub类中的itm

刚刚开始学习和了解java反射,如果您能在这个问题上提供帮助,我们将不胜感激

我正在尝试编写一个方法,它如下所示:

private void myMethod(列表testSub){
testSub.forEach(s->assertEquals(s.getSource(),“TEST”);
}
但是它显示了一个错误,因为java不知道testSub的类是否有getSource()这个方法,它希望我将s.getSource()强制转换为一个已知的类

我想让java知道testSub类中的itmes有这个getSource()方法,它可以被调用并且可以安全地调用

提前谢谢

----------------------------更新---------------------- 选择使用以下方式:

private void myMethod(列表testSub,类clazz){
testSub.forEach->assertEquals(clazz.getMethod(“getSource”).invoke,“TEST”);
}

必须为其捕获异常,但有效。

在类型变量定义中添加绑定:

private <T extends HasSource> void myMethod (List<T> testSub) {
编译器将知道
T
实际上是
HasSource
的一个子类,因此它有
getSource()
方法


当然,要利用此解决方案,您需要使所有要用作
testSub
元素的类实现
HasSource
接口。

有两种方法可以调用
getSource()
方法

一个是普通方法调用表达式,类似于
object.getSource()
。只有当编译器知道
对象
属于具有
getSource()
方法的类时,才可能这样做

在您的例子中,编译器只知道
s
属于泛型类型
T
,它是无界的,因此可以是任何类,甚至是
Object
,并且编译器无法确认是否存在getSource()方法

如果列表元素没有使用
getSource()
方法的公共父类或接口,可以使用instanceof/cast组合。这很难看,但如果您真的了解可能的元素类,可能会对您有用

for (T s : testSub) {
    if (s instanceof Class1) {
        assertEquals(((Class1) s).getSource(), "TEST"));
    } else if (s instanceof Class2) {
        assertEquals(((Class2) s).getSource(), "TEST"));
    } else {
        throw new IllegalArgumentException();
    }
}

另一种方法是使用反射。您可以找到
方法m=s.getClass.getMethod(“getSource”)
,如果不为null,则执行
m.invoke
。但这比instanceof/cast解决方案更难看,而且速度肯定要慢得多。

在示例代码中没有使用反射。你是说泛型吗?“必须为它捕获异常,但有效”:因为这看起来像一个测试用例,我希望你在出现异常时重新抛出异常或
fail()
。这不是我想要的,只有两个类将传递给myMethod,它们都已定义,并且都有getSource()方法。@DawnZHANG,罗曼给出了一个例子,而不是一个精确的解决方案。您必须选择一个绑定,它是列表中所有对象类的实际超类型。@DawnZHANG您需要告诉编译器,
T
不仅表示任何类,而且表示具有
getSource()
方法的类。要使它适用于两个类,您需要让它们扩展一个公共基类(或实现一个接口),或者让其中一个扩展另一个,然后使用定义
getSource()
的父类作为类型绑定。我无法执行以下操作:testSub.get(0).getClass()要获取传入的任何类?当然可以,但是必须将其与已知类匹配,并将元素强制转换为其中一个(匹配的那个)。引入泛型部分是为了避免这种铸造。另一种选择是使用反射,这非常难看和不安全。我使用的方法是m=s.getClass.getMethod(“getSource”),但为什么会这么慢?@DawnZHANG它会比较慢,因为在每次迭代中,它都必须搜索类及其超类,寻找具有给定名称的方法,并动态调用该方法。此外,您有两个完全不同的
getSource()
方法,使得HotSpot引擎无法进行任何优化,例如内联。
public interface HasSource {
    String getSource()
}
for (T s : testSub) {
    if (s instanceof Class1) {
        assertEquals(((Class1) s).getSource(), "TEST"));
    } else if (s instanceof Class2) {
        assertEquals(((Class2) s).getSource(), "TEST"));
    } else {
        throw new IllegalArgumentException();
    }
}