反射知识点学习

文章目录

    • 1. Java 反射机制原理示意图
      • 1.1 反射相关的主要类
      • 1.2 反射的优点和缺点
      • 1.3 反射调用优化-关闭访问检查
    • 2. Class 类
      • 2.1 基本介绍
      • 2.2 Class类的常用方法
      • 2.3 获取 Class 类对象
    • 3. 哪些类型有 Class 对象
    • 4. 类加载
      • 4.1 基本说明
      • 4.2 类加载时机
      • 4.3 类加载过程图
      • 4.4 类加载各阶段完成任务
      • 4.5 加载阶段
      • 4.6 连接阶段-验证
      • 4.7 连接阶段-准备
      • 5. 连接阶段-解析
      • 6. Initialization(初始化)
    • 5. 通过反射获取类的结构信息
      • 5.1 第一组:java.lang.Class 类
      • 5.2 第二组:java.lang.reflect.Field 类
      • 5.3 第三组: java.lang.reflect.Method 类
      • 5.4 第四组:java.lang.reflect.Constructor 类
    • 6. 通过反射创建对象
    • 7. 通过反射访问类中的成员
      • 7.1 访问属性 ReflecAccessProperty.java
      • 7.2 访问方法 ReflecAccessMethod.java
    • 8. 本章作业

反射知识点学习_第1张图片

1. Java 反射机制原理示意图

反射知识点学习_第2张图片

  • Java反射机制可以完成

反射知识点学习_第3张图片

1.1 反射相关的主要类

反射知识点学习_第4张图片

package com.xjz.reflection;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author xjz_2002
 * @version 1.0
 */
public class Reflection01 {
    public static void main(String[] args) throws Exception {

        //1. 使用 Properties 类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString(); // "com.xjz.Cat"
        String methodName = properties.get("method").toString(); //"hi"

        //2. 使用反射机制解决
        //(1) 加载类,返回 Class 类型的对象 cls
        Class cls = Class.forName(classfullpath);
        //(2) 通过 cls 得到你加载的类 com.xjz.Cat 的对象实例
        Object o = cls.newInstance();
        System.out.println("o 的运行类型=" + o.getClass());//运行类型
        //(3) 通过 cls 得到你加载的类 com.xjz.Cat 的 methodName “hi” 的方法对象
        //    即:在反射中,可以把方法视为对象(万物皆对象)
        Method method = cls.getMethod(methodName);
        //(4) 通过 method 调用方法:即通过方法对象类实现调用方法
        System.out.println("=======================");
        method.invoke(o); //传统对象 对象.方法(),反射机制 方法.invoke(对象)
        //java.lang.reflect.Field: 代表类的成员变量, Field 对象表示某个类的成员变量
        //得到 name 字段
        //getField 不能得到私有的属性
        Field ageField = cls.getField("age");
        System.out.println(ageField.get(o));//传统写法 对象.成员变量 , 反射:成员变量对象.get(对象)

        //java.lang.reflect.Constructor: 代表类的构造方法, Constructor 对象表示构造器
        Constructor constructor = cls.getConstructor();//()中可以指定构造器参数类型,返回无参构造器
        System.out.println(constructor);//public com.xjz.Cat()

        Constructor constructor2 = cls.getConstructor(String.class);//这里传入的 String.class 就是 String类的 Class对象
        System.out.println(constructor2); //public com.xjz.Cat(java.lang.String)

    }
}

1.2 反射的优点和缺点

反射知识点学习_第5张图片

1.3 反射调用优化-关闭访问检查

image-20230928171454966

反射知识点学习_第6张图片

package com.xjz.reflection;

import com.xjz.Cat;

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

/**
 * @author xjz_2002
 * @version 1.0
 * 测试反射调用的性能,和优化方案
 */
public class Reflection02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

