问题描述
碰到一个任务, 需要根据注解来创建一个新对象,而不能使用new关键字. 在取得注解的内容后,不知道如何根据注解内容来生成一个新的User对象?package annopractise;import java.lang.reflect.Field;public class UserAnnoTest { @UserAnno(id = 13, name = "sanan") public User user; public UserAnnoTest() throws ClassNotFoundException { Class<?> cl = UserAnnoTest.class; for (Field field : cl.getFields()) { UserAnno userAnno = field.getAnnotation(UserAnno.class); if (userAnno != null) { [color=red]// 此处该如何继续, 这里已经得到注解内容, 但是不知道如何创建User对象[/color] } } } @Override public String toString() { return user.toString(); } public static void main(String[] args) throws ClassNotFoundException { UserAnnoTest annoTest = new UserAnnoTest(); System.out.println(annoTest); }}User和UserAnno的代码如下:package annopractise;public class User { int id; String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "id: " + id + "tname: " + name + "n"; }}package annopractise;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface UserAnno { int id(); String name() default "";} 问题补充:Wind_ZhongGang 写道
解决方案
还可以这样做 Class<User> userClass = User.class; Constructor<User> constructor = userClass.getConstructor(); user = constructor.newInstance(); user.setId(id); user.setName(name);但是记住,如果User中有多个构造方法,一定记得申明一个无参的构造方法,如果一个构造方法都没有的话就不用担心。还有获取类属性应该用这个方法 Field[] fields = clazz.getDeclaredFields(); 我使用你提供的getFields方法无任何返回值,具体原因还在查。
解决方案二:
显然 通常这个User通常是不会引入到类中的,而其注解是需要的,因为它是解析的元数据,算是入口,所以可以这样写,来实现注解的功能,即把构造延迟到应用程序的解析上public static void main(String[] args) throws Exception {Class<?> cl = UserAnnoTest.class;for (Field field : cl.getFields()) {UserAnno ano = field.getAnnotation(UserAnno.class);if (ano != null) {Class<?> filedType = field.getType();Object f = filedType.newInstance();Method m = f.getClass().getMethod("setName", String.class); // 可以根据UserAnno字段來动态获取m.invoke(f, ano.name());Method m2 = f.getClass().getMethod("setId", int.class); // 可以根据UserAnno字段來动态获取m2.invoke(f, ano.id());System.out.println(f);}}}
解决方案三:
getFields()只能访问类中声明为公有的字段,私有的字段它无法访问.getDeclaredFields()能访问类中所有的字段,与public,private,protect无关sorry,看错,原来你的user是public的。是我搞错了,我申明成private的了。
解决方案四:
package com.annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;/** * Created by IntelliJ IDEA. * User: Zhong Gang * Date: 8/19/11 * Time: 3:27 PM */public class Main { @UserAnno(id = 1, name = "ZhongGang") private User user; public Main() { Class<Main> clazz = Main.class; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { UserAnno annotation = field.getAnnotation(UserAnno.class); if (annotation != null) { int id = annotation.id(); String name = annotation.name(); try { Class<User> userClass = User.class; Constructor<User> constructor = userClass.getConstructor(Integer.class, String.class); user = constructor.newInstance(id, name); } catch (InstantiationException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (IllegalAccessException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (NoSuchMethodException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (InvocationTargetException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } } } public static void main(String[] args) { Main main = new Main(); System.out.println(main.toString()); } public String toString() { return user.toString(); }}User中记得添加User的构造方法public User(Integer id, String name) { this.id = id; this.name = name; }