Java-Java.lang.NoSuchMethodException

Java-Java.lang.NoSuchMethodException,java,inheritance,reflection,methods,Java,Inheritance,Reflection,Methods,我尝试使用这个代码(Updatem_set在for循环中使用,该循环通过几个使用不同类型参数的方法。如果我在getMethod中添加例如int.class,我将在一次迭代后得到错误,因为下一个方法将需要String.class。是否可以使用反射解决此类问题?) 我得到这个错误: Exception in thread "main" java.lang.NoSuchMethodException: test.NormalChair.setHeight() at java.lang

我尝试使用这个代码(Updatem_set在for循环中使用,该循环通过几个使用不同类型参数的方法。如果我在
getMethod
中添加例如int.class,我将在一次迭代后得到错误,因为下一个方法将需要String.class。是否可以使用反射解决此类问题?)

我得到这个错误:

 Exception in thread "main" java.lang.NoSuchMethodException: test.NormalChair.setHeight()
        at java.lang.Class.getMethod(Class.java:1655)
        at test.ProductTrader.create(ProductTrader.java:68)
        at test.Test.main(Test.java:32)
在错误中,它显示它试图在我使用此方法的类中查找方法。但该方法在父类中,并且是公共方法。我知道如果我使用
getDeclaredMethod
,它将给出类似的错误,但为什么它使用
getMethod
给出此错误

我的类thas有以下方法:

public abstract class AbstractChair {
    public String name;
    public int height;
    public AbstractChair() {
    }

    public AbstractChair(String name, int height){
        this.name = name;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }   
}
我尝试在其上使用此方法的类:

public class NormalChair extends AbstractChair {
    public NormalChair() {
        super();
    }

    public NormalChair(String name, int height) {
        super(name, height);
    }


    // Copy constructor
    public NormalChair(NormalChair chair) {
      this(chair.getName(), chair.getHeight());
    }

}
更新2

如果我这样做:

if(method_name == "setHeight"){
  Method m_set = product.getClass().getMethod(method_name, int.class);
  m_set.invoke(product, method_value);
}
else if (method_name == "setName")
{
  Method m_set = product.getClass().getMethod(method_name, String.class);
  m_set.invoke(product, method_value);
}

然后错误消失。有人能建议更通用的方法吗?

使用
product.getClass().getMethod(“setHeight”,int.class);
。您必须传递方法参数类型以指向方法签名。

似乎忘记了传递方法所需的参数类型(请记住,可以使用不同的参数类型重载方法)。请看一下您的代码,那里没有
setHeight()
方法,只有
setHeight(int)
。您应该尝试类似的方法

Method m_set = product.getClass().getMethod(method_name,method_value.getClass());
m_set.invoke(product, method_value);
Method[] methods = product.getClass().getMethods();
for (Method m : methods){
    System.out.println(m);
    if (m.getName().equals("setHeight")){
        m.invoke(product, method_value);
        break;
    }
}

由于基本类型可能会有问题,所以您可以随意使用。假设您希望查找的类中只有一个同名的方法,您可以迭代所有公共方法,将其名称与您要查找的方法进行比较,然后使用所需的参数调用它。例如

Method m_set = product.getClass().getMethod(method_name,method_value.getClass());
m_set.invoke(product, method_value);
Method[] methods = product.getClass().getMethods();
for (Method m : methods){
    System.out.println(m);
    if (m.getName().equals("setHeight")){
        m.invoke(product, method_value);
        break;
    }
}

另一种可能更好的方法是使用
java.bean
包中的类,如
PropertyDescriptor
。有了这个类,您可以找到特定属性的getter和setter。请注意
setHeight
的属性是
height
,所以您需要像这样使用它

Method setter = new PropertyDescriptor("height", product.getClass()).getWriteMethod();
setter.invoke(product, method_value);

您的方法签名似乎与声明的方法不匹配。请不要将字符串与
=
进行比较。而应使用
equals
类似的
stringOne.equals(stringTwo)
。更多信息我可以通过反射从值中获取类型吗?因为类型可能会根据它将尝试获取的方法的类型而变化。@Andrius确定,请使用
方法\u值。getClass()
。如果
方法\u值的类型是声明中实际类型的子类,我不确定这是否有效。(更新:否:)在
getMethod
中使用-
method\u value.getClass().getTypeParameters()
会产生错误:
类型类中的方法getMethod(String,Class…)不适用于参数(String,TypeVariable[])
@Andrius
Class.getTypeParameters()
用于处理泛型。我不认为这是您在这里要找的。它不允许我输入valuesTypes…我可以以某种方式输入类型列表并让java选择适合的类型吗?现在,我得到:
参数类型不匹配
错误,因为我使用for循环,它使用很少的方法来设置对象的值(和方法有不同的类型)不,您不能,如果很少有方法可以匹配您的类型的某些子集,这将导致潜在的问题。您需要具体说明哪些参数类型具有您感兴趣的方法。但是,您的类似乎没有重载方法,因此您的类中只有一个具有相同名称的方法。如果这是真的,那么您可以接受所有m使用
getMethods()
方法,并对其进行迭代,得到一个具有
getName()的方法。等于(方法名称)
然后调用
method.invoke(产品、方法值)
@Andrius看看我的最新答案。你可能会在那里发现一些有趣的东西。当java开始寻找方法
setName
时,在一次
for
迭代之后,它不会给我错误吗?@Andrius你是什么意思?假设类
setName
for
循环中只有一个方法l找到它,用你将要传递的数据执行它,
invoke
,并停止其他方法的循环(因为根据之前的假设,不会有任何方法被命名为
setName
)。