//        Field
//        Method
//        Constructor
        //上面三个类都继承了 AccessibleObject类
        m1(); //传统  0ms
        m2(); //反射  1750ms
        m3(); //反射优化    1268ms


    }

    //传统方法来调用 hi
    public static void m1() {
        Cat cat = new Cat();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            cat.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("m1() 耗时=" + (end - start));
    }

    //反射机制调用方法 hi
    public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.xjz.Cat");
        Object o = cls.newInstance(); //实例化反射对象
        Method hi = cls.getMethod("hi");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            hi.invoke(o);//反之调用方法
        }
        long end = System.currentTimeMillis();
        System.out.println("m2() 耗时=" + (end - start));
    }

    //反射调用优化 + 关闭访问检查
    public static void m3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.xjz.Cat");
        Object o = cls.newInstance(); //实例化反射对象
        Method hi = cls.getMethod("hi");
        hi.setAccessible(true);//在反射调用方法时,取消访问检查,提高性能
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            hi.invoke(o);//反之调用方法
        }
        long end = System.currentTimeMillis();
        System.out.println("m3() 耗时=" + (end - start));
    }
}

2. Class 类

2.1 基本介绍

反射知识点学习_第7张图片

反射知识点学习_第8张图片

package com.xjz.reflection.class_;

import com.xjz.Cat;

/**
 * @author xjz_2002
 * @version 1.0
 * 对 Class 类特点的梳理
 */
public class Class01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //看看 Class 类图
        //1. Class 也是类,因此也继承 Object 类
//        Class
        //2. Class类对象不是 new 出来的,而是系统创建的
        //(1) 传统 new 对象
        /* ClassLoader 类
            public Class loadClass(String name) throws ClassNotFoundException {
                return loadClass(name, false);
            }
         */
        //Cat cat = new Cat();
        //(2) 反射方式,刚才没有 debug 到 ClassLoader 类的loadClass,
        // 原因是 没有注销Cat cat = new Cat(); 即: 类只加载一次
        /*
            ClassLoader 类, 仍然是通过 ClassLoader 类加载 Cat 类的 Class 对象
            public Class loadClass(String name) throws ClassNotFoundException {
                return loadClass(name, false);
            }
            */
        Class<?> cls1 = Class.forName("com.xjz.Cat");

        //3. 对于某个类的 Class类对象,在内存中只有一份,因为类只加载一次
        Class<?> cls2 = Class.forName("com.xjz.Cat");
        System.out.println(cls1.hashCode());//356573597
        System.out.println(cls2.hashCode());//356573597
        Class<?> cls3 = Class.forName("com.xjz.Dog");
        System.out.println(cls3.hashCode());//1735600054
    }
}

2.2 Class类的常用方法

反射知识点学习_第9张图片

package com.xjz.reflection.class_;

import com.xjz.Car;

import java.lang.reflect.Field;

/**
 * @author xjz_2002
 * @version 1.0
 * 演示 Class 类的常用方法
 */
public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {

        String classAllPath = "com.xjz.Car";
        //1. 获取到 Car 类对应的 Class 对象
        // 表示不确定的 Java 类型
        Class cls = Class.forName(classAllPath);
        //2. 输出 cls
        System.out.println(cls);//显示 cls 对象,是哪个类的 Class 对象 即:class com.xjz.Car
        //3. 得到报名
        System.out.println(cls.getPackage().getName());//包名 com.xjz
        //4. 得到全类名
        System.out.println(cls.getName());//com.xjz.Car
        //5. 通过 cls 创建对象实例
        Car car = (Car) cls.newInstance();
        System.out.println(car); //car.toString()
        //6. 通过反射获取属性 brand
        Field brand = cls.getField("brand");
        System.out.println(brand.get(car));
        //7. 通过反射给属性赋值
        brand.set(car,"奔驰");
        System.out.println(brand.get(car));//奔驰
        //8. 我希望大家可以得到所有的属性(字段)
        System.out.println("======所有的属性字段======");
        Field[] fields = cls.getFields();
        for (Field f : fields) {
            System.out.println(f.getName()); //名称
        }

    }
}

2.3 获取 Class 类对象

反射知识点学习_第10张图片

反射知识点学习_第11张图片

反射知识点学习_第12张图片

package com.xjz.reflection.class_;

import com.xjz.Car;

/**
 * @author xjz_2002
 * @version 1.0
 * 演示得到 Class 对象的各种方式(6)
 */
