如何根据注解创建新对象

碰到一个任务, 需要根据注解来创建一个新对象,而不能使用new关键字. 在取得注解的内容后,不知道如何根据注解内容来生成一个新的User对象?

[code="java"]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);
}

}[/code]

User和UserAnno的代码如下:
[code="java"]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";
}

}[/code]

[code="java"]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 "";

}[/code]

还可以这样做
Class userClass = User.class;
Constructor constructor = userClass.getConstructor();
user = constructor.newInstance();
user.setId(id);
user.setName(name);
但是记住,如果User中有多个构造方法,一定记得申明一个无参的构造方法,如果一个构造方法都没有的话就不用担心。

还有获取类属性应该用这个方法 Field[] fields = clazz.getDeclaredFields();

我使用你提供的getFields方法无任何返回值,具体原因还在查。

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 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 userClass = User.class;
    Constructor 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;
}

getFields()只能访问类中声明为公有的字段,私有的字段它无法访问.getDeclaredFields()能访问类中所有的字段,与public,private,protect无关

sorry,看错,原来你的user是public的。是我搞错了,我申明成private的了。

显然 通常这个User通常是不会引入到类中的,而其注解是需要的,因为它是解析的元数据,算是入口,所以可以这样写,来实现注解的功能,即把构造延迟到应用程序的解析上
[code="java"]
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);
}
}
}
[/code]