注解与反射

注解与反射

自定义注解

@Target 描述的注解可以用在什么地方
@Retention 表示被它所注解的注解在什么地方还有效
@Documented 是否将我们的注解生成在javaDoc文档中
@Inherited 说明子类可以继承父类中的该注解

/**
 * @program: 注解和反射
 * @description: 自定义注解
 * @author: wangj
 * @create: 2021/08/14 20:42
 */
public class Test03 {

    // 注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
    @MyAnnotation2(name="名字",schools={"朝阳小学","朝阳中学"})
    @MyAnnotation3("这这这这")
    public void test(){

    }
}

// 定义一个注解
@Target({ElementType.METHOD,ElementType.TYPE}) //描述的注解可以用在什么地方
@Retention(RetentionPolicy.RUNTIME) //表示被它所注解的注解在什么地方还有效
@Documented // 是否将我们的注解生成在javaDoc文档中
@Inherited  // 说明子类可以继承父类中的该注解
@interface MyAnnotation{
    String name() default "";
    int age() default 0;

    String[] schools();

}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
    String value(); // 注解如果只有一个参数,用value(),使用是 value可以省略
}

获得反射对象

一个类在内存中只有一个Class对象

public class Test02 {

    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的class对象
        Class c1 = Class.forName("com.example.reflection.User");
        Class c2 = Class.forName("com.example.reflection.User");
        Class c3 = Class.forName("com.example.reflection.User");
        Class c4 = Class.forName("com.example.reflection.User");
        System.out.println(c1);

        // 一个类在内存中只有一个Class对象
        // 一个类被加载后,类的整个结构都会被封装在Class对象中
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());

    }
}

// 实体类entity,pojo
class User{
    private String name;
    private int id;
    private int age;

    public User() {
    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}

得到Class类的几种方式

通过对象获得

对象.getClass

forName获得

Class.forName()

通过类名.class 获得

类名.class

基本内置对象的包装类都有一个Type属性

Class<Integer> c4 = Integer.TYPE

public class Test03 {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Person person = new Student();
        System.out.println("这个人是:" + person.name);

        //方式一: 通过对象获得
        Class c1 = person.getClass();
        System.out.println("通过<对象.getClass>获得Student Class对象: " + c1.hashCode());

        // 方式二: forName获得
        Class c2 = Class.forName("com.example.reflection.Student");
        System.out.println("通过<Class.forName>获得Student Class对象: " + c2.hashCode());

        //方式三: 通过类名.class 获得
        Class c3 = Student.class;
        System.out.println("通过 <类名.class> 获得Student Class对象: " + c3.hashCode());

        // 方式四: 基本内置对象的包装类都有一个Type属性
        Class<Integer> c4 = Integer.TYPE;

        System.out.println("通过<包装类的Type属性>,获取Class对象: " + c4);

        // 获取父类类型
        Class c5 = c1.getSuperclass();
        System.out.println("通过<getSuperclass>获取父类类型: " +c5);

        Teacher teacher = test(Teacher.class);
        System.out.println(teacher);
    }

    public static <T> T test(Class<T> claZZ) throws InstantiationException, IllegalAccessException {
        return claZZ.newInstance();
    }

}

class Person{
    String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person{
    public Student() {
        this.name="学生";
    }
}

class Teacher extends Person{
    public Teacher() {
        this.name="老师";
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                '}';
    }
}

获得类的信息

获得类的名字:

getName() 获得包名 + 类名

getSimpleName() 获得类名

获得类的属性:

getFields() 只能找到public属性

getDeclaredFields() 找到所有属性

获得类的方法:

getMethods() // 获得本类及其父类的全部方法

getDeclaredMethods() // 获得本类的全部方法

获得指定的方法:

getMethod("setName", String.class); // 获得名称为setName,参数为String 的方法

获得指定的构造器:

getConstructors() // 获得public 构造方法

getDeclaredConstructors() // 获得全部 构造方法

获得指定构造器:
getDeclaredConstructor(String.class, Integer.TYPE,int.class) 获得参数为(String ,int,int)的构造方法

public class Test05 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.example.reflection.User");

        // 获得类的名字
        System.out.println(c1.getName()); // 获得包名 + 类名
        System.out.println(c1.getSimpleName()); // 获得类名
        // 获得类的属性
//        Field[] fields = c1.getFields(); //只能找到public属性
//        for (Field field : fields) {
//            System.out.println(field);
//        }