public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {

        //1. Class.forName
        String classAllPath = "com.xjz.Car";//通过读取配置文件获取
        Class<?> cls1 = Class.forName(classAllPath);
        System.out.println(cls1);

        //2. 类名.class,应用场景:用于参数传递
        Class cls2 = Car.class;
        System.out.println(cls2);

        //3. 对象.getClass(),应用场景:有对象实例
        Car car = new Car();
        Class cls3 = car.getClass();
        System.out.println(cls3);

        //4. 通过类加载器【4种】来获取到类的 Class 对象
        //(1) 先得到类加载器 car
        ClassLoader classLoader = car.getClass().getClassLoader();
        //(2) 通过类加载器得到 Class 对象
        Class cls4 = classLoader.loadClass(classAllPath);
        System.out.println(cls4);

        //cls1 , cls2 , cls3 , cls4 其实是同一个对象
        System.out.println(cls1.hashCode());
        System.out.println(cls2.hashCode());
        System.out.println(cls3.hashCode());
        System.out.println(cls4.hashCode());

        //5. 基本数据(int,char,boolean,float,double,byte,short,long) 按如下方式得到 Class 类对象
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        Class<Boolean> booleanClass = boolean.class;
        System.out.println(integerClass);//int

        //6. 基本数据类型对应的包装类,可以通过 .TYPE 得到 Class 类对象
        Class<Integer> type1 = Integer.TYPE;
        Class<Character> type2 = Character.TYPE;//其它包装类 BOOLEAN, DOUBLE, LONG,BYTE 等等
        System.out.println(type1);

        System.out.println(integerClass.hashCode());//1735600054
        System.out.println(type1.hashCode());//1735600054

    }
}

3. 哪些类型有 Class 对象

反射知识点学习_第13张图片

package com.xjz.reflection.class_;

import com.sun.org.apache.bcel.internal.classfile.Deprecated;

import java.io.Serializable;

/**
 * @author xjz_2002
 * @version 1.0
 * 演示哪些类型有 Class 对象
 */
public class AllTypeClass {
    public static void main(String[] args) {

        Class<String> cls1 = String.class;//外部类
        Class<Serializable> cls2 = Serializable.class;//接口
        Class<Integer[]> cls3 = Integer[].class;//数组
        Class<float[][]> cls4 = float[][].class;//二维数组
        Class<Deprecated> cls5 = Deprecated.class;//注解
        //枚举
        Class<Thread.State> cls6 = Thread.State.class;
        Class<Long> cls7 = long.class;//基本数据类型
        Class<Void> cls8 = void.class;//void 数据类型
        Class<Class> cls9 = Class.class;//

        System.out.println(cls1);
        System.out.println(cls2);
        System.out.println(cls3);
        System.out.println(cls4);
        System.out.println(cls5);
        System.out.println(cls6);
        System.out.println(cls7);
        System.out.println(cls8);
        System.out.println(cls9);
    }
}

4. 类加载

4.1 基本说明

反射知识点学习_第14张图片

4.2 类加载时机

反射知识点学习_第15张图片

4.3 类加载过程图

反射知识点学习_第16张图片

4.4 类加载各阶段完成任务

反射知识点学习_第17张图片

4.5 加载阶段

反射知识点学习_第18张图片

4.6 连接阶段-验证

反射知识点学习_第19张图片

4.7 连接阶段-准备

反射知识点学习_第20张图片

package com.xjz.reflection.classLoad_;

/**
 * @author xjz_2002
 * @version 1.0
 * 我们说明一个类加载的链接阶段-准备
 */
public class ClassLoad02 {
    public static void main(String[] args) {
        
    }
}
class A {
    //属性-成员变量-字段
    //分析类加载的链接阶段-准备 属性是如何处理
    //1. n1 是实例属性,不是静态变量,因此在准备阶段,是不会分配内存
    //2. n2 是静态变量,分配内存 n2 是默认初始化 0,而不是 20
    //3. n3 是 static final 是常量,他和静态变量不一样,因为一旦赋值就不变 n3 = 30
    public int n1 = 10;
    public static int n2 = 20;
    public static final int n3 = 30;
}

