注解和反射知识总结

注解

Java.Annotation

1、注解入门

什么是注解?

  • Annotation是从JDK5.0以后引入的新技术
  • Annotation的作用
    • 不是程序本身,可以对程序作出解释(这一点和注解(comment)没什么区别)
    • 可以被其他程序(比如:编译器)读取
  • Annotation的格式:
    • 注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value=“unchecked”)
  • Annotation在哪里使用?
    • 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

测试代码:

package pers.mobian.annotationreflex;

public class TestAnnotationReflex {
	//此处的标记,即为注解
    @Override
    public String toString() {
        return super.toString();
    }
}

2、内置注解

  • @Override:定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明
  • @Deprecated:定义在java.lang.Deprecated中,此注释可以用于修饰方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择
  • @SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息
    • 与前两个注释有所不同,你需要添加一个参数才嗯那个正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了。
      1. @SuppressWarnings(“all”)
      2. @SuppressWarnings(“unchecked”)
      3. @SuppressWarnings(value = {“unchecked”,“deprecation”})

测试代码:

package pers.mobian.annotationreflex;

import java.util.ArrayList;

public class TestAnnotationReflex {
    //重写的方法
    @Override
    public String toString() {
        return super.toString();
    }
    //已过时,或者存在更好的替代方法
    @Deprecated
    public static void test(){
        System.out.println("Deprecated注解");
    }
    public static void main(String[] args) {
        test();
    }

    //将原本没有使用到的信息报出的异常进行抑制
    @SuppressWarnings("all")
    public void test02(){
       ArrayList<Integer> arrayList = new ArrayList<>();
    }
}

3、自定义注解,元注解

  • 元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
  • 这些类型和它们所支持的类在java.lang.annotation包中可以找到(@Target,@Retention,@Documented,@Inherited)
    • @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
    • @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
      • (SOURCE < CLASS < RUNTIME)
    • @Document:说明该注解将被包含在javadoc中
    • @Inherited:说明子类可以继承父类中的该注解

测试代码:

package pers.mobian.annotationreflex;

import java.lang.annotation.*;

@MyAnnotation
public class TestMetaAnnitation {
    @MyAnnotation
    public void test() {
    }
}


//表示我们的注解可以使用的范围(方法上,类上)
@Target(value = {ElementType.METHOD, ElementType.TYPE})

//表示注解在什么地方有效(上文中已经提及了三个不同的范围)
@Retention(value = RetentionPolicy.RUNTIME)

//表示是否将我们的注解生成在Javadoc中
@Documented

//表示子类可以继承父类的注解
@Inherited
//定义一个注解
@interface MyAnnotation {
}
  • 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
  • 分析:
    • @interface用来声明一个注解,格式:public@interface注解名{定义内容}
    • 其中的每一个方法实际上是声明了一个配置参数
    • 方法的名称就是参数的名称
    • 返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)
    • 可以通过default来声明参数的默认值
    • 如果只有一个参数成员,一般参数名为value
    • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值

自定义元注解的测试代码:

package pers.mobian.annotationreflex;

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

public class TestMetaAnnitation2 {
    @MyAnnotation2(name = "mobian")
    public void test() {

    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@interface MyAnnotation2 {
    //注解使用的格式:数据类型 参数名(); 此处的括号,不是方法,而是代表参数(重要)
    String name();
    //设置默认值为0
    int age() default 0;
    //类似于index = -1,表示不存在
    int id() default  -1;

    String[] schools() default {"重庆大学","电子科技大学"};
}

@interface MyAnnotation3{
    //当只有一个参数的时候,尽量使用value,因为这样在注解被使用的时候,参数为一个的时候,可以省略参数名
    String value();
}

反射

Java.Reflection

反射机制的研究及应用:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jV4gwGiA-1579419151193)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118111111779.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rVMw4IhW-1579419151208)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118110224664.png)]

1、Java反射机制概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ogVnMUbl-1579419151212)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118110636910.png)]

优点:

  • 可以实现动态创建和编译,体现了很强的灵活性

