java 注解与反射总结

目录

一、注解

1、内置注解

2、元注解

3、自定义注解

二、反射

1、什么是反射(Reflection )?

2、反射可以实现的功能

3、反射常用方法

测试案例1:类地址等测试

测试案例2:类的相关属性和方法的查看

测试案例3:通过反射动态操作对象及方法

测试案例4:反射操作与普通操作速度对比

 测试案例5:注解与反射操作,框架底层逻辑


一、注解

1、内置注解

@Override注解在方法上
表示重写父类方法,编译时期报错,提高可读性
@Deprecated注解在方法上
表示方法已经过时
@SuppressWarning注解在类或方法或变量上
忽略指定的警告

2、元注解

@Target 表示我们的注解可以用在哪些地方
@Retention 表示我们的注解在什么地方才有效
runtime>class>sources
@Document  表示是否将我们的注解生成在JAVAdoc中
@Inherited 子类可以继承父类的注解
package com.wxl.springbootpro01;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Test.MyAnnotation
public class Test {
    @org.junit.jupiter.api.Test
    public void test(){

    }

    @MyAnnotation
    public void method(){

    }

    //定义一个注解
    //Target 表示我们的注解可以用在哪些地方
    @Target(value={ElementType.METHOD,ElementType.TYPE})

    //Retention 表示我们的注解在什么地方才有效
    //runtime>class>sources
    @Retention(value = RetentionPolicy.RUNTIME)//运行时有效
    @interface MyAnnotation{

    }
}

3、自定义注解

package com.wxl.springbootpro01;

import java.lang.annotation.*;

//自定义注解
public class Test {
    @org.junit.jupiter.api.Test
    public void test(){

    }

    //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
    @MyAnnotation(name="Jack",schools = {"撤犊子大学"})
    public void method(){

    }

    @MyAnnotation2("Jack")
    public void method2(){

    }

    @Target({ElementType.TYPE,ElementType.METHOD})//作用域
    @Retention(RetentionPolicy.RUNTIME)//运行时生效
    @interface MyAnnotation{
        //注解的参数:参数类型+参数名();
        String name() default "";
        int age() default 0;
        int id() default -1;//如果默认值为-1,代表不存在,类似于indexof,如果找不到就返回-1
        String[] schools() default {"清华大学"};
    }

    @Target({ElementType.TYPE,ElementType.METHOD})//作用域
    @Retention(RetentionPolicy.RUNTIME)//运行时生效
    @interface MyAnnotation2{
        String value();//如果只有一个值建议使用value命名,赋值时可省略value
    }

}

二、反射

1、什么是反射(Reflection )?

主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

2、反射可以实现的功能

Java 反射机制主要提供了以下功能,这些功能都位于java.lang.reflect包。

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。
  • 生成动态代理。

3、反射常用方法

利用 Class 类的对象 labelCls 可以访问 labelCls 对象的描述信息、JLabel 类的信息以及基类 Object 的信息。表 1 列出了通过反射可以访问的信息。

类型访问方法返回值类型说明
包路径getPackage()Package 对象获取该类的存放路径
类名称getName()String 对象获取该类的名称
继承类getSuperclass()Class 对象获取该类继承的类
实现接口getlnterfaces()Class 型数组获取该类实现的所有接口
构造方法getConstructors()Constructor 型数组获取所有权限为 public 的构造方法
getDeclaredContruectors()Constructor 对象获取当前对象的所有构造方法
方法getMethods()Methods 型数组获取所有权限为 public 的方法
getDeclaredMethods()Methods 对象获取当前对象的所有方法
成员变量getFields()Field 型数组获取所有权限为 public 的成员变量
getDeclareFileds()Field 对象获取当前对象的所有成员变量
内部类getClasses()Class 型数组获取所有权限为 public 的内部类
getDeclaredClasses()Class 型数组获取所有内部类
内部类的声明类getDeclaringClass()Class 对象如果该类为内部类,则返回它的成员类,否则返回 null

测试案例1:类地址等测试

package com.wxl.springbootpro01;

import java.lang.annotation.ElementType;

//什么叫反射
public class Test {
    @org.junit.jupiter.api.Test
    public void test() throws ClassNotFoundException {
        //通过反射获取类的Class对象
        Class c1 = Class.forName("com.wxl.springbootpro01.Test");
        System.out.println(c1);
        //一个类在内存中只有一个Class对象
        //一个类被加载后,类的整个结构都会被封装在Class对象中。
    }

    //测试Class类的创建方式有哪些
    @org.junit.jupiter.api.Test
    public void test2() throws ClassNotFoundException {
        User user = new User();
        user.setName("Jack");
        System.out.println(user.getName());

        //方式一:通过对象获得
        Class c1 = user.getClass();
        System.out.println(c1.hashCode());

        //方式二:forName获得
        Class c2 = Class.forName("com.wxl.springbootpro01.User");
        System.out.println(c2.hashCode());

        //方式三:通过类名.class获得
        Class c3 = User.class;
        System.out.println(c3.hashCode());

        //方式四:基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);

        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);