5. 连接阶段-解析

反射知识点学习_第21张图片

6. Initialization(初始化)

反射知识点学习_第22张图片

package com.xjz.reflection.classLoad_;

/**
 * @author xjz_2002
 * @version 1.0
 * 演示类加载-初始化阶段
 */
public class ClassLoad03 {
    public static void main(String[] args) {

        //代码分析
        //1. 加载 B 类,并生成 B 的 class 对象
        //2. 链接 num = 0
        //3. 初始化阶段
        // 依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并
        /*
            clinit() {
                System.out.println("B 静态代码块被执行");
                //num = 300;
                num = 100;
            }
            合并: num = 100
        */

        //new B();//类加载
        //System.out.println(B.num);//100, 如果直接使用类的静态属性,也会导致类的加载
        //看看加载类的时候,是有同步机制控制
        /*
        protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException
        {
            //正因为有这个机制,才能保证某个类在内存中, 只有一份 Class 对象
            synchronized (getClassLoadingLock(name)) {
            //.... }
        }
        */
        B b = new B();
    }
}
class B {
    static {
        System.out.println("B 静态代码块执行");
        num = 300;
    }

    static int num = 100;

    public B() {//构造器
        System.out.println("B() 构造器执行");
    }
}

5. 通过反射获取类的结构信息

5.1 第一组:java.lang.Class 类

反射知识点学习_第23张图片

5.2 第二组:java.lang.reflect.Field 类

反射知识点学习_第24张图片

5.3 第三组: java.lang.reflect.Method 类

反射知识点学习_第25张图片

5.4 第四组:java.lang.reflect.Constructor 类

反射知识点学习_第26张图片

package com.xjz.reflection;

import org.junit.jupiter.api.Test;

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

/**
 * @author xjz_2002
 * @version 1.0
 * 演示如何通过反射获取类的结构信息
 */
public class ReflectionUtils {
    public static void main(String[] args) {

    }

    @Test
    public void api_02() throws ClassNotFoundException {

        //得到 Class对象
        Class<?> personCls = Class.forName("com.xjz.reflection.Person");
        // getDeclaredFields: 获取本类中所有的属性
        //规定 说明: 默认修饰符 是 0 , public 是 1 ,private 是 2 ,protected 是 4 , static 是 8 ,final 是 16
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中所有的属性=" + declaredField.getName()
                            + " 该属性的修饰符值=" + declaredField.getModifiers()
                            + " 该属性的类型=" + declaredField.getType());
        }

        //getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类中所有方法=" + declaredMethod.getName()
                            + " 该方法的访问修饰符值=" + declaredMethod.getModifiers()
                            + " 该方法返回类型=" + declaredMethod.getReturnType());

            //输出当前这个方法的形参数组情况
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("该方法的形参类型=" + parameterType);
            }
        }

        //getDeclaredConstructors:获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("==============================================");
            System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里我们只输出名字

            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("该构造器的形参类型=" + parameterType);
            }
        }


    }

    //第一组方法 API
    @Test
    public void api_01() throws ClassNotFoundException {

        //得到 Class对象
        Class<?> personCls = Class.forName("com.xjz.reflection.Person");
        // getName 获取全类名
        System.out.println(personCls.getName());//com.xjz.reflection.Person
        // getSimpleName:获取简单类名
        System.out.println(personCls.getSimpleName());//Person
        // getFields: 获取所有 public 修饰的属性,包含本类以及父类的
        Field[] fields = personCls.getFields();
        for (Field field : fields) { //增强for
            System.out.println("本类以及父类的属性=" + field.getName()); //name , hobby
        }
        // getDeclaredFields: 获取本类中所有的属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中所有的属性=" + declaredField.getName());
        }
        // getMethods: 获取所有 public 修饰的方法,包含本类以及父类的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("本类以及父类的方法=" + method.getName());
        }
        //getDeclaredMethods:获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类中所有方法=" + declaredMethod.getName());
        }
        //getConstructors: 获取所有 public 修饰的构造器,包含本类
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("本类的构造器=" + constructor.getName());
        }
        //getDeclaredConstructors:获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里我们只输出名字
        }
        //getPackage:以 Package 形式返回 包信息
        System.out.println(personCls.getPackage());//com.hspedu.reflection
        //getSuperClass:以 Class 形式返回父类信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println("父类的 class对象=" + superclass);
        //getInterfaces:以 Class[]形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("接口信息=" + anInterface);
        }
        //getAnnotations:以 Annotation[] 形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解信息=" + annotation);//注解
        }

    }


}
class A {
    public String hobby;

