一、注解

1. 初识注解

package com.onlineframework;

import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("all")
public class annoTest {
    @Override
    public String toString() {
        return super.toString();
    }
    @Deprecated
    public static void dep(){
        System.out.println("dep");
    }

    public static void test02(){
        List list = new ArrayList();
    }

    public static void main(String[] args) {
        dep();
        test02();
    }
}

2. 元注解

package com.onlineframework;

import java.lang.annotation.*;

@MyAnnotation
public class AnnoTest02 {
    @MyAnnotation
    public void test(){

    }
}
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
@Inherited
@interface MyAnnotation{    //@interface自动继承了java.lang.annotation.Annotation接口

}

3. 自定义注解,设置其默认值

package com.onlineframework;

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

public class AnnoTest03 {
    @MyAnnotation2()
    @MyAnnotation3("OK")
    public void test(){

    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2 {
    //定义参数:参数类型 + 参数名
    String name() default "";
    int age() default 0;
    int id() default -1;
    String[] schools() default {};
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
    String[] value();
}

二、反射

1. 什么是反射

package com.onlineframework;

//什么是反射
public class ReflectionTest01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //一个类被加载后,类的整个结构都会被封装在Class对象中
        //三种获得Class对象的方法
        Class c1 = Class.forName("com.onlineframework.User");
        Class c2 = new User().getClass();
        Class c3 = User.class;
        System.out.println(c1.hashCode() == c2.hashCode() && c2.hashCode() == c3.hashCode()); //一个类在内存中只有一个Class对象
        
    }
}

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + 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;
    }
}

2. 获得父类对象

package com.onlineframework;

public class ReflectionTest02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person p = new Student();
        Class c1 = p.getClass();
        Class c2 = Class.forName("com.onlineframework.Person");
        Class c3 = Person.class;
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());

        //内置包装类都有一个TYPE属性
        Class<Integer> c4 = Integer.TYPE;
        System.out.println(c4);

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

class Person{
    public String name;
    public int age;

}
class Student extends Person{
    public Student(){
        this.name = "stu";
    }
}
class Teacher extends Person{
    public Teacher(){
        this.name = "teach";
    }
}

3. 各种类型的Class对象

package com.onlineframework;

import java.lang.annotation.ElementType;

public class ReflectionTest04 {
    public static void main(String[] args) {
        Class objectClass = Object.class;   //类
        Class comparableClass = Comparable.class; //接口
        Class strArrayClass = String[].class;//一维数组
        Class intArrayClass = int[][].class;//二维数组
        Class overrideClass = Override.class;//注解
        Class elementTypeClass = ElementType.class; //枚举
        Class integerClass = Integer.class;//基本数据类型
        Class voidClass = void.class;//void
        Class classClass = Class.class;

        System.out.println(objectClass);
        System.out.println(comparableClass);
        System.out.println(strArrayClass);
        System.out.println(intArrayClass);
        System.out.println(overrideClass);
        System.out.println(elementTypeClass);
        System.out.println(integerClass);
        System.out.println(voidClass);
        System.out.println(classClass);

        int [] a = new int[10];
        int [] b = new int[20];
        System.out.println(a.getClass().hashCode());    //只要类型与维度一样,就是同一个Class
        System.out.println(b.getClass().hashCode());
        System.out.println(a.getClass().hashCode() == b.getClass().hashCode()); //true

    }
}

4. 类加载的过程、Class对象加载的时机

package com.onlineframework;

public class ReflectionTest05 {
    public static void main(String[] args) {
        System.out.println("new之前");
        System.out.println(A.m);
        System.out.println("new之前");
        A a = new A();
        System.out.println(A.m);

        /*
        * 1. 加载,会产生一个类对应的Class对象
        * 2. 链接,链接结束后 m = 0
        * 3. 初始化,
        *     <clinit>(){
        *       m=300;
        *       System.out.println("静态代码块");
        *       m=100;
        *     }
        *   此时 m = 100
        * */
    }
}
class A{
    static {
        m=300;
        System.out.println("静态代码块");
    }
    static int m = 100;
    public A(){
        System.out.println("无参构造");
    }
}