        //运行测试可以看到地址都一样为对象的地址
//        Jack
//        1582785598
//        1582785598
//        1582785598
    }

    @org.junit.jupiter.api.Test
    public void test3() {
        Class c1 = Object.class;//类
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//一维数组
        Class c4 = int[][].class;//二维数组
        Class c5 = Override.class;//注解
        Class c6 = ElementType.class;//枚举
        Class c7 = Integer.class;//基本数据类型
        Class c8 = void.class;//void
        Class c9 = Class.class;//Class

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

//        class java.lang.Object
//        interface java.lang.Comparable
//        class [Ljava.lang.String;
//        class [[I
//        interface java.lang.Override
//        class java.lang.annotation.ElementType
//        class java.lang.Integer
//        void
//        class java.lang.Class

        //只要元素类型与维度一样,就是同一个Class
    }

}

class User {
    private String name;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

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

测试案例2:类的相关属性和方法的查看

package com.wxl.springbootpro01;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
    //获得类的信息
    @org.junit.jupiter.api.Test
    public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.wxl.springbootpro01.User");

        //获得类的名字
        System.out.println(c1.getName());//获得包名+类名
        System.out.println(c1.getSimpleName());//获得类名

        //获得类的属性
        System.out.println("====================");
        Field[] fields = c1.getFields();//只能找到public属性

        fields = c1.getDeclaredFields();//找到全部的属性
        for (Field field : fields) {
            System.out.println(field);
        }

        //获得指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

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

        //获得指定方法
        //重载
        System.out.println("==========================");
        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();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("###" + constructor);
        }

        //获取指定的构造器
        Constructor declaredConstructor=c1.getDeclaredConstructor(String.class,int.class);
        System.out.println("指定:"+declaredConstructor);
    }
}

class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public User() {
    }

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

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

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

    private void show() {
        System.out.println("how are you");
    }
}

测试案例3:通过反射动态操作对象及方法

package com.wxl.springbootpro01;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    //动态的创建对象,通过反射
    @org.junit.jupiter.api.Test
    public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {

        //获得Class对象
        Class c1 = Class.forName("com.wxl.springbootpro01.User");

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

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

        //通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        //通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);

        //invoke:激活的意思
        //(对象,”方法的值“)
        setName.invoke(user3, "dragon wu");
        System.out.println(user3.getName());

        //通过反射操作属性
        System.out.println("===============================");
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");

        //不能直接操作私有属性,我们需要关闭程序的安全检测,属性或方法的setAccessible(true).
        name.setAccessible(true);
        name.set(user4, "dragon wu");
        System.out.println(user4.getName());
    }
}

class User {
    private String name;
    private int age;

    public User() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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



测试案例4:反射操作与普通操作速度对比

package com.wxl.springbootpro01;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    //普通方式调用
    @org.junit.jupiter.api.Test
    public void test() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        User user = new User();

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }

        long endTime = System.currentTimeMillis();

        System.out.println("普通方式执行10亿次:" + (endTime - startTime) + "ms");
    }

    //反射方法调用
    @org.junit.jupiter.api.Test
    public void test2() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        User user = new User();
        Class c1 = user.getClass();

        Method getName = c1.getDeclaredMethod("getName", null);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user, null);
        }

        long endTime = System.currentTimeMillis();

        System.out.println("反射方式执行10亿次:" + (endTime - startTime) + "ms");
    }

    //反射方法调用 关闭检测
    @org.junit.jupiter.api.Test
    public void test3() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        User user = new User();
        Class c1 = user.getClass();

        Method getName = c1.getDeclaredMethod("getName", null);
        getName.setAccessible(true);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user, null);
        }

        long endTime = System.currentTimeMillis();

        System.out.println("关闭检测,反射方式执行10亿次:" + (endTime - startTime) + "ms");
    }


    @org.junit.jupiter.api.Test
    public void test5() throws NoSuchMethodException, IllegalAccessException, NoSuchFieldException, InstantiationException, InvocationTargetException, ClassNotFoundException {
        test();
        test2();
        test3();
    }
}

class User {
    private String name;
    private int age;

    public User() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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



 测试案例5:注解与反射操作,框架底层逻辑

package com.wxl.springbootpro01;

import java.lang.annotation.*;
import java.lang.reflect.Field;

//练习反射操作注解
public class Test {
    @org.junit.jupiter.api.Test
    public void test() throws ClassNotFoundException, NoSuchFieldException {
        Class c1=Class.forName("com.wxl.springbootpro01.Student");

        //通过反射获得注解
        Annotation[] annotations=c1.getAnnotations();
        for(Annotation annotation:annotations){
            System.out.println(annotation);
        }

        //获得注解的value的值
        StudentTable studentTable=(StudentTable) c1.getAnnotation(StudentTable.class);
        String value=studentTable.value();
        System.out.println(value);

        //获得类指定的注解
        Field f=c1.getDeclaredField("name");
        FieldStudent annotation=f.getAnnotation(FieldStudent.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }
}



@StudentTable("db_student")
class Student{
    @FieldStudent(columnName = "db_id",type = "int",length = 10)
    private int id;
    @FieldStudent(columnName = "db_age",type = "int",length = 10)
    private int age;
    @FieldStudent(columnName = "db_name",type = "varchar",length = 10)
    private String 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;
    }
}


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

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent{
    String columnName();
    String type();
    int length();
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值