    public void hi(){

    }

    public A(){}

    public A(String name){

    }
}
interface IA{
}
interface IB{

}

@Deprecated
class Person extends A implements IA,IB{
    //属性
    public String name;
    protected static int age;
    String job;
    private double sal;

    //构造器
    public Person(){

    }
    public Person(String name){

    }

    //私有的
    public Person(String name,int age){

    }

    //方法
    public void m1(String name,int age,double sal){

    }
    protected String m2(){
        return null;
    }
    void m3(){

    }
    private void  m4(){

    }
}

6. 通过反射创建对象

反射知识点学习_第27张图片

  • 测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
  • 测试 2:通过调用某个特定构造器的方式,实现创建某类的对象
package com.xjz.reflection;

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

/**
 * @author xjz_2002
 * @version 1.0
 * 演示通过反射机制创建实例
 */
public class ReflecCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //1. 先获取 User 类的 Class 对象
        Class<?> userClass = Class.forName("com.xjz.reflection.User");
        //2. 通过 public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);
        //3. 通过 public 的有参构造器创建实例
        /*
            constructor 对象就是
            public User(String name) {//public 的有参构造器
                this.name = name;
            }
         */
        //3.1 先得到对应构造器
        Constructor<?> constructor = userClass.getConstructor(String.class);
        //3.2 创建实例,并传入实参
        Object xjz = constructor.newInstance("xjz");
        System.out.println("xjz=" + xjz);
        //4. 通过非 public 的有参构造器创建实例
        //4.1 得到 private 的构造器对象
        Constructor<?> constructor2 = userClass.getDeclaredConstructor(int.class, String.class);
        //4.2 创建实例
        //暴破【暴力破解】,使用反射可以访问 private 构造器/方法/属性,反射面前,都是纸老虎
        constructor2.setAccessible(true);
        Object user2 = constructor2.newInstance(100, "张杰");
        System.out.println("user2=" + user2);


    }
}

class User { // User 类
    private int age = 10;
    private String name = "xjz_2002";

    public User() { //无参 public
    }

    public User(String name) { //public 的有参构造器
        this.name = name;
    }

    private User(int age, String name) { //private 有参构造器
        this.age = age;
        this.name = name;
    }

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

7. 通过反射访问类中的成员

7.1 访问属性 ReflecAccessProperty.java

反射知识点学习_第28张图片

package com.xjz.reflection;

import java.lang.reflect.Field;

/**
 * @author xjz_2002
 * @version 1.0
 * 演示反射操作属性
 */
public class ReflecAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {

        //1. 得到 Student 类对应的 Class 对象
        Class<?> stuClass = Class.forName("com.xjz.reflection.Student");
        //2. 创建对象
        Object o = stuClass.newInstance();// o 的运行类型是 Student
        System.out.println(o.getClass());//Student
        //3. 使用反射得到 age 属性对象
        Field age = stuClass.getField("age");
        age.set(o,21);//通过反射来操作属性
        System.out.println(o);
        System.out.println(age.get(o));//返回 age属性的值

        //4. 使用反射操作 name 属性
        Field name = stuClass.getDeclaredField("name");
        //对 name 进行暴破,可以操作 private 属性
        name.setAccessible(true);
//        name.set(o,"老徐");
        name.set(null,"老徐"); //因为 name 是 static 属性,因此 o 也可以写出 null
        System.out.println(o);
        System.out.println(name.get(o));//获取属性值
        System.out.println(name.get(null));//获取属性值,要求 name 是 static


    }
}

class Student { //类
    public int age;
    private static String name;

    public Student() { //构造器
    }

