注解和反射


这篇注解与反射文章是基于 狂神说哔站视频的笔记与总结,仅供个人学习和复习用。欲学习知识推荐前往大佬的博客中学习。

注解 Annotation

Annotation的作用

  • 不是程序本身,可以对程序作出解释。
  • 可以被其他程序(编译器等)读取。

Annotation的格式:

  • 注解是以”@注释名”在代码中存在的,还可以增加一些参数值。例如:@SuppressWarnings(Value=”unchecked”)

元注解

@MyAnnotation
public class Test01 {

}

/**定义一个注解
 * @Target : 表示我们的注解可以用到什么地方
 * @Retention : 表示我们的注解在什么地方还有效     runtime > class > sources
 */
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented //表示是否将我们的注解生成在JAVAdoc中
@Inherited //子类可以继承父类的注解
@interface MyAnnotation{

}

反射 Reflection

Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能操作任意对象的内部属性及方法。

获取Class类的方式

public class demo2 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println(person.name);
        //通过反射获取类的的Class对象
        //方式一 :通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        //方式二 :forname获得
        Class c2 = Class.forName("com.kuang.demo2.Student");
        System.out.println(c2.hashCode());
        //方式三 :通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());
        //基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);
        //获得父类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}
//实体类
class Person{
    public String name;
}
class Teacher extends Person{
    public Teacher() {
        this.name = "老师";
    }
}
class Student extends Person{
    public Student() {
        this.name = "学生";
    }
}

通过反射获取类中的内容

  • 实体类
//实体类
class Person{
    public String name;
}
class Teacher extends Person{
    public Teacher() {
        this.name = "老师";
    }
}
class Student extends Person{
    private String address;
    public int id;
    public Student() {
        this.name = "学生";
    }

    public Student(String address, int id) {
        this.address = address;
        this.id = id;
    }


    public void test(){
        System.out.println("测试*********");
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "address='" + address + '\'' +
                ", id=" + id +
                '}';
    }
}
  • 反射操作
public class demo03 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.kuang.demo2.Student");

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

        //获得类的属性
        System.out.println("**********************");
        //Field[] fields = c1.getFields(); //获得所有public属性包括父类中的字段
        Field[] fields = c1.getDeclaredFields();//获得某个类的声明字段,既包括public private 和proteced,但是不包括父类的声明字段
        for (Field field : fields) {
            System.out.println(field);
        }

        //获得指定属性的值
        System.out.println("********************");
        Field address = c1.getDeclaredField("address");//获得当前类的指定属性 不包括父类的
        System.out.println(address);

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

        //获得指定方法
        //重载
        Method getAddress = c1.getMethod("getAddress", null);
        Method setAddress = c1.getMethod("setAddress", String.class);
        System.out.println(getAddress);
        System.out.println(setAddress);

        //获得指定构造器
        System.out.println("*************");
        Constructor[] constructors = c1.getConstructors();//只返回制定参数类型访问权限是public的构造器。
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();//返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

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

结果

com.kuang.demo2.Student
Student
**********************
private java.lang.String com.kuang.demo2.Student.address
public int com.kuang.demo2.Student.id
********************
private java.lang.String com.kuang.demo2.Student.address
********************
getDeclaredMethodspublic java.lang.String com.kuang.demo2.Student.getAddress()
getDeclaredMethodspublic void com.kuang.demo2.Student.test()
getDeclaredMethodspublic void com.kuang.demo2.Student.setAddress(java.lang.String)
public java.lang.String com.kuang.demo2.Student.getAddress()
public void com.kuang.demo2.Student.setAddress(java.lang.String)
*************
public com.kuang.demo2.Student()
public com.kuang.demo2.Student(java.lang.String,int)
public com.kuang.demo2.Student()
public com.kuang.demo2.Student(java.lang.String,int)
public com.kuang.demo2.Student(java.lang.String,int)

通过反射动态的创建对象

  • 实体类
//实体类
class Person{
    public String name;
}
class Teacher extends Person{
    public Teacher() {
        this.name = "老师";
    }
}
class Student extends Person{
    private String address;
    public int id;
    public Student() {
        this.name = "学生";
    }