5. 类初始化的时机

package com.onlineframework;

//类什么时候初始化?
public class ReflectionTest06 {
    static {
        System.out.println("Main init");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //Son son = new Son();
        /*
          Main init
          Father init
          Son init
        */

        //Class.forName("com.onlineframework.Son");
        /*
          Main init
          Father init
          Son init
        */

        //System.out.println(Son.b); //Son类不会加载
        /*
          Main init
          Father init
          2
        */

        //Son[] array = new Son[5];   //不会引起任何初始化
        /*Main init*/

        System.out.println(Son.M);      //常量在链接阶段就被赋值,不引起任何初始化
        /*Main init*/


    }

}
class Father {
    static {
        System.out.println("Father init");
    }
    static int b = 2;
}
class Son extends Father{
    static {
        System.out.println("Son init");
        m = 300;
    }
    static int m = 100;
    static final int M = 1;
}

6. 三种ClassLoader

package com.onlineframework;

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

        //系统类加载器的父类加载器  --> 扩展类加载器
        //负责jre/lib/ext目录下的jar包加载,或者 -D java.ext.dirs 指定目录下的jar包加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //扩展类加载器的父类加载器 --> 根加载器(C/C++),无法直接获取
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        //sun.misc.Launcher$AppClassLoader@18b4aac2
        //sun.misc.Launcher$ExtClassLoader@1b6d3586
        //null

        ClassLoader classLoader = Class.forName("com.onlineframework.ReflectionTest07").getClassLoader();
        System.out.println(classLoader);    //sun.misc.Launcher$AppClassLoader@18b4aac2

        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);   //跟加载器:null

        System.out.println(System.getProperty("java.class.path"));
        /* C:\Program Files\Java\jdk1.8.0_271\jre\lib\charsets.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\deploy.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\access-bridge-64.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\cldrdata.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\dnsns.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jaccess.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jfxrt.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\localedata.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\nashorn.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunec.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunjce_provider.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunmscapi.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunpkcs11.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\zipfs.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\javaws.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\jce.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfr.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfxswt.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\jsse.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\management-agent.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\plugin.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\resources.jar;
        C:\Program Files\Java\jdk1.8.0_271\jre\lib\rt.jar;
        C:\Users\perfxlab_000\IdeaProjects\jbasic\target\classes;
        F:\Program Files\JetBrains\IntelliJ IDEA 2021.3.1\lib\idea_rt.jar
       */
        //双亲委派机制:自定义的类例如 java.lang.String 无法替代根加载器加载的类,提高安全性
    }
}

7. 获得类的信息

package com.onlineframework;

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

//获得类的信息
public class ReflectionTest08 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.onlineframework.User");

        System.out.println(c1.getName());       //获得包名+类名  com.onlineframework.User
        System.out.println(c1.getSimpleName()); //获得类名      User

        System.out.println("======================================================");
        for (Field field : c1.getFields()) {    //只能找到public属性
            System.out.println(field);
        }
        //Field name = c1.getField("name");  // 获取不到

        System.out.println("==============getDeclaredFields============================");
        for (Field declaredField : c1.getDeclaredFields()) {    //获得所有属性
            System.out.println(declaredField);
        }

        Field name1 = c1.getDeclaredField("name");
        System.out.println(name1);
        System.out.println("==============getMethods=======================");
        for (Method method : c1.getMethods()) { //获得所有public方法(包括父类),不包括所有private
            System.out.println(method);
        }

        System.out.println("==============getDeclaredMethods=======================");
        for (Method declaredMethod : c1.getDeclaredMethods()) { //只获得该类内方法,包括private
            System.out.println(declaredMethod);
        }

        System.out.println("==============getMethod=======================");
        Method getName = c1.getMethod("getName", null);
        System.out.println(getName);
        System.out.println(c1.getMethod("setName", String.class));

        System.out.println("==============getConstructors (public only)=======================");
        Constructor[] constructors = c1.getConstructors();

        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        System.out.println("==============getDeclaredConstructors (all)=======================");
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        System.out.println("==============getDeclaredConstructor=======================");
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, Integer.TYPE, Integer.TYPE);
        System.out.println(declaredConstructor);

    }
}