    @Override
    public String toString() {
        return "Student[age=" + age + ",name=" + name + ']';
    }
}

7.2 访问方法 ReflecAccessMethod.java

反射知识点学习_第29张图片

package com.xjz.reflection;

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

/**
 * @author xjz_2002
 * @version 1.0
 * 演示通过反射调用方法
 */
public class ReflecAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //1. 得到 Boos 类对应的 Class 对象
        Class<?> bossCls = Class.forName("com.xjz.reflection.Boss");
        //2. 创建对象
        Object o = bossCls.newInstance();
        //3. 调用 public 的 hi 方法
        //Method hi = bossCls.getMethod("hi", String.class);
        //3.1 得到 hi 方法对象
        Method hi = bossCls.getDeclaredMethod("hi", String.class);
        //3.2 调用
        hi.invoke(o,"张国荣");

        //4. 调用 private static 方法
        //4.1 得到 say 方法对象
        Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        //4.2 因为 say 方法是 private,所有需要暴破,原理和前面的构造器和属性一样
        say.setAccessible(true);
        System.out.println(say.invoke(o,21,"xjz",'男'));
        //4.3 因为 say 方法是 static的,还可以这样调用,可以传入 null
        System.out.println(say.invoke(null,22,"tom",'女'));

        //5. 在反射中,如果方法有返回值,统一返回 Object,但是他运行类型和方法定义的返回类型一致
        Object reVal = say.invoke(null, 300, "王五", '男');
        System.out.println("reVal 的运行类型=" + reVal.getClass());//String

        //再演示一个返回的案例
        Method m1 = bossCls.getDeclaredMethod("m1");
        Object reVal2 = m1.invoke(o);
        System.out.println("reVal2 =运行类型=" + reVal2.getClass()); //Monster


    }
}

class Monster {
}

class Boss {//类
    public int age;
    private static String name;

    public Boss() {//构造器
    }

    public Monster m1() {
        return new Monster();
    }

    private static String say(int n, String s, char c) {//静态方法
        return n + " " + s + " " + c;
    }

    public void hi(String s) {//普通 public 方法
        System.out.println("hi " + s);
    }
}

8. 本章作业

反射知识点学习_第30张图片

package com.xjz.homework;

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

/**
 * @author xjz_2002
 * @version 1.0
 */
public class Homework01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //1. 得到 PrivateTest类对应的 Class对象
        Class<PrivateTest> privateTestClass = PrivateTest.class;
        //2. 创建对象实例
        PrivateTest privateTestObj = privateTestClass.newInstance();
        //3. 得到 name 属性对象
        Field name = privateTestClass.getDeclaredField("name");
        //4. 暴破name
        name.setAccessible(true);
        name.set(privateTestObj,"xjz");
        //5. 得到getName方法对象
        Method getName = privateTestClass.getMethod("getName");
        //6. 因为getName() 是public,所有直接嗲用
        Object invoke = getName.invoke(privateTestObj);
        System.out.println("name属性值=" + invoke);
    }
}

class PrivateTest {
    private String name = "hellokitty";
    //默认无参构造器
    public String getName(){
        return name;
    }
}

反射知识点学习_第31张图片

package com.xjz.homework;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author xjz_2002
 * @version 1.0
 */
public class Homework02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //1. Class类的forName方法得到File类的 class对象
        Class<?> fileClass = Class.forName("java.io.File");
        //2. 得到所有的构造器
        Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
        //遍历输出
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("File的类所有构造器=" + declaredConstructor);
        }
        //3. 指定得到 public java.io.File(java.lang.String)
        Constructor<?> constructor = fileClass.getConstructor(String.class);
        String fileAllPath = "d:\\mynew.txt";
        Object file = constructor.newInstance(fileAllPath); //创建File对象

        //4. 得到createNewFile 方法对象
        Method createNewFile = fileClass.getMethod("createNewFile");
        createNewFile.invoke(file);//创建文件,调用的是 createNewFile
        //file 的运行类型就是File
        System.out.println(file.getClass());//class java.io.File
        System.out.println("创建文件成功" + fileAllPath);

    }
}

你可能感兴趣的:(后端开发基础知识点,java,反射)