反射知识点学习

news/2024/5/19 5:19:47 标签: java, 反射

文章目录

    • 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. 本章作业

image-20230928163222663

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

image-20230928163240928

image-20230928163343071

1.1 反射相关的主要类

image-20230928163416900

java">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 反射的优点和缺点

image-20230928170555665

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

image-20230928171454966

image-20230928171547125

java">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 基本介绍

image-20230928172213503

image-20230928172250021

java">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类的常用方法

image-20230928174347986

java">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 类对象

image-20230928180145691

image-20230928180151255

image-20230928180157283

java">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 对象

image-20230928184711589

java">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 基本说明

image-20230928192003731

4.2 类加载时机

image-20230928192053660

4.3 类加载过程图

image-20230928192110265

4.4 类加载各阶段完成任务

image-20230928192132922

4.5 加载阶段

image-20230928192155241

4.6 连接阶段-验证

image-20230928192223356

4.7 连接阶段-准备

image-20230928192237893

java">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. 连接阶段-解析

image-20230928192623999

6. Initialization(初始化)

image-20230928192644741

java">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. 通过反射获取类的结构信息

javalangClass__509">5.1 第一组:java.lang.Class 类

image-20230930151133200

javalangreflectField__513">5.2 第二组:java.lang.reflect.Field 类

image-20230930151234712

javalangreflectMethod__517">5.3 第三组: java.lang.reflect.Method 类

image-20230930151326302

javalangreflectConstructor__521">5.4 第四组:java.lang.reflect.Constructor 类

image-20230930151502568

java">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. 通过反射创建对象

image-20230930151549506

  • 测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
  • 测试 2:通过调用某个特定构造器的方式,实现创建某类的对象
java">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. 通过反射访问类中的成员

java_784">7.1 访问属性 ReflecAccessProperty.java

image-20230930151705599

java">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 + ']';
    }
}

java_843">7.2 访问方法 ReflecAccessMethod.java

image-20230930151820601

java">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. 本章作业

image-20230930151849221

java">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;
    }
}

image-20230930151918622

java">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);

    }
}

http://www.niftyadmin.cn/n/5060141.html

相关文章

【Java 进阶篇】MySQL 数据控制语言(DCL):管理用户权限

MySQL 是一个强大的关系型数据库管理系统&#xff0c;提供了丰富的功能和选项来管理数据库和用户。数据库管理员&#xff08;DBA&#xff09;通常使用数据控制语言&#xff08;Data Control Language&#xff0c;简称 DCL&#xff09;来管理用户的权限和访问。 本文将详细介绍…

【数据结构与算法】栈与队列相关算法的实现

目录 检查括号是否成对出现 反转字符串 循环队列的实现 使用队列实现栈 使用栈实现队列 检查括号是否成对出现 算法要求 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串&#xff0c;判断该字符串是否有效。 有效字符串需满…

【CFD小工坊】浅水方程的离散及求解方法

【CFD小工坊】浅水方程的离散及求解方法 前言基于有限体积法的方程离散界面通量与源项计算干-湿网格的处理数值离散的稳定性条件参考文献 前言 我们模型的控制方程&#xff0c;即浅水方程组的表达式如下&#xff1a; ∂ U ∂ t ∂ E ( U ) ∂ x ∂ G ( U ) ∂ y S ( U ) U…

win10打开VMware 16 pro里面的虚拟机就蓝屏怎么办

2023年9月30日&#xff0c;周六下午 今天下午我也遇到了这个问题&#xff0c;后来解决了&#xff0c;于是记录一下我的解决办法 目录 1、打开控制面板&#xff0c;并选择“程序和功能” 2、点击“启动或关闭Windows服务” 3、勾选两个服务 4、重启电脑&#xff0c;大功告成…

mongodb Community 7 安装(linux)

链接&#xff1a;mongodb官网 链接&#xff1a;官方安装文档 一、安装 1.安装依赖 apt-get install gnupg curl2.安装public key cd /usr/localcurl -fsSL https://pgp.mongodb.com/server-7.0.asc | gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor3.把mon…

2023 年中秋有什么福利?

苏生不惑第454 篇原创文章&#xff0c;将本公众号设为星标&#xff0c;第一时间看最新文章。 时间过得很快&#xff0c;又到了一年的中秋加国庆。准备吃月饼了吗&#xff1f; 按照惯例抓取了苏生不惑公众号2023年的所有文章数据&#xff0c;详情见之前文章2023批量下载公众号文…

国庆中秋特辑(五)MySQL如何性能调优?下篇

目录 5.数据库维护6. 数据库调优工具7.数据库架构优化8.代码层面优化9. 硬件层面优化10. 数据库安全 MySQL 性能优化是一项关键的任务&#xff0c;可以提高数据库的运行速度和效率。以下是一些优化方法&#xff0c;包括具体代码和详细优化方案。 接下来详细介绍&#xff0c;共有…

NullPointerException:com.sun.tools.javac.api.JavacTool

错误信息 在Linux 环境部署的spring boot 应用使用到 JavaCompiler ,需要使用 com.sun.tools.javac.api.JavacTool,结果在运行时出现一下错误 NullPointerException: com.sun.tools.javac.api.JavacTool错误原因 执行java -version,发现是有jdk的,但是javac 确无法执行,而且在/…