java动态调用方法

时间:2013-09-07 19:25:50

标签: java reflection

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

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());

提前致谢。

4 个答案:

答案 0 :(得分:4)

您要找的班级是Method。请仔细阅读相应的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")

然后,您需要在班级的实例上invoke()使用此方法。

VehicleConfiguration instance = new VehicleConfiguration();

Object returnObject = method.invoke(instance); // assuming no parameters

然后要调用getName(),您需要将返回的对象强制转换为具有该方法的类型。假设getMake()VehicleMake类型的方法,请将其称为

((VehicleMake)returnObject).getMake();

答案 1 :(得分:2)

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

此外,如果您将此作为练习以外的任何其他内容使用,请不要自己动手。使用Commons BeanUtils或Spring BeanWrapper

答案 2 :(得分:1)

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

class Nameable
{
    private String name;

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

    public String getName()
    {
        return this.name;
    }
}

现在,当您为Make,Model和Year创建对象时,他们都可以使用此类,以便它们可以互换使用,然后可以组合成Car

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
}

答案 3 :(得分:0)

这最终成为我的最终解决方案,它结合了MrLore和Sotirios Delimanolis解决方案。该解决方案在不使用任何条件的情况下是完全动态的。

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

String propertyName = "vehicleYear";

vehicleConfiguration.getInfo(propertyName).getName()

propertyName = "vehicleMake";

vehicleConfiguration.getInfo(propertyName).getName()

此类表示VehicleConfiguration

@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;
}

此类表示VehicleYear

@Entity
public class VehicleYear extends LookupBaseEntity {

}

此类表示VehicleMake

@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;
    }

}