缺点:

  • 对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们呢希望做什么并且它满足我们的要求。这类操作总是慢于直接执行相同的操作

测试代码:

package pers.mobian.reflexction;

public class TestReflexction {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取的Class对象
        Class c1 = Class.forName("pers.mobian.reflexction.User");
        System.out.println(c1);

        Class c2 = Class.forName("pers.mobian.reflexction.User");
        Class c3 = Class.forName("pers.mobian.reflexction.User");

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

//内含name和age属性,get、set、toString及构造器方法
class User {
    private String name;
    private Integer age;

    public User() {
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

执行结果:

class pers.mobian.reflexction.User
//打印的哈希值相同,表示同一个类
//一个加载的类在JVM中只会有一个Class实例
142666848
142666848

补充:

//在Object类中定义了以下的方法,此方法将被所有的子类继承
public final native Class<?> getClass();

//以上的方法返回值的类型是一个Class类,次类是java反射的源头,实际上所谓的反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称

2、理解Class类并获取Class实例

反射相关的主要API:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ep7DeeNa-1579419151216)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200119152705068.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q6H7UnCj-1579419151219)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118120011929.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ONQdnWlq-1579419151222)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118120230075.png)]

测试代码:

package pers.mobian.reflexction;

public class TestReflexction2 {
    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();
        System.out.println(student.name);
        
        //通过对象getClass获得
        Class c1 = student.getClass();
        System.out.println(c1);
        System.out.println(c1.hashCode());

        //通过forname获得
        Class c2 = Class.forName("pers.mobian.reflexction.Student");
        System.out.println(c2);
        System.out.println(c2.hashCode());

        //通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3);
        System.out.println(c3.hashCode());

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

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

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 pers.mobian.reflexction.Student
1060830840
class pers.mobian.reflexction.Student
1060830840
class pers.mobian.reflexction.Student
1060830840
int
class pers.mobian.reflexction.Person

总结:

  1. 若一直具体的类,可以通过类的class属性获取,该方法最为安全可靠,程序性能最高。

     Class c3 = Student.class;
    
  2. 已知某个类的实例,调用该实例的getClass()方法获取Class对象

    Class c1 = student.getClass();
    
  3. 已知一个类的全类名,且该类在路劲下,可以通过Class类的静态方法forName()获取,需要抛出ClassNotFoundException异常

     Class c2 = Class.forName("pers.mobian.reflexction.Student");
    
  4. 内置基本数据类型,可以直接使用类名.TYPE,进行查看相对应的类

  5. 利用ClassLoader

那些类型会有Class对象:

  • class:外部类,成员(成员内部类、静态内部类),局部内部类,匿名内部类
  • interface:接口
  • []:数组
  • enum:枚举
  • annotation:注解@interface
  • primitive type:基本数据类型
  • void

测试代码:

package pers.mobian.reflexction;

import javax.swing.text.Element;

public class TestReflexction3 {
    public static void main(String[] args) {
        Class c1 = Object.class;//类
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//一维数组
        Class c4 = int[][].class;//二维数组
        Class c5 = Override.class;//注解
        Class c6 = Element.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
        int[] a = new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

执行结果:

class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
interface javax.swing.text.Element
class java.lang.Integer
void
class java.lang.Class
142666848
142666848

3、类的加载与ClassLoader

3.1 java的内存分配:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xy5yR1xB-1579419151225)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118174132511.png)]

3.2 类的加载过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UoO9bsPL-1579419151227)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118174215703.png)]

3.3 类的加载与ClassLoader的理解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFJ4sbKX-1579419151229)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118174426971.png)]

测试代码:

package pers.mobian.reflexction;

public class TestReflexction4 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.m);
    }
}

class A {
    static {
        System.out.println("这里是静态初始化区域");
        m = 200;
    }

    static int m = 100;

    public A() {
        System.out.println("这里是空参构造的区域");
    }
}

执行结果:

这里是静态初始化区域
这里是空参构造的区域
100

