Java 通过反射调用getter的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2638590/
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
Best way of invoking getter by reflection
提问by Javi
I need to get the value of a field with a specific annotation, So with reflection I am able to get this Field Object. The problem is that this field will be always private though I know in advance it will always have a getter method. I know that I can use setAccesible(true) and get its value (when there is no PermissionManager), though I prefer to invoke its getter method.
我需要使用特定注释获取字段的值,因此通过反射我能够获取此字段对象。问题是这个字段将永远是私有的,尽管我事先知道它总是有一个 getter 方法。我知道我可以使用 setAccesible(true) 并获取它的值(当没有 PermissionManager 时),尽管我更喜欢调用它的 getter 方法。
I know that I could look for the method by looking for "get+fieldName" (though I know for example for boolean fields are sometimes named as "is+fieldName").
我知道我可以通过查找“get+fieldName”来查找该方法(尽管我知道例如布尔字段有时被命名为“is+fieldName”)。
I wonder if there is a better way to invoke this getter (many frameworks use getters/setters to access the attributes so maybe they do in another way).
我想知道是否有更好的方法来调用这个 getter(许多框架使用 getter/setter 来访问属性,所以也许他们以另一种方式这样做)。
Thanks
谢谢
采纳答案by sfussenegger
I think this should point you towards the right direction:
我认为这应该为您指明正确的方向:
import java.beans.*
for (PropertyDescriptor pd : Introspector.getBeanInfo(Foo.class).getPropertyDescriptors()) {
if (pd.getReadMethod() != null && !"class".equals(pd.getName()))
System.out.println(pd.getReadMethod().invoke(foo));
}
Note that you could create BeanInfo or PropertyDescriptor instances yourself, i.e. without using Introspector. However, Introspector does some caching internally which is normally a Good Thing (tm). If you're happy without a cache, you can even go for
请注意,您可以自己创建 BeanInfo 或 PropertyDescriptor 实例,即不使用 Introspector。但是,Introspector 会在内部进行一些缓存,这通常是一件好事 (tm)。如果你在没有缓存的情况下很开心,你甚至可以去
// TODO check for non-existing readMethod
Object value = new PropertyDescriptor("name", Person.class).getReadMethod().invoke(person);
However, there are a lot of libraries that extend and simplify the java.beans API. Commons BeanUtils is a well known example. There, you'd simply do:
但是,有很多库可以扩展和简化 java.beans API。Commons BeanUtils 是一个众所周知的例子。在那里,您只需执行以下操作:
Object value = PropertyUtils.getProperty(person, "name");
BeanUtils comes with other handy stuff. i.e. on-the-fly value conversion (object to string, string to object) to simplify setting properties from user input.
BeanUtils 带有其他方便的东西。即动态值转换(对象到字符串,字符串到对象)以简化用户输入的设置属性。
回答by Michael Borgwardt
The naming convention is part of the well-established JavaBeansspecification and is supported by the classes in the java.beanspackage.
命名约定是完善的JavaBeans规范的一部分,由java.beans包中的类支持。
回答by Naveedur Rahman
You can use Reflectionsframework for this
您可以为此使用反射框架
import static org.reflections.ReflectionUtils.*;
Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
withModifier(Modifier.PUBLIC), withPrefix("get"), withAnnotation(annotation));
回答by Anand
You can invoke reflections and also, set order of sequence for getter for values through annotations
您可以调用反射,还可以通过注释为值设置 getter 的顺序
public class Student {
private String grade;
private String name;
private String id;
private String gender;
private Method[] methods;
@Retention(RetentionPolicy.RUNTIME)
public @interface Order {
int value();
}
/**
* Sort methods as per Order Annotations
*
* @return
*/
private void sortMethods() {
methods = Student.class.getMethods();
Arrays.sort(methods, new Comparator<Method>() {
public int compare(Method o1, Method o2) {
Order or1 = o1.getAnnotation(Order.class);
Order or2 = o2.getAnnotation(Order.class);
if (or1 != null && or2 != null) {
return or1.value() - or2.value();
}
else if (or1 != null && or2 == null) {
return -1;
}
else if (or1 == null && or2 != null) {
return 1;
}
return o1.getName().compareTo(o2.getName());
}
});
}
/**
* Read Elements
*
* @return
*/
public void readElements() {
int pos = 0;
/**
* Sort Methods
*/
if (methods == null) {
sortMethods();
}
for (Method method : methods) {
String name = method.getName();
if (name.startsWith("get") && !name.equalsIgnoreCase("getClass")) {
pos++;
String value = "";
try {
value = (String) method.invoke(this);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(name + " Pos: " + pos + " Value: " + value);
}
}
}
// /////////////////////// Getter and Setter Methods
/**
* @param grade
* @param name
* @param id
* @param gender
*/
public Student(String grade, String name, String id, String gender) {
super();
this.grade = grade;
this.name = name;
this.id = id;
this.gender = gender;
}
/**
* @return the grade
*/
@Order(value = 4)
public String getGrade() {
return grade;
}
/**
* @param grade the grade to set
*/
public void setGrade(String grade) {
this.grade = grade;
}
/**
* @return the name
*/
@Order(value = 2)
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the id
*/
@Order(value = 1)
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the gender
*/
@Order(value = 3)
public String getGender() {
return gender;
}
/**
* @param gender the gender to set
*/
public void setGender(String gender) {
this.gender = gender;
}
/**
* Main
*
* @param args
* @throws IOException
* @throws SQLException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void main(String args[]) throws IOException, SQLException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Student student = new Student("A", "Anand", "001", "Male");
student.readElements();
}
}
Output when sorted
排序时输出
getId Pos: 1 Value: 001
getName Pos: 2 Value: Anand
getGender Pos: 3 Value: Male
getGrade Pos: 4 Value: A