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