总结:

  1. 将字节码文件加载到内存中,并且生成一个与类对应的Class对象

  2. 链接,链接结束后m = 0

  3. 初始化{

    System.out.println(“这里是静态初始化区域”);

    m = 200;

    m = 100;

    }

    m = 100;

补充图示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qDGVyekZ-1579419151232)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118180351569.png)]

运行说明:在main方法中,实例化对象A,得到A对应的对象。对象A就去找它的自己的Class类(无论创建几个对象都只有一个),Class内包含了类的一个基本结构。通过A类具体的东西,对他进行赋值。赋值完之后,通过clinit初始化成功后,就能够获得具体的值

3.4 什么时候会发生类初始化?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YcGB4wCr-1579419151235)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118181940962.png)]

测试代码:

package pers.mobian.reflexction;


import java.lang.reflect.Array;

public class TestReflexction5 {
    static {
        System.out.println("Main类被加载");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        //1、主动引用初始化
        //Son son = new Son();
        /*
        执行结果:
        Main类被加载
        父类被加载
        子类被加载
        */

        //2、反射产生的主动引用初始化
        //Class.forName("pers.mobian.reflexction.Son");
        /*
        执行结果:
        Main类被加载
        父类被加载
        子类被加载
        */

        //3、不产生初始化
        System.out.println(Son.b);
        System.out.println(Son.M);
        Son[] array = new Son[5];
    }
}

class Father {
    static int b = 2;

    static {
        System.out.println("父类被加载");
    }
}

class Son extends Father {
    static int m = 100;
    static final int M = 200;

    static {
        System.out.println("子类被加载");
    }
}

3.5、类加载器的作用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OC527Byo-1579419151237)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118184930155.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-seo8tOrc-1579419151240)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200118185026272.png)]

测试代码:

package pers.mobian.reflexction;

public class TestReflexction6 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统类的加载器
        ClassLoader  systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器-->扩展类加载器
        ClassLoader parent =  systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父类加载器-->根加载器
        ClassLoader parent2 = parent.getParent();
        System.out.println(parent2);

        //测试当前类是哪个加载器加载的
        ClassLoader classLoader = Class.forName("pers.mobian.reflexction.TestReflexction6").getClassLoader();
        System.out.println(classLoader);

        //测试JDK内置的类是谁加载的
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        //获取系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));

        //双亲委派机制(记忆)
        //当自定义的类出现与系统定义的类同名的时候,例如自定义了一个类String,先去用户类加载器是否有这个包,
        // 再去扩展类加载器看是否有这个包,再去根加载器看是否有这个包,如果发现存在同名的类,自己写的String类就失效
        //双亲委派机制,多重检测保证了安全性
    }
}

执行结果:

jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
jdk.internal.loader.ClassLoaders$PlatformClassLoader@880ec60
//根加载器是用C++写的,无法直接访问到
null
jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
null
E:\ideaWorkSpace\pan\out\production\day12_annotationreflex_01

4、创建运行时类的对象

测试代码:

package pers.mobian.annotationreflex;

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

public class TestReflexction8 {
    public static void main(String[] args) throws Exception {
        //利用反射创建对象1
        Class c1 = Class.forName("pers.mobian.annotationreflex.User");
//        User user = (User) c1.newInstance();//在jdk9之后废除了
        User user = (User) c1.getDeclaredConstructor().newInstance();//默认调用无参构造
        System.out.println(user);

        //利用反射创建对象2()
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class, String.class);
        Object user2 = constructor.newInstance("默辨", 18, 001, "男");
        System.out.println(user2); 
    }
}

执行结果:

User{name='null', age=0, id=0}
User{name='默辨', age=18, id=1}

5、获取运行时;类的完整结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g9ioGT0g-1579419151242)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200119100740164.png)]

测试代码:

package pers.mobian.annotationreflex;

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

