目录
    
   
    
     1.1 、直接通过一个 class 的静态变量class获取
    
   
    
     1.2、如果有一个实例变量,通过该实例变量提供的 getClasss() 方法获取
    
   
    
     1.3、知道一个 class 的完整类名,通过Class.forName()获取
    
   
通过 Class 实例获取 class 信息的方法称为反射(Reflection)。
由于 JVM 为每个加载的类创建了对应的类实例,并在实例中保存了该类的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段等。因此,如果获得了某个类实例,就可以通过这个类实例取到实例对应的类的所有信息。
    一、获取 Class 实例
   
获取一个 class 的 Class 实例三种方法:
    1.1 、直接通过一个 class 的静态变量class获取
   
Class clazz = String.class;
    1.2、如果有一个实例变量,通过该实例变量提供的 getClasss() 方法获取
   
如果有一个实例变量,可以通过该实例变量提供的 getClass() 方法获取
String str = "hello world";
Class clazz = str.getClass();    
    1.3、知道一个 class 的完整类名,通过
    
     Class.forName()
    
    获取
   
Class.forName()
 Class clazz =  Class.forName("java.lang.String");因为Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例。可以用==比较两个Class实例:
public class Main {
    public static void main(String[] args) throws Exception {
        Class clazz1 = String.class;
        String str = "Hello world";
        Class clazz2 = str.getClass();
        Class clazz3 = Class.forName("java.lang.String");
        System.out.println(clazz1 == clazz2); //true
        System.out.println(clazz1 == clazz3); //true
        System.out.println(clazz2 == clazz3);//true
    }
}class 实例比较和 instanceof 的差别:
public class Main {
    public static void main(String[] args) throws Exception {
        Integer n = new Integer(123);
        boolean b1 = n instanceof Integer; // true,因为n是Integer类型
        boolean b2 = n instanceof Number; // true,因为n是Number类型的子类
        boolean b3 = n.getClass() == Integer.class; // true,因为n.getClass()返回Integer.class
        boolean b4 = n.getClass() == Number.class; // false,因为Integer.class!=Number.class
    }
}用 instanceof 不但匹配指定类型,还匹配指定类型的子类,而用 == 判断class 实例可以精确地判断数据类型,但不能作为比较子类型比较。
通常情况,用 instanceof 判断数据类型,应为面向抽象编程地时候,不关心具体地子类型。只有在需要精确判断一个类型是不是某个 class 的时候,才使用 == 判断 class 实例。
反射的目的是为了获取某个实例的信息,因为当拿到某个 object 实例时,可以通过反射获取 object 的 class 信息。
例如获取到一个 Class 实例 ,就可以通过该 Class 实例来创建对应类型的实例:
public class Main {
    public static void main(String[] args) throws Exception{
        // 获取String的Class实例:
        Class cls = String.class;
        // 创建一个String实例:
        String s = (String) cls.newInstance();
    }
}
上述代码相当于 new String()。 通过 Class.newInstance 可以创建实例,它的局限性是只能调用 public 的无参构造方法。带参数的构造方法或者非 public 的构造方法都无法通过 Class.newInstance() 被调用。
    
     动态加载
    
   
    
    
    JVM 在执行 Java 程序的时候,并不是一次性把所有用到的 class 全部加载到内存,而是第一次需要用到 class 时才加载。例如:
   
