java动态调用方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18677032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 10:05:39  来源:igfitidea点击:

java dynamically call methods

javareflection

提问by Code Junkie

I'm trying to figure out how to dynamically call a method. I have a string that describes the method name, but I'm not sure how to do it. I thought this could be done with reflection, but haven't had any success. Example

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

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

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

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

You'll notice all the method calls are the same with the exception of the getVehicleYear, etc

您会注意到所有方法调用都相同,但 getVehicleYear 等除外

I have a string that describes the method names, just not sure how to use it.

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

I got as far as this with reflection, but failed.

我通过反思做到了这一点,但失败了。

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

Thanks in advance.

提前致谢。

采纳答案by Code Junkie

This ended up being my final solution which is a combination of MrLore and Sotirios Delimanolis solutions. This solution is completely dynamic without the use of any conditions.

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

This class performs the search for the name by passing in the property name;

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

String propertyName = "vehicleYear";

vehicleConfiguration.getInfo(propertyName).getName()

propertyName = "vehicleMake";

vehicleConfiguration.getInfo(propertyName).getName()

This class represents the VehicleConfiguration

这个类代表 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;
}

This class represents the VehicleYear

这个类代表 VehicleYear

@Entity
public class VehicleYear extends LookupBaseEntity {

}

This class represents the VehicleMake

这个类代表 VehicleMake

@Entity
public class VehicleMake extends LookupBaseEntity {

}

Which both extend LookupBaseEntity

两者都扩展了 LookupBaseEntity

public class LookupBaseEntity extends StatefulEntity {

    private String name;

    public String getName() {
        return name;
    }

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

}

回答by chrylis -cautiouslyoptimistic-

You have to use actual method name: getVehicleMake, not vehicleMake.

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

Additionally, if you're using this as anything other than an exercise, don't roll your own. Use Commons BeanUtilsor Spring's BeanWrapper.

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

回答by Sotirios Delimanolis

The class you are looking for is Method. Please read the appropriate javadoc carefully.

您正在寻找的课程是Method. 请仔细阅读相应的 javadoc。

You can get a method with, for example

你可以得到一个方法,例如

// 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")

You then need to invoke()this method on an instance of your class.

然后你需要invoke()在你的类的一个实例上使用这个方法。

VehicleConfiguration instance = new VehicleConfiguration();

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

To then call getName(), you need to cast the returned object to the type that has the method. Assuming getMake()is a method of the type VehicleMake, call it like this

然后调用getName(),您需要将返回的对象强制转换为具有该方法的类型。假设getMake()是一个类型的方法VehicleMake,这样调用它

((VehicleMake)returnObject).getMake();

回答by MrLore

Expanding on my comment, As all the methods you showed have a getName()method, let's create a simple class which defines this:

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

class Nameable
{
    private String name;

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

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

Now when you create the object for Make, Model and Year, they can all use this class so they can be used interchangeably, and can then be combined into a Car:

现在,当您为 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;
    }
}

Then a simple implementation would be:

那么一个简单的实现将是:

class PaganiZonda2006 extends Car
{
    public PaganiZonda2006()
    {
        super(new Nameable("Pagani"), new Nameable("Zonda"), new Nameable("2006"));
    }
}

And finally, when you want to get the information out, you can read it like so:

最后,当您想要获取信息时,您可以这样阅读:

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
}