public class TestReflexction7 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        //两种不同的方式获取
        //Class c1 = Class.forName("pers.mobian.annotationreflex.User");
        //System.out.println(c1);
        User user = new User();
        Class c1 = user.getClass();

        //获取类的名字
        System.out.println(c1.getName());//获取类的全类名
        System.out.println(c1.getSimpleName());//获取类的单独名字
        System.out.println("---");


        //获取类的属性
        Field[] fields = c1.getFields();//只能找到public属性
        for (Field field : fields) {
            System.out.println(field);
        }
        fields = c1.getDeclaredFields();//获取类的所有的方法
        for (Field field : fields) {
            System.out.println("#1:"+field);
        }
        System.out.println("--");


        //获取指定属性的值(name:“变量名”)
        Field name = c1.getField("sex");//只能获取到公共的方法
        System.out.println(name);
        name = c1.getDeclaredField("name");//能够获取到所有的方法
        System.out.println("#2:"+name);
        System.out.println("--");

        //获得类的方法
        Method[] methods = c1.getMethods();//获取到本类和父类的所有公共方法(正常类继承Object类)
        for (Method method : methods) {
            System.out.println(method);

        }
        methods = c1.getDeclaredMethods();//获取到本类的所有方法,私有+公有
        for (Method method : methods) {
            System.out.println("#3:"+method);
        }
        System.out.println("--");

        //获得指定方法
        Method test = c1.getDeclaredMethod("test",null);
        System.out.println(test);

        Method getName = c1.getMethod("getName",null);
        System.out.println(getName);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println("#4"+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("#5:"+constructor);
        }
    }
}

执行结果:

pers.mobian.annotationreflex.User
User
---
public java.lang.String pers.mobian.annotationreflex.User.sex
#1:private java.lang.String pers.mobian.annotationreflex.User.name
#1:private int pers.mobian.annotationreflex.User.age
#1:private int pers.mobian.annotationreflex.User.id
#1:public java.lang.String pers.mobian.annotationreflex.User.sex
--
public java.lang.String pers.mobian.annotationreflex.User.sex
#2:private java.lang.String pers.mobian.annotationreflex.User.name
--
public java.lang.String pers.mobian.annotationreflex.User.toString()
public java.lang.String pers.mobian.annotationreflex.User.getName()
public void pers.mobian.annotationreflex.User.setName(java.lang.String)
public int pers.mobian.annotationreflex.User.getId()
public int pers.mobian.annotationreflex.User.getAge()
public void pers.mobian.annotationreflex.User.setId(int)
public void pers.mobian.annotationreflex.User.setAge(int)
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
#3:public java.lang.String pers.mobian.annotationreflex.User.toString()
#3:public java.lang.String pers.mobian.annotationreflex.User.getName()
#3:private void pers.mobian.annotationreflex.User.test()
#3:public void pers.mobian.annotationreflex.User.setName(java.lang.String)
#3:public int pers.mobian.annotationreflex.User.getId()
#3:public int pers.mobian.annotationreflex.User.getAge()
#3:public void pers.mobian.annotationreflex.User.setId(int)
#3:public void pers.mobian.annotationreflex.User.setAge(int)
--
private void pers.mobian.annotationreflex.User.test()
public java.lang.String pers.mobian.annotationreflex.User.getName()
#4public void pers.mobian.annotationreflex.User.setName(java.lang.String)
--
public pers.mobian.annotationreflex.User(java.lang.String,int,int,java.lang.String)
public pers.mobian.annotationreflex.User()
#5:public pers.mobian.annotationreflex.User(java.lang.String,int,int,java.lang.String)
#5:public pers.mobian.annotationreflex.User()

6、调用运行时类的指定结构

6.1获取指定结构

测试代码:

package pers.mobian.annotationreflex;

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

public class TestReflexction8 {
    public static void main(String[] args) throws Exception {
        //利用反射创建对象1
        Class c1 = Class.forName("pers.mobian.annotationreflex.User");
//        User user = (User) c1.newInstance();//在jdk9之后废除了
        User user = (User) c1.getDeclaredConstructor().newInstance();//默认调用无参构造
        System.out.println(user);

        //利用反射创建对象2()
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class, String.class);
        Object user2 = constructor.newInstance("默辨", 18, 001, "男");
        System.out.println(user2);


