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
java dynamically call methods
提问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 BeanUtils
or 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
}