    public Student(String address, int id) {
        this.address = address;
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "address='" + address + '\'' +
                ", id=" + id +
                '}';
    }
}
  • 反射操作
//通过反射动态的创建对象
public class demo04 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得Class对象
        Class c1 = Class.forName("com.kuang.demo2.Student");

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

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
        Student st2 = (Student) constructor.newInstance("广州", 1);
        System.out.println(st2);

        //通过反射调用普通方法
        Student st3 = (Student) c1.newInstance();//构造一个对象
        //通过反射获取一个方法
        Method setAddress = c1.getDeclaredMethod("setAddress", String.class);
        setAddress.invoke(st3,"广州"); //invoke:激活的意思 (对象,"方法的值")
        System.out.println(st3.getAddress());

        //通过反射操作属性
        System.out.println("*********************");
        Student st4 = (Student) c1.newInstance();//构造一个对象

        Field address = c1.getDeclaredField("address");//反射获取属性
        address.setAccessible(true);//不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true)
        address.set(st4,"广州");
        System.out.println(st4.getAddress());

        Field id = c1.getDeclaredField("id");
        id.set(st4,1);//id为public 属性可以直接操作
        System.out.println(st4.getId());
    }
}
  • 打印结果
Student{address='null', id=0}
Student{address='广州', id=1}
广州
*********************
广州
1

分析性能问题

  • 实体类
//实体类
class Person{
    public String name;
}
class Teacher extends Person{
    public Teacher() {
        this.name = "老师";
    }
}
class Student extends Person{
    private String address;
    public int id;
    public Student() {
        this.name = "学生";
    }

    public Student(String address, int id) {
        this.address = address;
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "address='" + address + '\'' +
                ", id=" + id +
                '}';
    }
}
  • 测试类
//性能对比
public class demo05 {
    //普通方式调用
    public static void test01(){
        Student student = new Student();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            student.getAddress();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("普通方式执行:"+(endTime-startTime)+"ms");
    }


    //反射方式调用
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Student student2 = new Student();
        Class c1 = student2.getClass();

        Method setId = c1.getDeclaredMethod("setId", int.class);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            setId.invoke(student2,111);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式执行:"+(endTime-startTime)+"ms");
    }
    //反射方式调用 关闭检测
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Student student3 = new Student();
        Class c2 = student3.getClass();

        Method setId = c2.getDeclaredMethod("setId", int.class);
        setId.setAccessible(true);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            setId.invoke(student3,111);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("关闭检测后反射方式执行:"+(endTime-startTime)+"ms");
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test01();
        test02();
        test03();
    }
}
  • 结果
普通方式执行:0ms
反射方式执行:46ms
关闭检测后反射方式执行:34ms

通过反射获取泛型

public class demo07 {
    public void test01(Map<String,Student> map, List<Student> list){
        System.out.println("test01");
    }
    public Map<String,Student> test02(){
        System.out.println("test02");
        return  null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = demo07.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("***" + genericParameterType);
            if(genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }

        Method method2 = demo07.class.getMethod("test02",null);
        Type genericReturnType = method2.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("return" + actualTypeArgument);
            }
        }
    }
}
***java.util.Map<java.lang.String, com.kuang.demo2.Student>
class java.lang.String
class com.kuang.demo2.Student
***java.util.List<com.kuang.demo2.Student>
class com.kuang.demo2.Student
returnclass java.lang.String
returnclass com.kuang.demo2.Student

通过反射获取注解信息

//反射操作注解
public class demo08 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.kuang.demo2.Student2");
        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //获得注解的value的值
        TableStudent tableStudent = (TableStudent)c1.getAnnotation(TableStudent.class);
        String value = tableStudent.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());
    }
}

@TableStudent("db_student")
class Student2{
    @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 = 3)
    private String name;

    public Student2() {
    }

    public Student2(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 "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

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

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

结果

@com.kuang.demo2.TableStudent(value=db_student)
db_student
db_name
varchar
3

文章作者: Sky
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Sky !
评论
  目录