// Main.java
public class Main {
        public static void main(String[] args) {
            if (args.length > 0) {
                create(args[0]);
            }
        }
        static void create(String name) {
            Person p = new Person(name);
        }
}当执行Main.java 时,由于用到 Main, JVM会把 Main.class 加载到内存。然后,并不会加载 Person.class ,除非程序执行到 create() 方法, JVM 发现需要加载 Person 类时,才会首次加载 Person.class 。如果没有加载 create() 方法,那么 Person.class 就不会被加载。这就是 JVM 动态加载 class 的特性。
Class 类扩展方法
| 方法 | 描述 | 
| String toGenericString() | 返回一个描述这个类的字符串信息,包含修饰符和类型参数的信息 | 
| forName(String className) | 根据类的完整路径返回Class对象 | 
| forName(String name, boolean initialize,ClassLoader loader) | 根据类的完整路径返回Class对象 | 
| T newInstance() | 创建类的实例 | 
| boolean isInstance(Object obj) | 判断是否是类的实例 | 
| boolean isAssignableFrom(Class<?> cls) | 判断当前的Class对象所表示的类,是不是参数中传递的Class对象所表示的类的父类 | 
| boolean isInterface() | 判断是否接口 | 
| boolean isPrimitive() | 判断是否为原始基本类型(例如int、char、long..) | 
| boolean isAnnotation() | 判断是否注解类型 | 
| boolean isSynthetic() | 判断是的合成类 | 
| String getName() | 获取类名称 | 
| getClassLoader() | 获取加载器 | 
| Class<? super T> getSuperclass() | 获取父类 | 
| Type getGenericSuperclass() | 获取直接父类,并且父类的泛型类型也会返回 | 
| Package getPackage() | 获取包名 | 
| Class<?>[] getInterfaces() | 获得这个对象所实现的所有接口 | 
| Type[] getGenericInterfaces() | 获得这个对象所实现的所有接口并且返回接口泛型 | 
| Class<?> getComponentType() | 获取一个数组的Class对象 | 
| int getModifiers() | 获取修饰符 | 
| Object[] getSigners() | 返回类的签名者 | 
| Method getEnclosingMethod() | 当此Class对象表示方法内部的本地或匿名类时,使用getEnclosingMethod()方法返回基础类的最新封闭方法 | 
| Constructor<?> getEnclosingConstructor() | 如果此类是在该构造函数中声明的本地类或匿名类,则方法返回此类的封闭构造函数 | 
| Class<?> getDeclaringClass() | 返回表示在它被声明的类的Class对象,如果此Class对象所表示的类或接口是另一个类成员 | 
| Class<?> getEnclosingClass() | 返回底层的直接外围类。如果底层类是顶级类(Object)则返回null | 
| String getSimpleName() | 获取简单类名 | 
| String getCanonicalName() | 获取规范名称 | 
| boolean isAnonymousClass() | 判断是否匿名内部类 | 
| boolean isLocalClass() | 判断是否为本地类 | 
| boolean isMemberClass() | 判断是否成员类 | 
| Class<?>[] getClasses() | 返回Class 对象数组(不包含private修饰) | 
| Field[] getFields() | 返回公共字段(public 修饰) | 
| Method[] getMethods() | 返回公共方法(public 修饰) | 
| Constructor<?>[] getConstructors() | 获取构造方法(public 修饰) | 
| Field getField(String name) | 根据参数获取字段信息(public 修饰) | 
| Method getMethod(String name, Class<?>… parameterTypes) | 返回Method对象匹配指定名称和parameterTypes(public 修饰) | 
| Constructor<T> getConstructor(Class<?>… parameterTypes) | 返回一个 Constructor 对象,该对象反映了此 Class 对象表示的类的指定公共构造函数 | 
| Class<?>[] getDeclaredClasses() | 返回Class 对象数组 | 
| Field[] getDeclaredFields() | 获取类字段信息 | 
| Method[] getDeclaredMethods() | 获取类方法 | 
| Constructor<?>[] getDeclaredConstructors() | 获取构造方法 | 
| Field getDeclaredField(String name) | 根据参数获取字段信息 | 
| Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回Method对象匹配指定名称和parameterTypes | 
| Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes) | 根据参数获取对应构造方法 | 
| InputStream getResourceAsStream(String name) | 查找具有给定名称的资源 | 
| java.net.URL getResource(String name) | 查找具有给定名称的资源,返回URL | 
| java.security.ProtectionDomain getProtectionDomain() | 返回类的 ProtectionDomain 对象 | 
| boolean desiredAssertionStatus() | 该方法以布尔值的形式返回该类的指定断言状态 | 
| boolean isEnum() | 判断是否枚举 | 
| T[] getEnumConstants() | 获取枚举元素 | 
| T cast(Object obj) | 将对象强制转换为所表示的类或接口 | 
| <U> Class<? extends U> asSubclass(Class<U> clazz) | 强制把Class对象转化成参数类的子类 | 
| AnnotatedType getAnnotatedSuperclass() | 获取当前类的父类,可以用 AnnotatedType 来描述,也就是说它们申明了泛型并且被注解标注 | 
| AnnotatedType[] getAnnotatedInterfaces() | 获取当前类的接口,可以用 AnnotatedType[] 来描述,也就是说它们申明了泛型并且被注解标 | 
示例
import com.sun.javafx.geom.transform.Identity;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.security.ProtectionDomain;
import java.util.HashMap;
public class Main {
    public Integer age;
    private String userName;
    public Main() {
    }
    private Main(Integer age, String userName) {
        this.age = age;
        this.userName = userName;
    }
    public void showLong(Long l) {
    }
    private void say(Long l) {
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Main{" +
                "userName='" + userName + '\'' +
                '}';
    }
    public static void main(String[] args) {
        printClassInfo();
    }
    static void printClassInfo() {
        //返回一个描述这个类的字符串信息,包含修饰符和类型参数的信息
        toGenericString();
        //根据类的完整路径,加载类,返回Class对象
        clssForName();
        //创建类的实例
        newInstance();
        // 判断是否是类的实例
        isInstance();
        //判断当前的Class对象所表示的类,是不是参数中传递的Class对象所表示的类的父类
        isAssignableFrom();
        // 判断是否接口
        isInterface();
        // 判断是否数组
        isArray();
        //判断是否为原始基本类型(例如int、char、long..)
        isPrimitive();
        // 判断是否注解类型
        isAnnotation();
        /**
         * 判断是的合成类
         * https://blog.sina.com.cn/s/blog_1534f339a0102y88n.html
         *
         */
        // 获取类名称
        getName();
        // 获取加载器
        getClassLoader();
        // 获取父类(public 修饰)
        getSuperclass();
        // 获取直接父类,并且父类的泛型类型也会返回
        getGenericSuperclass();
        // 获取包名
        getPackage();
        // 获得这个对象所实现的所有接口
        getInterfaces();
        // 获得这个对象所实现的所有接口并且返回接口泛型
        getGenericInterfaces();
        // 获取一个数组的Class对象
        getComponentType();
        // 获取修饰符
        getModifiers();
        // 返回类的签名者
        getSigners();
        // 当此Class对象表示方法内部的本地或匿名类时,使用getEnclosingMethod()方法返回基础类的最新封闭方法
        getEnclosingMethod();
        // 如果此类是在该构造函数中声明的本地类或匿名类,则方法返回此类的封闭构造函数
        getEnclosingConstructor();
        //返回表示在它被声明的类的Class对象,如果此Class对象所表示的类或接口是另一个类成员
        getDeclaringClass();
        // 返回底层的直接外围类。如果底层类是顶级类(Object)则返回null
        getEnclosingClass();
        // 获取简单类名
        getSimpleName();
        // 获取规范名称
        getCanonicalName();
        // 判断是否匿名内部类
        isAnonymousClass();
        // 判断是否为本地类
        isLocalClass();
        // 判断是否成员类
        isMemberClass();
        // 返回Class 对象数组(不包含private修饰)
        getClasses();
        //返回公共字段(public 修饰)
        getFields();
        //返回公共方法(public 修饰)
        getMethods();
        // 获取构造方法(public 修饰)
        getConstructors();
        // 根据参数获取字段信息(public 修饰)
        getField();
        //返回Method对象匹配指定名称和parameterTypes(public 修饰)
        getMethod();
        //返回一个 Constructor 对象,该对象反映了此 Class 对象表示的类的指定公共构造函数
        getConstructor();
        //返回Class 对象数组
        getDeclaredClasses();
        // 获取类字段信息
        getDeclaredFields();
        //获取类方法
        getDeclaredMethods();
        // 获取构造方法
        getDeclaredConstructors();
        // 根据参数获取字段信息
        getDeclaredField();
        // 返回Method对象匹配指定名称和parameterTypes
        getDeclaredMethod();
        // 根据参数获取对应构造方法
        getDeclaredConstructor();
        // 查找具有给定名称的资源
        getResourceAsStream();
        // 查找具有给定名称的资源,URL
        getResource();
        //返回类的 ProtectionDomain 对象
        getProtectionDomain();
        //该方法以布尔值的形式返回该类的指定断言状态
        desiredAssertionStatus();
        // 判断是否枚举
        isEnum();
        // 获取枚举元素
        getEnumConstants();
        //将对象强制转换为所表示的类或接口
        cast();
        //强制把Class对象转化成参数类的子类
        asSubclass();
        // 获取当前类的父类,可以用 AnnotatedType 来描述,也就是说它们申明了泛型并且被注解标注
        getAnnotatedSuperclass();
        //获取当前类的接口,可以用 AnnotatedType[] 来描述,也就是说它们申明了泛型并且被注解标注
        getAnnotatedInterfaces();
    }
    //返回一个描述这个类的字符串信息,包含修饰符和类型参数的信息
    static void toGenericString() {
        Class clazz = Runnable.class;
        System.out.println("toGenericString: " + clazz);
    }
    // 根据类的完整路径返回与类或关联的Class对象
    static void clssForName() {
        try {
            // 参数:类的完整路
            Class clazz1 = Class.forName("Main");
            ClassLoader cLoader = clazz1.getClassLoader();
            /**
             * 参数一:类的完整路
             * 参数二 类是否初始化  true:初始化  false 不初始化
             * 参数三:加载器
             */
            Class clazz2 = Class.forName("java.lang.String", true, cLoader);
            System.out.println("Class.forName():" + clazz1);
            System.out.println("Class.forName(...):" + clazz2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    // 创建类的实例
    static void newInstance() {
        try {
            Class clazz = Main.class;
            // 创建Main类的实例
            Main main = (Main) clazz.newInstance();
            main.setUserName("张三");
            System.out.println("newInstance: " + main.toString());
        } catch (Exception e) {
        }
    }
    // 判断是否属于类的实例
    static void isInstance() {
        try {
            Class clazz = Class.forName("Main");
            Class clazz1 = Class.forName("java.lang.String");
            // 创建Main类的实例
            Main main = (Main) clazz.newInstance();
            // 判断是否是类的实例
            boolean result = clazz.isInstance(main); // true
            boolean result1 = clazz1.isInstance(main); // false
            System.out.println("isInstance: result = " + result + " result1=" + result1);
        } catch (Exception e) {
        }
    }
    // 判断当前的Class对象所表示的类,是不是参数中传递的Class对象所表示的类的父类
    static void isAssignableFrom() {
        try {
            Class parent = Class.forName("Parent");
            Class Son = Class.forName("Son");
            //
            Boolean result = parent.isAssignableFrom(Son); // true
            System.out.println("isAssignableFrom: result = " + result);
        } catch (Exception e) {
        }
    }
    // 判断是否接口
    static void isInterface() {
        try {
            Class demoService = Class.forName("DemoService");
            Boolean result = demoService.isInterface();
            System.out.println("isInterface: result = " + result);// true
        } catch (Exception e) {
        }
    }
    // 判断是否数组
    static void isArray() {
        Class clazz = String[].class;
        Boolean result = clazz.isArray();
        System.out.println("isInterface: result = " + result); // true
    }
    // 判断是否为原始基本类型(例如int、char、long..)
    static void isPrimitive() {
        String str = new String();
        Class cl1 = str.getClass();
        //创建并返回short-
        // short sh = 10;
        Class cl2 = short.class; // true
        // Class cl2 = Integer.class; // false
        Boolean result = cl1.isPrimitive(); //false
        Boolean result1 = cl2.isPrimitive(); //true
        System.out.println("isPrimitive: result = " + result + "   result1 = " + result1);
    }
    // 判断是否注解类型
    static void isAnnotation() {
        Class ann1 = Identity.class;
        Class ann2 = Deprecated.class;
        System.out.println("isAnnotation  ann1= " + ann1.isAnnotation() + "    ann2=" + ann2.isAnnotation());
    }
    //获取类名称
    static void getName() {
        Class clazz = Main.class;
        System.out.println("getName = " + clazz.getName());
    }
    // 获取类加载器
    static void getClassLoader() {
        Class clazz = Main.class;
        System.out.println("getClassLoader = " + clazz.getClassLoader());
    }
    // 获取父类
    static void getSuperclass() {
        Class clazz = Son.class;
        System.out.println("getSuperclass = " + clazz.getSuperclass());
    }
    // 获取直接父类
    static void getGenericSuperclass() {
        Class clazz = Son.class;
        System.out.println("getGenericSuperclass = " + clazz.getGenericSuperclass());
    }
    // 获取包名
    static void getPackage() {
        Class clazz = String.class;
        System.out.println("getPackage = " + clazz.getPackage());
    }
    // 获得这个对象所实现的所有接口
    static void getInterfaces() {
        Class clazz = DemoServiceImpl.class;
        Class[] arr = clazz.getInterfaces();
        if (null != arr && arr.length > 0) {
            System.out.println("getInterfaces arr = " + arr[0]);
        }
    }
    // 获得这个对象所实现的所有接口并且返回接口泛型
    static void getGenericInterfaces() {
        Class clazz = DemoServiceImpl.class;
        Type[] arr = clazz.getGenericInterfaces();
        if (null != arr && arr.length > 0) {
            System.out.println("getGenericInterfaces arr = " + arr[0]);
        }
    }
    // 获取一个数组的Class对象
    static void getComponentType() {
        Class clazz = String[].class;
        Class componentType = clazz.getComponentType();
        Class clazz1 = String.class;
        Class componentType1 = clazz1.getComponentType();
        System.out.println("getComponentType   = " + componentType + " getComponentType=" + componentType1);
    }
    // 获取修饰符
    static void getModifiers() {
        Class clazz = Main.class;
        int modifiers = clazz.getModifiers();
        System.out.println("getModifiers  = " + modifiers);
    }
    // 返回类的签名者
    static void getSigners() {
        try {
            Class cls = Main.class;
            Object[] obj = cls.getSigners();
            System.out.println("getSigners  = " + obj);
        } catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
    // 当此Class对象表示方法内部的本地或匿名类时,使用getEnclosingMethod()方法返回基础类的最新封闭方法
    static void getEnclosingMethod() {
        try {
            Class c = (new Out()).ClassAObject().getClass();
            System.out.println("getEnclosingMethod() = " + c.getEnclosingMethod());
        } catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
    // 如果此类是在该构造函数中声明的本地类或匿名类,则方法返回此类的封闭构造函数
    static void getEnclosingConstructor() {
        try {
            Class c = (new Out()).c.getClass();
            System.out.println("getEnclosingConstructor() = " + c.getEnclosingConstructor());
        } catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
    // 返回这个类的声明类。
    static void getDeclaringClass() {
        Class cl = Integer.class;
        // It returns an array of Methods
        // that denotes the private, protected, public and default
        // Methods of the class Integer
        Method[] methods = cl.getMethods();
        // Traverse Integer class
        // for (int i = 0; i < methods.length; ++i) {
        Class declare_classes = methods[0].getDeclaringClass();
        System.out.println(" getDeclaringClass= " + declare_classes.toString());
        // }
    }
    /**
     * 返回底层直接外围类
     */
    static void getEnclosingClass() {
        Class clazz = new Out().c.getClass();
        Class clazz1 = Object.class;
        System.out.println(" getEnclosingClass= " + clazz.getEnclosingClass());
        System.out.println(" getEnclosingClass= " + clazz1.getEnclosingClass());
    }
    // 获取简单类名
    static void getSimpleName() {
        Class clazz = String.class;
        System.out.println(" getSimpleName= " + clazz.getSimpleName());
    }
    // 获取规范名称
    static void getCanonicalName() {
        Class clazz = String.class;
        System.out.println(" getCanonicalName= " + clazz.getCanonicalName());
    }
    // 判断是否匿名类
    static void isAnonymousClass() {
        Class clazz = new HashMap<String, String>() {
            // 匿名类
        }.getClass();
        System.out.println(" isAnonymousClass= " + clazz.isAnonymousClass());
    }
    // 判断是否为本地类
    static void isLocalClass() {
        class A {
        }
        Class clazz = A.class;
        Class clazz1 = Out.class;
        System.out.println(" isLocalClass= " + clazz.isLocalClass() + "  isLocalClass=" + clazz1.isLocalClass());
    }
    // 判断是否成员类
    static void isMemberClass() {
        class A {
        }
        Class clazz = A.class;
        Class clazz1 = Out.class;
        System.out.println(" isMemberClass= " + clazz.isLocalClass() + "  isMemberClass=" + clazz1.isLocalClass());
    }
    // 返回Class 对象数组
    static void getClasses() {
        Class clazz = Main.class;
        Class[] clazzArr = clazz.getClasses();
        for (int i = 0; i < clazzArr.length; i++) {
            System.out.println("getClasses = " + clazzArr[i].getName());
        }
    }
    // 返回公共字段(public 修饰)
    static void getFields() {
        Class clazz = Main.class;
        Field[] clazzArr = clazz.getFields();
        for (int i = 0; i < clazzArr.length; i++) {
            System.out.println("getFields = " + clazzArr[i]);
        }
    }
    // 返回公共方法(public 修饰)
    static void getMethods() {
        Class clazz = Main.class;
        Method[] clazzArr = clazz.getMethods();
        for (int i = 0; i < clazzArr.length; i++) {
            System.out.println("getMethods = " + clazzArr[i]);
        }
    }
    // 获取构造方法
    static void getConstructors() {
        Class clazz = Main.class;
        Constructor[] clazzArr = clazz.getConstructors();
        for (int i = 0; i < clazzArr.length; i++) {
            System.out.println("getConstructors = " + clazzArr[i]);
        }
    }
    // 根据参数获取字段信息,不包含(private 修饰)
    static void getField() {
        try {
            Class clazz = Main.class;
            Field field = clazz.getField("age");
            System.out.println("getField=" + field);
        } catch (Exception e) {
        }
    }
    // 返回Method对象匹配指定名称和parameterTypes
    static void getMethod() {
        try {
            Class clazz = Main.class;
            Class[] cArg = new Class[1];
            cArg[0] = Long.class;
            Method method = clazz.getMethod("showLong", cArg);
            System.out.println("getMethod=" + method.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //返回一个 Constructor 对象,该对象反映了此 Class 对象表示的类的指定公共构造函数
    static void getConstructor() {
        try {
            Class cls[] = new Class[]{String.class};
            Constructor c = String.class.getConstructor(cls);
            System.out.println("getConstructor=" + c);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 返回Class 对象数组
    static void getDeclaredClasses() {
        Class clazz = Main.class;
        Class[] clazzArr = clazz.getDeclaredClasses();
        for (int i = 0; i < clazzArr.length; i++) {
            System.out.println("getDeclaredClasses = " + clazzArr[i].getName());
        }
    }
    //获取类字段信息
    static void getDeclaredFields() {
        try {
            Class clazz = Main.class;
            Field[] fieldArr = clazz.getDeclaredFields();
            for(Field f : fieldArr){
                System.out.println("getDeclaredFields=" + f);
            }
        } catch (Exception e) {
        }
    }
    // 获取类方法
    static void getDeclaredMethods() {
        try {
            Class clazz = Main.class;
            Method[] methodArr = clazz.getDeclaredMethods();
            for(Method m : methodArr){
                System.out.println("getDeclaredMethods=" + m);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取构造方法
    static void getDeclaredConstructors() {
        try {
            Constructor[] cArr= Main.class.getDeclaredConstructors();
            for(Constructor c : cArr){
                System.out.println("getDeclaredConstructors=" + c);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //根据参数获取字段信息
    static void getDeclaredField() {
        try {
            Class clazz = Main.class;
            Field field = clazz.getDeclaredField("userName");
            System.out.println("getDeclaredField=" + field);
        } catch (Exception e) {
        }
    }
    // 返回Method对象匹配指定名称和parameterTypes
    static void getDeclaredMethod() {
        try {
            Class clazz = Main.class;
            Class[] cArg = new Class[1];
            cArg[0] = Long.class;
            Method method = clazz.getDeclaredMethod("say", cArg);
            System.out.println("getDeclaredMethod=" + method.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 根据参数获取对应构造方法
    static void getDeclaredConstructor() {
        try {
            Class parameterTypes[] = {Integer.class,String.class};
            Constructor c = Main.class.getDeclaredConstructor(parameterTypes);
            System.out.println("getDeclaredConstructor=" + c);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 查找具有给定名称的资源,返回InputStream
    static void getResourceAsStream() {
        InputStream in = Main.class.getResourceAsStream("application.properties");
        byte[] buf = new byte[1024];
        int len;
        try {
            while ((len = in.read(buf)) != -1) {
                String s = new String(buf, 0,len,"GBK");
                System.out.println(s);
            }
            in.close();
        }catch (Exception E){
        }
    }
    // 查找具有给定名称的资源,返回URL
    static void getResource() {
        java.net.URL url = Main.class.getResource("application.properties");
        System.out.println("getResource = "+url);
    }
    // 返回类的 ProtectionDomain 对象
    static void getProtectionDomain() {
        ProtectionDomain protectionDomain = Main.class.getProtectionDomain();
        System.out.println("getProtectionDomain = "+protectionDomain);
    }
    // 该方法以布尔值的形式返回该类的指定断言状态
    static void desiredAssertionStatus() {
        boolean result  = Main.class.desiredAssertionStatus();
        System.out.println("desiredAssertionStatus = "+result);
    }
    // 判断是否枚举
    static void isEnum() {
        boolean result  = Main.class.isEnum();
        boolean result1  = EnumDemo.class.isEnum();
        System.out.println("isEnum = "+result +" isEnum="+result1);
    }
    // 获取枚举元素
    static void getEnumConstants() {
        EnumDemo[] enumDemoArr  = EnumDemo.class.getEnumConstants();
        for(EnumDemo e:enumDemoArr){
            System.out.println("getEnumConstants = "+e );
        }
    }
    //将对象强制转换为所表示的类或接口
    static void cast() {
        Class clazz = Main.class;
        try {
            Object obj =new Main(23,"张三");
            if(obj instanceof  Main){
                Main m = (Main) clazz.cast(obj);
                System.out.println("cast = "+m.toString() );
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 强制把Class对象转化成参数类的子类
    static void asSubclass() {
        Class son = Son.class;
        Class parent = Parent.class;
        try {
            Class p =  son.asSubclass(parent);
            System.out.println("asSubclass ="+p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取Class 类的父类注解
    static void getAnnotatedSuperclass() {
        try {
            Annotation[] anns = B.class.getAnnotatedSuperclass().getAnnotations();
            for (Annotation a : anns){
                System.out.println("getAnnotatedSuperclass = "+a.annotationType().getName());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    //返回一个AnnotatedType对象数组,表示使用类型来指定此Class对象表示的实体的超接口
    static void getAnnotatedInterfaces() {
        try {
            AnnotatedType[] anns = First.class.getAnnotatedInterfaces();
            for (AnnotatedType a : anns){
                System.out.println("getAnnotatedInterfaces = "+ a);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    public class a {
    }
    public class b {
    }
    private class c {
    }
}
class Out {
    public Object c;
    public Out() {
        class ClassA {
        }
        ;
        c = new ClassA();
    }
    public Object ClassAObject() {
        class ClassA {
        }
        return new ClassA();
    }
}
enum EnumDemo {
    PAY_WX(),
    PAY_ALI();
}
class Grandfather {
}
class Parent<T> extends Grandfather {
}
class Son extends Parent<Integer> {
}
interface DemoService<T> {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface First  { }
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface Second { }
class A { }
class B extends @First @Second A { }
class DemoServiceImpl implements DemoService<Integer> {
}
    二、访问字段
   
Class 类提供了以下几个方法获取字段:
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field[] getFields():获取所有public的field(包括父类)
- Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
示例
public class Main {
    public static void main(String[] args) throws Exception {
        Class stdClass = Student.class;
        // 获取public字段"score":
        System.out.println(stdClass.getField("score"));
        // 获取继承的public字段"name":
        System.out.println(stdClass.getField("name"));
        // 获取private字段"grade":
        System.out.println(stdClass.getDeclaredField("grade"));
    }
}
class Student extends Person {
    public int score;
    private int grade;
}
class Person {
    public String name;
}
控制台显示
public int Student.score
public java.lang.String Person.name
private int Student.grade一个 Field 对象包含了一个字段的所有信息:
getName() : 返回字段名称 。例如 “name”。
getType(): 返回字段类型,也是一个 Class 示例。 例如 String.class。
getModifiers():返回字段修饰符,它是一个 int值,不同 bit 表示不同含义。
例如 String类的value字段为例,它的定义是:
public final class String {
    private final byte[] value;
}用反射获取该字段的信息,代码如下:
import java.lang.reflect.Modifier;
public class Main {
    public static <Field> void main(String[] args) throws Exception {
        java.lang.reflect.Field f = String.class.getDeclaredField("value");//   private final char value[];
        f.getName(); // "value"
        f.getType(); // class [B 表示byte[]类型
        int m = f.getModifiers();
        Modifier.isFinal(m); // true
        Modifier.isPublic(m); // false
        Modifier.isProtected(m); // false
        Modifier.isPrivate(m); // true
        Modifier.isStatic(m); // false
        
    }
}
获取/设置字段值
import java.lang.reflect.Field;
public class Main {
    public static void main(String[] args) throws Exception {
        Person p = new Person("Xiao Ming");
        Class c = p.getClass();
        Field f = c.getDeclaredField("name");
        f.setAccessible(true);  //  别管这个字段是不是public,一律允许访问
        Object value = f.get(p);  // 获取值
        System.out.println(value); // "Xiao Ming"'
        f.set(p, "Xiao Zhang"); // 设置值
        System.out.println(p.getName()); // "Xiao Hong"
    }
}
class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)。例如,某个SecurityManager可能不允许对java和javax开头的package的类调用setAccessible(true),这样可以保证JVM核心库的安全。
Field 类扩展方法
| 方法 | 描述 | 
| boolean isEnumConstant() | 判断是否枚举常量 | 
| Class<?> getType() | 获取字段类型,不包含泛型类型 | 
| Type getGenericType() | 获取字段类型 | 
| String toGenericString() | 返回描述这个字段的字符串 | 
| Object get(Object obj) | 获取字段值 | 
| boolean getBoolean(Object obj) | 获取 boolean 类型字段值 | 
| byte getByte(Object obj) | 获取 byte 类型字段值 | 
| char getChar(Object obj) | 获取 char 类型字段值 | 
| short getShort(Object obj) | 获取 short 类型字段值 | 
| int getInt(Object obj) | 获取 int类型字段值 | 
| long getLong(Object obj) | 获取 long类型字段值 | 
| float getFloat(Object obj) | 获取float类型字段值 | 
| double getDouble(Object obj) | 获取 double类型字段值 | 
| void set(Object obj, Object value) | 设置字段值 | 
| void setBoolean(Object obj, boolean z) | 设置boolean 类型字段值 | 
| void setByte(Object obj, byte b) | 设置 byte 类型字段值 | 
| void setChar(Object obj, char c) | 设置char 类型字段值 | 
| void setShort(Object obj, short s) | 设置short 类型字段值 | 
| void setInt(Object obj, int i) | 设置int类型字段值 | 
| void setLong(Object obj, long l) | 设置long类型字段值 | 
| void setFloat(Object obj, float f) | 设置float类型字段值 | 
| void setDouble(Object obj, double d) | 设置double类型字段值 | 
| AnnotatedType getAnnotatedType() | 返回一个AnnotatedType对象,该对象包含类型等信息 | 
示例
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
public class Main {
    public static void main(String[] args) throws Exception {
        // 判断是否枚举常量
        isEnumConstant();
        // 获取字段类型,不包含泛型类型
        getType();
        // 获取字段类型
        getGenericType();
        // 返回描述这个字段的字符串
        toGenericString();
        // 获取/设置字段值
        get$set();
        // 获取/设置boolean 类型字段值
        getBoolean$setBoolean();
        // 获取/设置 byte 类型字段值
        getByte$setByte();
        // 获取/设置char 类型字段值
        getChar$setChar();
        // 获取/设置short 类型字段值
        getShort$setShort();
        // 获取/设置int类型字段值
        getInt$setInt();
        // 获取/设置long类型字段值
        getLong$setLong();
        // 获取/设置float类型字段值
        getFloat$setFloat();
        // 获取/设置double类型字段值
        getDouble$setDouble();
        //返回一个AnnotatedType对象,该对象包含类型等信息
        getAnnotatedType();
    }
    // 判断是否枚举常量
    static void isEnumConstant() {
        Class clazz = Pay.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("PAY");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        boolean isEnumConstant = field.isEnumConstant();
        System.out.println("isEnumConstant = " + isEnumConstant);
    }
    //  获取字段类型,不包含泛型类型
    static void getType() {
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("name");
            //field =  clazz.getDeclaredField("address"); // 获取不到
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        Class c = field.getType();
        System.out.println("getType = " + c);
    }
    static void getGenericType() {
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("address");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        Type c = field.getGenericType();
        System.out.println("getGenericType = " + c);
    }
    /**
     * *返回描述这个{@code字段}的字符串,包括
     * 其泛型类型。的访问修饰符
     * 字段(如果有的话),然后是泛型字段类型,然后是
     * 一个空格,后跟类的全限定名
     * 声明字段,后面跟着句号,后面跟着名称
     */
    static void toGenericString() {
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("address");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        String str = field.toGenericString();
        System.out.println("toGenericString = " + str);
    }
    // 获取/设置 字段值
    static void get$set() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("name");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            //设置字段的值
            field.set(p, "kevin");
            // 获取字段的值
            Object obj = field.get(p);
            System.out.println("get$set = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取/设置boolean 类型字段值
    static void getBoolean$setBoolean() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("deleteFlag");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段的值
            field.setBoolean(p, Boolean.TRUE);
            // 获取字段的值
            boolean obj = field.getBoolean(p);
            System.out.println("getBoolean$setBoolean = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取/设置 byte 类型字段值
    static void getByte$setByte() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("byteField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段的值
            field.setByte(p, Byte.parseByte("3"));
            // 获取字段的值
            byte obj = field.getByte(p);
            System.out.println("getByte$setByte = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取/设置char 类型字段值
    static void getChar$setChar() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("charField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段的值
            field.setChar(p, '2');
            // 获取字段的值
            char obj = field.getChar(p);
            System.out.println("getChar$setChar = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取/设置short 类型字段值
    static void getShort$setShort() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("shortField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段的值
            field.setShort(p, Short.parseShort("2"));
            // 获取字段的值
            short obj = field.getShort(p);
            System.out.println("getShort$setShort = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取/设置int 类型字段值
    static void getInt$setInt() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("intField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段的值
            field.setInt(p, 2);
            // 获取字段的值
            int obj = field.getInt(p);
            System.out.println("getInt$setInt = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取/设置 long 类型字段值
    static void getLong$setLong() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("longField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段值
            field.setLong(p, 4L);
            // 获取字段值
            long obj = field.getLong(p);
            System.out.println("getLong$setLong = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取/设置 float 类型字段值
    static void getFloat$setFloat() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("floatField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段的值
            field.setFloat(p, 3.0F);
            // 获取字段的值
            float obj = field.getFloat(p);
            System.out.println("getFloat$setFloat = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取/设置 double 类型字段值
    static void getDouble$setDouble() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("doubleField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 设置字段的值
            field.setDouble(p, 6.01);
            // 获取字段的值
            double obj = field.getDouble(p);
            System.out.println("getDouble$setDouble = " + obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 返回一个AnnotatedType对象,该对象包含类型等信息
    static void getAnnotatedType() {
        Person p = new Person();
        Class clazz = Person.class;
        Field field = null;
        try {
            field = clazz.getDeclaredField("doubleField");
            field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
            // 获取字段的值
            AnnotatedType obj = field.getAnnotatedType();
            System.out.println("getAnnotatedType = " + obj.getType());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class Person<T> {
    private Pay pay;
    private String name;
    private T address;
    private boolean deleteFlag;
    private byte byteField;
    private char charField;
    private short shortField;
    private int intField;
    private long longField;
    private float floatField;
    private double doubleField;
    public double getDoubleField() {
        return doubleField;
    }
    public void setDoubleField(double doubleField) {
        this.doubleField = doubleField;
    }
    public float getFloatField() {
        return floatField;
    }
    public void setFloatField(float floatField) {
        this.floatField = floatField;
    }
    public long getLongField() {
        return longField;
    }
    public void setLongField(long longField) {
        this.longField = longField;
    }
    public int getIntField() {
        return intField;
    }
    public void setIntField(int intField) {
        this.intField = intField;
    }
    public short getShortField() {
        return shortField;
    }
    public void setShortField(short shortField) {
        this.shortField = shortField;
    }
    public char getCharField() {
        return charField;
    }
    public void setCharField(char charField) {
        this.charField = charField;
    }
    public Person() {
    }
    public Person(String name) {
        this.name = name;
    }
    public Person(boolean deleteFlag) {
        this.deleteFlag = deleteFlag;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public byte getByteField() {
        return byteField;
    }
    public void setByteField(byte byteField) {
        this.byteField = byteField;
    }
    public Pay getPay() {
        return pay;
    }
    public void setPay(Pay pay) {
        this.pay = pay;
    }
    public T getAddress() {
        return address;
    }
    public void setAddress(T address) {
        this.address = address;
    }
    public boolean isDeleteFlag() {
        return deleteFlag;
    }
    public void setDeleteFlag(boolean deleteFlag) {
        this.deleteFlag = deleteFlag;
    }
}
enum Pay {
    PAY
}
    三、调用方法
   
Class类提供了以下几个方法来获取Method
- Method getMethod(name, Class…):获取某个public的Method(包括父类)
- Method getDeclaredMethod(name, Class…):获取当前类的某个Method(不包括父类)
- Method[] getMethods():获取所有public的Method(包括父类)
- Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
示例
public class Main {
    public static void main(String[] args) throws Exception {
        Class stdClass = Student.class;
        // 获取public方法getScore,参数为String:
        System.out.println(stdClass.getMethod("getScore", String.class));
        // 获取继承的public方法getName,无参数:
        System.out.println(stdClass.getMethod("getName"));
        // 获取private方法getGrade,参数为int:
        System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
    }
}
class Student extends Person {
    public int getScore(String type) {
        return 99;
    }
    private int getGrade(int year) {
        return 1;
    }
}
class Person {
    public String getName() {
        return "Person";
    }
}
控制台显示
public int Student.getScore(java.lang.String)
public java.lang.String Person.getName()
private int Student.getGrade(int)一个 Method 对象包含一个方法的所有信息:
- getName() 返回方法名称
- getReturnType() 返回方法返回值类型
- getParamMeterTypers() 返回方法的参数类型,是一个 Class 数组
- getModifiers() 返回方法修饰符,它是一个 int,不同int表示不同含义
    3.1、 普通方法调用
   
获取到一个Method对象时,就可以对它进行调用。代码为例:
String s = "Hello world";
String r = s.substring(6); // "world"反射来调用substring方法,需要以下代码:
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws Exception {
        // String对象:
        String s = "Hello world";
        // 获取String substring(int)方法,参数为int:
        Method m = String.class.getMethod("substring", int.class);
        // 在s对象上调用该方法并获取结果:
        String r = (String) m.invoke(s, 6);
        // 打印调用结果:
        System.out.println(r);
    }
}
Method实例调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错。
    3.2、 静态方法调用
   
获取到的Method表示一个静态方法,调用静态方法时,由于无需指定实例对象,所以invoke方法传入的第一个参数永远为null。以Integer.parseInt(String)为例:
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws Exception {
        // 获取Integer.parseInt(String)方法,参数为String:
            Method m = Integer.class.getMethod("parseInt", String.class);
        // 调用该静态方法并获取结果:
        Integer n = (Integer) m.invoke(null, "12345");
        // 打印调用结果:
        System.out.println(n);// 12345
    }
}
    3.3、 非 public 方法调用
   
对于非public方法,虽然可以通过Class.getDeclaredMethod()获取该方法实例,但直接对其调用将得到一个IllegalAccessException。为了调用非public方法,我们通过Method.setAccessible(true)允许其调用:
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        Method m = p.getClass().getDeclaredMethod("setName", String.class);
        m.setAccessible(true);
        m.invoke(p, "Bob");
        System.out.println(p.name); // Bob
    }
}
class Person {
    String name;
    private void setName(String name) {
        this.name = name;
    }
}
需要注意的话,setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)。例如,某个SecurityManager可能不允许对java和javax开头的package的类调用setAccessible(true),这样可以保证JVM核心库的安全。
    3.4、 多态方法调用
   
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws Exception {
        // 获取Person的hello方法:
        Method h = Person.class.getMethod("hello");
        // 对Student实例调用hello方法:
        h.invoke(new Student());
    }
}
class Person {
    public void hello() {
        System.out.println("Person:hello");
    }
}
class Student extends Person {
    public void hello() {
        System.out.println("Student:hello");
    }
}
控制台显示
Student:hello使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方法(如果存在)。上述的反射代码:
Method m = Person.class.getMethod("hello");
m.invoke(new Student());相当于:
Person p = new Student();
p.hello();Method扩展方法
| 方法 | 描述 | 
| Class<?> getReturnType() | 获取方法返回类型 | 
| Type getGenericReturnType() | 获取方法返回类型,返回类型是参数化类型 | 
| Object invoke(Object obj, Object… args) | 调用该方法并获取结果 | 
| boolean isBridge() | 判断是否桥接方法 | 
| boolean isDefault() | 判断是否isDefault方法 | 
| Object getDefaultValue() | 获取默认值 | 
示例
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Comparator;
public class Main {
    public static void main(String[] args) throws Exception {
        // 获取方法返回类型
        getReturnType();
        // 获取方法返回类型,返回类型是参数化类型
        getGenericReturnType();
        //调用该方法并获取结果
        invoke();
        // 判断是否桥接方法
        isBridge();
        // 判断是否isDefault方法
        isDefault();
        // 获取默认值
        getDefaultValue();
    }
    // 获取方法返回类型
    static void getReturnType() {
        Person p = new Person();
        Method m = null;
        try {
            m = p.getClass().getDeclaredMethod("getName");
            m.setAccessible(true);
            Class clazz = m.getReturnType();
            System.out.println("getReturnType= " + clazz);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
    // 获取方法返回类型,返回类型是参数化类型
    static void getGenericReturnType() {
        Person p = new Person();
        Method m = null;
        try {
            m = p.getClass().getDeclaredMethod("say");
            m.setAccessible(true);
            Type clazz = m.getGenericReturnType();
            System.out.println("getGenericReturnType= " + clazz);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
    //调用该方法并获取结果:
    static void invoke() {
        Student p = new Student();
        Method m = null;
        try {
            m = p.getClass().getDeclaredMethod("setName", String.class);
            m.setAccessible(true);
            m.invoke(p, "Kevin");
            System.out.println("invoke= " + p.name);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 判断是桥接方法
    static void isBridge() {
        Class<B> classB = B.class;
        Method[] methods = classB.getDeclaredMethods();
        System.out.println("方法总数量:" + methods.length);
        for (Method method : methods) {
            System.out.println(method.getReturnType().getSimpleName() + " "
                    + method.getName() +
                    "(" + method.getParameters()[0].getType().getSimpleName() + ")"
                    + " is " + (method.isBridge() ? "bridge" : "common") + " method"
            );
        }
    }
    // 判断是否isDefault方法
    static void isDefault() {
        Class c = Comparator.class;
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            // check whether method is Default Method or not
            if (method.isDefault()) {
                // print Method name
                System.out.println("isDefault = " + method.getName() + "  " + method.isDefault());
            }
        }
    }
    // 获取默认值
    static void getDefaultValue() {
        try {
            Method method = AnnotationDemo.class.getDeclaredMethod("fauvMovie");
            System.out.println("getDefaultValue =" + method.getDefaultValue());
        } catch (Exception e) {
        }
    }
}
@interface AnnotationDemo {
    public String fauvMovie() default "Inception";
    public double fauvMovieRating() default 9.6;
    public int fauvMovieReleaseYear();
}
class Person<T> {
    String name;
    private void setName(String name) {
        this.name = name;
    }
    public T say() {
        return null;
    }
    public String getName() {
        return name;
    }
}
class Student {
    String name;
    private void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
// 声明一个泛型接口
interface A<T> {
    void test(T t);
}
//泛型本身是语言级别的,经过编译后,泛型就会被擦除,所以接口 A 在编译后,test 方法的入参会被转换为 Object
//编译器编译
//public interface A {
//    void test(Object t);
//}
// 使用 String 类型实现一个具体的实现类
class B implements A<String> {
    public void test(String s) {
        System.out.println(s);
    }
}
//实现类 B 中的实现方法是 void test(String s),其实根本就没有实现 void test(Object t) 方法。但是这个代码是正确的,可以正常运行,因为 JVM 在编译过程中对我们的实现类做了一点手脚
//编译器编译
//public class B implements A {
//    public void test(String s) {
//        System.out.println(s);
//    }
//    public void test(Object s) {
//        this.test((String) s);
//    }
//}
    四、调用构造方法
   
通过创建对象实例:
Person p = new Person();调用Class提供的newInstance()方法
Person p = Person.class.newInstance();调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。
为了调用任意的构造方法,Java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。Constructor对象和Method非常类似,不同之处仅在于它是一个构造方法,并且,调用结果总是返回实例:
import java.lang.reflect.Constructor;
public class Main {
    public static void main(String[] args) throws Exception {
        // 获取构造方法Integer(int):
        Constructor cons1 = Integer.class.getConstructor(int.class);
        // 调用构造方法:
        Integer n1 = (Integer) cons1.newInstance(123);
        System.out.println(n1);
        // 获取构造方法Integer(String)
        Constructor cons2 = Integer.class.getConstructor(String.class);
        Integer n2 = (Integer) cons2.newInstance("456");
        System.out.println(n2);
    }
}
Class实例获取Constructor的方法如下
- getConstructor(Class…):获取某个public的Constructor
- getDeclaredConstructor(Class…):获取某个Constructor
- getConstructors():获取所有public的Constructor
- getDeclaredConstructors():获取所有Constructor
注意Constructor总是当前类定义的构造方法,和父类无关,因此不存在多态的问题。
调用非public的Constructor时,必须首先通过setAccessible(true)设置允许访问,setAccessible(true)可能会失败。
 
