java动态调用方法

java动态调用方法,java,reflection,Java,Reflection,我试图弄清楚如何动态调用一个方法。我有一个描述方法名的字符串,但我不知道如何做。我认为这可以通过反思来实现,但没有取得任何成功。范例 set.add(vehicleConfiguration.getVehicleYear.getName()); set.add(vehicleConfiguration.getVehicleMake().getName()); set.add(vehicleConfiguration.getVehicleModel().getName()); 您会注意到,除

我试图弄清楚如何动态调用一个方法。我有一个描述方法名的字符串,但我不知道如何做。我认为这可以通过反思来实现,但没有取得任何成功。范例

set.add(vehicleConfiguration.getVehicleYear.getName());

set.add(vehicleConfiguration.getVehicleMake().getName());

set.add(vehicleConfiguration.getVehicleModel().getName());
您会注意到,除了getVehicleYear等之外,所有的方法调用都是相同的

我有一个描述方法名称的字符串,只是不知道如何使用它

我经过深思熟虑终于做到了这一点,但失败了

set.add(Class.forName("VehicleConfiguration").getMethod("vehicleMake", null).getName());

提前谢谢

您必须使用实际的方法名称:
getVehicleMake
,而不是
vehicleMake


此外,如果你把它当作锻炼以外的任何东西,不要自己玩。使用Commons
BeanUtils
或Spring的
BeanRapper

您要找的类是。请仔细阅读相应的javadoc

例如,您可以使用

// assumign `getVehicleMake` is the name of the method and it accepts no parameters
Method method = VehicleConfiguration.class.getMethod("getVehicleMake"); 
// VehicleConfiguration.class can be replaced by
// Class.forName("VehicleConfiguration") 
// if VehicleConfiguration is the fully qualified, ie. with packages, name of the class
// other you need Class.forName("com.yourpackage.VehicleConfiguration")
然后需要在类的实例上调用()这个方法

VehicleConfiguration instance = new VehicleConfiguration();

Object returnObject = method.invoke(instance); // assuming no parameters
然后要调用
getName()
,需要将返回的对象强制转换为具有该方法的类型。假设
getMake()
VehicleMake
类型的方法,请这样调用它

((VehicleMake)returnObject).getMake();

扩展我的评论,因为您展示的所有方法都有一个
getName()
方法,让我们创建一个简单的类来定义它:

class Nameable
{
    private String name;

    public Nameable(final String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return this.name;
    }
}
现在,当您为Make、Model和Year创建对象时,它们都可以使用该类,以便可以互换使用,然后可以组合成一辆
汽车

class Car
{
    public final Nameable make;
    public final Nameable model;
    public final Nameable year;

    public Car(Nameable make, Nameable model, Nameable year)
    {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    public Nameable getInfo(final String info)
    {
        switch(info)
        {
            case "make": return this.make;
            case "model": return this.model;
            case "year": return this.year;
        }
        return null;
    }
}
那么一个简单的实现就是:

class PaganiZonda2006 extends Car
{
    public PaganiZonda2006()
    {
        super(new Nameable("Pagani"), new Nameable("Zonda"), new Nameable("2006"));
    }
}
最后,当你想把信息拿出来时,你可以这样读:

public static void main(String[] args)
{
    Car car = new PaganiZonda2006();
    System.out.println(car.getInfo("make").getName()); //Pagani
    System.out.println(car.getInfo("model").getName()); //Zonda
    System.out.println(car.getInfo("year").getName()); //2006
}

这最终成为我的最终解决方案,它是MrLore和Sotirios Delimanolis解决方案的组合。此解决方案是完全动态的,不使用任何条件

此类通过传入属性名来执行名称搜索

String propertyName = "vehicleYear";

vehicleConfiguration.getInfo(propertyName).getName()

propertyName = "vehicleMake";

vehicleConfiguration.getInfo(propertyName).getName()
此类表示车辆配置

@Entity
public class VehicleConfiguration extends StatefulEntity {

    @ManyToOne
    @JoinColumn(name = "year_id")
    private VehicleYear vehicleYear;

    @ManyToOne
    @JoinColumn(name = "make_id")
    private VehicleMake vehicleMake;

    public LookupBaseEntity getInfo(final String fieldName) {
        try { 
            String methodName = WordUtils.capitalize(fieldName);
            Method method = VehicleConfiguration.class.getMethod("get" + methodName);  
            return (LookupBaseEntity) method.invoke(this); 
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            Logger.getLogger(VehicleConfiguration.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
}
此类表示车辆EAR

@Entity
public class VehicleYear extends LookupBaseEntity {

}
此类代表车辆制造商

@Entity
public class VehicleMake extends LookupBaseEntity {

}
它们都扩展了LookupBaseEntity

public class LookupBaseEntity extends StatefulEntity {

    private String name;

    public String getName() {
        return name;
    }

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

}

谢谢chrylis,我错过了那个。另外两个小问题,null会发生什么,当我调用getName()时,它实际上是调用我方法的getName(),还是从getMethod()调用getName()?方法名称的更改还不够。调用
getName()
是错误的。@George The
null
告诉反射系统,您需要名为
getVehicleMake
的方法,该方法不带任何参数,是的,正如Sotirios所指出的,您将在
方法上调用
getName()
,而不是在您想要的结果上调用(您没有调用
invoke()
方法
)。
getVehicleModel()
getVehicleMake()
getVehicleYear()
的返回类型是什么?如果它们都有
getName()
方法听起来泛型比反射更能解决您的问题。或者甚至只是一个
if
/
else
块。反射99%的时间都是多余的。@MrLore,我愿意接受一些想法,请在下面用泛型来展示一个例子。如果可能的话,我宁愿远离if/else。谢谢你去castreturnObject,是动态的还是不动态的?@George不完全是,你需要知道类型,这样代码才能编译。还有一些解决方法,比如使用反射。你不能调用你不知道的类型的方法。谢谢,我最终使用了你的解决方案。它不像我希望对switch语句所做的那样完全是动态的,但我确实比其他解决方案更喜欢它。