JAVA--异常

发布时间 2023-10-02 17:19:52作者: harper886

什么是反射?

可以从类里面将该类的成员方法成员变量,构造方法的信息给拿出来

image-20231002150155173

使用可以获取成员变量,构造方法,成员方法的所有信息.

image-20231002150508560

学习反射应该学习如何获取和解剖

image-20231002150630025

获取class对象的三种方式

image-20231002151024153

  1. 在源代码阶段使用Class.forName("全类名");(最常用)

  2. 在加载阶段使用A.class(一般更多是当作参数传递)

  3. 在运行阶段使用对象.getClass();(已经有了这个类的对象才能使用)

    代码演示

    public class MyReflectDemo01 {
        public static void main(String[] args) throws ClassNotFoundException {
            //1.第一种方式
            //全类名:包名+类名 Student
            Class clazz = Class.forName("Student");
            //打印
            System.out.println(clazz);
            //第二种方式
            Class clazz2 = Student.class;
            //打印
            System.out.println(clazz2);
            System.out.println(clazz == clazz2);//两个获取的是一个对象
            //第三种方式
            Student s = new Student();
            Class clazz3 = s.getClass();
            System.out.println(clazz3);
            //获取的字节码文件对象是一样的
            System.out.println(clazz3 == clazz2);
            System.out.println(clazz2 == clazz);
        }
    }
    

    下面是一个标准的Java类

    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    

利用反射获取构造方法

在Java当中万物皆可对象,所以如图所示: Class有对象,构造方法有对象,成员变量和成员方法也有对象

image-20231002153113862

image-20231002153420774

  1. 返回所有public修饰的构造方法
  2. 返回所有的构造方法
  3. 返回单个的public修饰的构造方法
  4. 返回单个的构造方法

一个Student类

public class Student {
    private String name;
    private int age;

    private Student(int age) {
        this.age = age;
    }

    private Student(String name) {
        this.name = name;
    }

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

反射的各种方法

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;

public class MyReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //获取class字节码文件对象
        Class clazz = Class.forName("Student");
        //获取public构造方法
        /*
        Constructor[] cons =clazz.getConstructors();
        for (Constructor con : cons) {
            System.out.println(con);
        }
        */
        //获取所有构造方法
//        Constructor[] con1 =clazz.getDeclaredConstructors();
//        for (Constructor con : con1) {
//            System.out.println(con);
//        }
        //获取单个构造方法
//        Constructor con1 = clazz.getDeclaredConstructor();
//        System.out.println(con1);
//        //向里面传递的是字节码文件
//        Constructor con2 = clazz.getDeclaredConstructor(String.class);
//        System.out.println(con2);
//        Constructor con3 = clazz.getDeclaredConstructor(int.class);
//        System.out.println(con3);
        Constructor con4 = clazz.getDeclaredConstructor(String.class, int.class);
//        System.out.println(con4);
//        int modifiers = con4.getModifiers();//可以获取权限修饰符
//        System.out.println(modifiers);
//        Student stu = new Student();
//        Parameter[] parameters = con4.getParameters();
//        for (Parameter parameter : parameters) {
//            System.out.println(parameter);
//        }
    }
}

使用反射创建对象

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

public class MyReflectDemo02 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取class字节码文件对象
        Class clazz = Class.forName("Student");
        Constructor con3 = clazz.getDeclaredConstructor(String.class);
        //暴力反射:临时取消权限校验
        con3.setAccessible(true);
        Student stu = (Student) con3.newInstance("张三");//本身为private修饰
        System.out.println(stu);
    }
}

反射获取成员变量

image-20231002160619949

一个Student类

public class Student {
    private String name;
    private int age;
    public String gender;

    public Student() {
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

使用反射获取成员变量之后的各种操作

import java.lang.reflect.Field;

public class MyReflectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //1.获取class字节码文件的对象
        Class clazz = Class.forName("Student");
        //2.获取成员变量
//        Field[] fields = clazz.getFields();
        //获取所有成员变量
//        Field[] fields = clazz.getDeclaredFields();
//        for (Field field : fields) {
//            System.out.println(field);
//        }
        //获取单个public成员变量
//        Field gender = clazz.getField("gender");
//        System.out.println(gender);
//        获取单个成员变量
        Field name = clazz.getDeclaredField("name");
        System.out.println(name);
        //获取权限修饰符(也是int类型整数)
        int modifiers = name.getModifiers();
        System.out.println(modifiers);
        //获取变量名
        String n = name.getName();
        System.out.println(n);
        //获取成员变量数据类型
        Class<?> type = name.getType();
        System.out.println(type);
        //获取成员变量记录的值
        Student s = new Student("zhangsan", 23, "男");
        name.setAccessible(true);//临时取消访问权限
        String value = (String) name.get(s);
        System.out.println(value);
        //修改对象里面的值
        name.set(s, "lisi");
        System.out.println(s);

    }
}

反射获取成员方法

image-20231002163804063

一个Student类

import java.io.IOException;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public void sleep() {
        System.out.println("睡觉");
    }

    private String eat(String something) throws IOException, NullPointerException {
        System.out.println("在吃" + something);
        return "奥里给";
    }

    private String eat(String something, int a) {
        System.out.println("在吃" + something);
        return "奥里给";
    }

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

使用反射调用成员方法的各种操作

import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class MyReflectDemo03 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.获取字节码文件对象
        Class clazz = Class.forName("Student");
        //2.获取里面所有的方法对象(包含父类所有的公共方法)
//        Method[] methods = clazz.getMethods();
//        for (Method method : methods) {
//            System.out.println(method);
//        }
        //获取里面所有的方法对象(不可获取父类的公共方法),但是可以获取本类中私有的方法
//        Method[] methods = clazz.getDeclaredMethods();
//        for (Method method : methods) {
//            System.out.println(method);
//        }
        //获取指定的单一方法
        Method m = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(m);
        //获取方法修饰符
        int modifiers = m.getModifiers();
        System.out.println(m);
        //方法的名字
        String name = m.getName();
        System.out.println(name);
        //获取方法的形参
        Parameter[] parameters = m.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }
        //获取方法抛出的异常
        Class[] exceptionTypes = m.getExceptionTypes();
        for (Class exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }
        //方法运行 invoke方法
        Student s = new Student();
        //参数1:表示方法的调用者
        //参数2:表示在调用方法的时候传递的实际参数
        m.setAccessible(true);
        m.invoke(s, "汉堡");
        //如果方法带返回值的话
        Object result = m.invoke(s, "汉堡包");
        System.out.println(result);
    }
}