        //通过反射调用普通方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke : 激活的意思
        //(对象, " 方法的值" )
        Object mobian = setName.invoke(user, "mobian");
        System.out.println(user.getName());


        //通过反射操作属性
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性,需要关闭安全监测,设置属性或者方法.setAccessible(true)
        name.setAccessible(true);
        name.set(user,"pan");
        System.out.println(user.getName());

        //打印对象
        System.out.println(user);
    }
}

执行结果:

User{name='null', age=0, id=0}
User{name='默辨', age=18, id=1}
mobian
pan
User{name='pan', age=0, id=0}

补充两个方法:

invoke

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6J119hyN-1579419151245)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200119114447743.png)]

setAccessible

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vYupSYwB-1579419151247)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200119114409591.png)]

6.2 对比三种方式的性能

三种方式:正常创建对象获取,反射创建对象获取,关闭权限检测对象获取

测试代码:

package pers.mobian.annotationreflex;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Timer;

public class TestReflexction9 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        test1();
        test2();
        test3();
    }

    public static void test1() {
        User user = new User();
        long startTime = System.currentTimeMillis();

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

        System.out.println("执行时间是:" + (endTime - startTime) + "ms");
    }

    public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        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("执行时间是:" + (endTime - startTime) + "ms");
    }

    public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        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("执行时间是:" + (endTime - startTime) + "ms");
    }
}

执行结果:

执行时间是:12ms
执行时间是:6113ms
执行时间是:2702ms

6.3 获取泛型信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cVnXgVsQ-1579419151249)(C:\Users\Mrpan\AppData\Roaming\Typora\typora-user-images\image-20200119143309974.png)]

测试代码:

package pers.mobian.annotationreflex;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

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

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

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = TestReflexction10.class.getMethod("test01", Map.class, List.class);
        //1、通过方法获得他的参数类型列表
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            //2、打印参数类型
            System.out.println("#" + genericParameterType);
            //3、对每一个参数类型进行进行判定,如果是结构化的参数类型,就再对其进行打印
            if (genericParameterType instanceof ParameterizedType) {
                //4、获得真实参数信息
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                //5、打印相对应的强转以后的参数
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }

        }

        System.out.println("====");
        Method method2 = TestReflexction10.class.getMethod("test02");
        //1、通过方法获得他的返回值参数信息
        Type genericReturnType = method2.getGenericReturnType();
        //2、对返回值参数信息进行判定,如果是属于结构化的参数类型,就再对其进行打印
        if (genericReturnType instanceof ParameterizedType) {
            //3、获取真实的返回值类型
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            //4、打印强壮以后的返回值参数类型
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("$" + actualTypeArgument);
            }
        }
    }
}

执行结果:

#java.util.Map<java.lang.String, pers.mobian.annotationreflex.User>
class java.lang.String
class pers.mobian.annotationreflex.User
#java.util.List<pers.mobian.annotationreflex.User>
class pers.mobian.annotationreflex.User
====
$class java.lang.String
$class pers.mobian.annotationreflex.User

6.4 获取注解信息

测试代码:

package pers.mobian.annotationreflex;

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

public class TestReflexction11 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("pers.mobian.annotationreflex.Student2");

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

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

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

        f = c1.getDeclaredField("id");
        annotation = f.getAnnotation(Field_mobian.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());

    }
}

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

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field_mobian {
    String columnName();

    String type();

    int length();
}

@Table_mobian("db_student")
class Student2 {
    @Field_mobian(columnName = "db_id", type = "int ", length = 10)
    private int id;

    @Field_mobian(columnName = "db_age", type = "int ", length = 10)
    private int age;

    @Field_mobian(columnName = "db_name", type = "vaechar ", 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 + '\'' +
                '}';
    }
}

执行结果:

@pers.mobian.annotationreflex.Table_mobian(value="db_student")
db_student
db_name
vaechar
3
db_id
int 
10
发布了9 篇原创文章 · 获赞 5 · 访问量 847

猜你喜欢

转载自blog.csdn.net/qq_44377709/article/details/104041511