8. 通过反射动态创建对象

package com.onlineframework;

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

//通过反射动态创建对象
public class ReflectionTest09 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class c1 = Class.forName("com.onlineframework.User");

        User newInstance = (User)c1.newInstance();  //无参构造器
        System.out.println(newInstance);        // User{name='null', id=0, age=0}

        //通过构造器创建对象
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        Object aaa = declaredConstructor.newInstance("aaa", 11, 12);
        System.out.println(aaa);        // User{name='aaa', id=11, age=12}

        //通过反射调用方法
        User user = (User) c1.newInstance();
        Method setName = c1.getMethod("setName", String.class);
        setName.invoke(user,"name1");
        System.out.println(user);       // User{name='name1', id=0, age=0}

        //通过反射操作属性(private异常)
        Field name = c1.getDeclaredField("name");
        //name.set(user,"name2");
        System.out.println(user);

        //通过反射操作属性
        name.setAccessible(true);
        name.set(user,"name3");
        System.out.println(user);

    }
}

9. 反射的性能

package com.onlineframework;

import javax.jws.soap.SOAPBinding;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//性能问题
public class ReflectionTest10 {

    public static void test_ordinary(){
        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 test_reflection() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.getMethod("getName");
        long startTime = System.currentTimeMillis();

        for (int i=0;i< 1000000000 ;i++){
            getName.invoke(user);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方法:"+(endTime - startTime) +"ms");
    }
    public static void test_reflection_without_accessible() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.getMethod("getName");
        getName.setAccessible(true);
        long startTime = System.currentTimeMillis();

        for (int i=0;i< 1000000000 ;i++){
            getName.invoke(user);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方法关闭检测:"+(endTime - startTime) +"ms");
    }

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test_ordinary();
        test_reflection();
        test_reflection_without_accessible();

        //普通方法:4ms
        //反射方法:2228ms
        //反射方法关闭检测:1485ms
    }
}

10. 反射获取泛型

package com.onlineframework;

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 ReflectionTest11 {
    public void test1(Map<String,User> map, List<User> list){
        System.out.println("test1");
    }

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

    public static void main(String[] args) throws NoSuchMethodException {
        Method method1 = ReflectionTest11.class.getMethod("test1", Map.class, List.class);

        //获得参数的泛型类型
        Type[] genericParameterTypes1 = method1.getGenericParameterTypes();

        for (Type type : genericParameterTypes1) {
            System.out.println(type);
            if(type instanceof ParameterizedType){  //ParameterizedType 参数化类型,例如Collection<String>
                Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("  "+actualTypeArgument);
                }
            }
        }
        System.out.println("======================test2================");
        Method test2 = ReflectionTest11.class.getMethod("test2");
        Type genericReturnType = test2.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }

    }
}

11. 注解与反射

package com.onlineframework;

import java.lang.annotation.*;

public class ReflectionTest12 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.onlineframework.Student2");
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);     //@com.onlineframework.Student2Table(value=db_student)
        }
        //获得注解的value
        Student2Table c1Annotation = (Student2Table)c1.getAnnotation(Student2Table.class);
        System.out.println(c1Annotation.value());//db_student

        //获得注解的其他属性
        Student2Field nameAnnotation = (Student2Field)c1.getDeclaredField("name").getAnnotation(Student2Field.class);
        System.out.println(nameAnnotation.col());//db_name

    }
}

@Student2Table("db_student")
class Student2 {
    @Student2Field(col = "db_name",type = "char",length = 10)
    private String name;
    @Student2Field(col = "db_id",type = "int",length = 10)
    private int id;
    @Student2Field(col = "db_age",type = "int",length = 10)
    private int age;

    public Student2(){

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

    @Override
    public String toString() {
        return "Student2{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", 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;
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Student2Table{
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Student2Field{
    String col();
    String type();
    int length();
}