        Field[] fields = c1.getDeclaredFields(); // 找到所有属性
        for (Field field : fields) {
            System.out.println(field);
        }
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        // 获得类的方法
        Method[] methods = c1.getMethods(); // 获得本类及其父类的全部方法
        for (Method method : methods) {
            System.out.println(" getMethods ==>" + method);
        }

        methods = c1.getDeclaredMethods(); // 获得本类的全部方法
        for (Method method : methods) {
            System.out.println("getDeclaredMethods ==> " + method);
        }
        
        // 获得指定的方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        // 获得指定的构造器
        System.out.println("============================================");
        Constructor[] constructors = c1.getConstructors(); // 获得public 构造方法
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();  // 获得全部 构造方法
        for (Constructor constructor : constructors) {
            System.out.println(" ### " + constructor);
        }
        // 获得指定构造器
        Constructor constructor = c1.getDeclaredConstructor(String.class, Integer.TYPE,int.class);
        System.out.println(constructor);
    }
}

动态创建对象执行方法

Class.newInstance() 调用了类的无参构造器构造一个对象
Constructor.newInstance(Object... var1) 通过构造器创建对象
Method.invokeinvoke(Object var1, Object... var2) 通过反射调用普通方法

能直接操作私有属性,需要关闭程序的安全检测,属性或方法的 setAccessible 方法
Field.setAccessible(true) 关闭java访问安全检查
Field.set(Object var1, Object var2) 通过反射操作属性

public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 获得class对象
        Class c1 = Class.forName("com.example.reflection.User");

        // 构造一个对象
        User user = (User)c1.newInstance(); // 本质上调用了类的无参构造器
        System.out.println(user);

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class,int.class);
        User user2 = (User)constructor.newInstance("无伤", 1, 18);
        System.out.println(user2);

        // 通过反射调用普通方法
        User user3 = (User)c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        // 调用(对象,"方法的参数")==> 调用 对象的方法
        setName.invoke(user3,"无敌");
        System.out.println(user3);

        // 通过反射操作属性
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");
        // 不能直接操作私有属性,需要关闭程序的安全检测,属性或方法的 setAccessible 方法
        name.setAccessible(true); //关闭java访问安全检查
        name.set(user4,"无名");
        System.out.println(user4);

    }
}

获取泛型信息

method.getGenericParameterTypes() 获得泛型参数类型

Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments() 获取实际参数类型

Type genericReturnType = method.getGenericReturnType() 获得返回泛型类型

public class Test08 {

    public void test01(Map<String,User> map, List<User> list){
        System.out.println("test01");
    }

    public Map<String,User> test02(){
        System.out.println("test01");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {

        System.out.println("==============参数泛型=================");
        Method method= Test08.class.getMethod("test01", Map.class, List.class);
        // 获得泛型参数类型
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println(" # " + genericParameterType);
            // 获取实际参数类型
            Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("--" + actualTypeArgument);

            }
        }
        //  获得返回泛型类型
        System.out.println("=============返回值泛型==================");
        method = Test08.class.getMethod("test02", null);
        Type genericReturnType = method.getGenericReturnType();
        System.out.println(genericReturnType);
        // 获取实际参数类型
        Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
        for (Type actualTypeArgument : actualTypeArguments) {
            System.out.println("--" + actualTypeArgument);

        }
    }
}

反射操作注解

通过反射获得注解 class.getAnnotations()

获得指定注解 MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);

获得注解的属性值 String value = myTable.value();

public class Test09 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.example.reflection.Stu");

        // 通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        // 获得注解的value的值
        MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);
        String value = myTable.value();
        System.out.println(value);

        // 获得类指定属性的注解
        Field name = c1.getDeclaredField("name");
        MyField myField = name.getAnnotation(MyField.class);
        System.out.println(myField.column());
        System.out.println(myField.type());
        System.out.println(myField.length());

    }

}

@MyTable("db_stu")
class Stu{
    @MyField(column = "db_id",type = "int",length = 10)
    private int id;
    @MyField(column = "db_age",type = "int",length = 10)
    private int age;
    @MyField(column = "db_name",type = "varchar",length = 10)
    private String name;

    public Stu() {
    }

    public Stu(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}


// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTable{
    String value();
}

// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyField{
    String column();
    String type();
    int length();
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容