反射

反射

1.什么是反射?

反射机制是指在程序的运行状态下,任何一个类,我们可以获取类的构造方法,字段,方法,也可以对他们进行修改和设置,这种方法,我们称为反射。

2.反射的前提

想要对一个类必须获取该类的字节码,有如下三种方式。

  • getClass()方法
  • 静态属性class
  • Class.forName()方法
3.类加载器
1.概念
 将.class文件加载到内存中,并生成相对应的Class对象
2.分类以及作用
 1.根类加载器
   负责Java核心类的加载
 2.扩展类加载器
   负责Jre的扩展目录中jar包的加载
 3.系统类加载器
   负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
4.创建一个学生类(后面的例子都为此学生类)
public class Student {
   public String name;
    int age;
    private  double height;
    protected double weight;
    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
        System.out.println("有参构造调用了");
    }
    public Student() {
        System.out.println("无参构造调用了");
    }
    private Student(String name,int age){
        this.name=name;
        this.age=age;
        System.out.println("私有构造调用了");
    }
    public void show(){
        System.out.println("空参方法");
    }
    public void show1(int age){
        System.out.println(age);
    }
    private void show2(String name,int age){
        System.out.println(name+age);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                ", weight=" + weight +
                '}';
    }
}
5.如何通过反射获取类的构造方法,并实例化
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取当前对象的字节码对象
        Class<?> student = Class.forName("com.westore.reflect.Student");
        /**
         * 获取当前字节码对象的构造方法(不包括私有)
         * public com.westore.reflect.Student()
         * public com.westore.reflect.Student(java.lang.String,int,double)
         */
        Constructor<?>[] constructors = student.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("===========");
        /**
         * 获取当前字节码对象的所有构造方法(包括私有)
         * private com.westore.reflect.Student(java.lang.String,int)
         * public com.westore.reflect.Student()
         * public com.westore.reflect.Student(java.lang.String,int,double)
         */
        Constructor<?>[] declaredConstructors = student.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("==========");
        /**
         * 无参构造实例化可直接通过字节码实例化,也可先获取无参构造对象创建对象
         */
        Object o2 = student.newInstance();
        System.out.println("==================");
        /**
         * 获取指定的构造方法,传入形式参数的字节码对象
         * 不能获取私有的构造
         */
        Constructor<?> constructor = student.getConstructor(String.class, int.class, double.class);
        System.out.println(constructor);
        //调用构造方法
        Object o1 = constructor.newInstance("lee",18,178);
        System.out.println("==============");
        /**
         * 可获取私有的构造方法
         */
        Constructor<?> constructor1 = student.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor1);
        //切记,私有的使用时必须调用此方法打破封装
        constructor1.setAccessible(true);
        Object o = constructor1.newInstance("LEE",18);
        System.out.println("===============");
        
    }
}

//输出结果
public com.westore.reflect.Student()
public com.westore.reflect.Student(java.lang.String,int,double)
===========
private com.westore.reflect.Student(java.lang.String,int)
public com.westore.reflect.Student()
public com.westore.reflect.Student(java.lang.String,int,double)
==========
无参构造调用了
==================
public com.westore.reflect.Student(java.lang.String,int,double)
有参构造调用了
==============
private com.westore.reflect.Student(java.lang.String,int)
私有构造调用了
===============
6.如何通过反射获取字段,并设置值
public class Demo2 {
    //获取类的字段
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class<?> aClass = Class.forName("com.westore.reflect.Student");
        //实例化无参构造
        Object o = aClass.newInstance();
        /**
         * 获取公共的字段
         */
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("====================");
        /**
         * 获取所有的字段
         */
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("================");
        /**
         * 获取任意单个字段,并可以对字段进行设置
         * set时需要传入对象和value
         * 获取时通过get方法获取
         */
        Field age = aClass.getDeclaredField("age");
        age.set(o,18);
        System.out.println(age.get(o));
        System.out.println(age);
        System.out.println("============");
        /**
         * 获取私有字段
         * 设置私有字段时,必须首先打破封装,否则会出现如下
         * Exception in thread "main" java.lang.IllegalAccessException
         */
        Field height = aClass.getDeclaredField("height");
        height.setAccessible(true);
        height.set(o,130);
        System.out.println(height.get(o));
    }
}

//输出结果
无参构造调用了
public java.lang.String com.westore.reflect.Student.name
====================
public java.lang.String com.westore.reflect.Student.name
int com.westore.reflect.Student.age
private double com.westore.reflect.Student.height
protected double com.westore.reflect.Student.weight
================
18
int com.westore.reflect.Student.age
============
130.0
7.如何通过反射获取方法,并调用
public class Demo3 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class<?> aClass = Class.forName("com.westore.reflect.Student");
        Object o = aClass.newInstance();
        /**
         * 获取所有的公共方法,包括父类
         */
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("=====================");
        /**
         * 获取当前类的所有方法(不包括父类)
         */
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("==============");
        /**
         * 获取指定无参方法,并调用(只适合公开的方法)
         */
        Method show = aClass.getMethod("show");
        Object invoke = show.invoke(o);
        System.out.println("===============");
        /**
         * 获取指定有参方法,并调用(只适合公开的方法)
         */
        Method show1 = aClass.getMethod("show1", int.class);
        Object invoke1 = show1.invoke(o, 18);
        System.out.println("====================");
        /**
         * 获取指定有参方法,可获取所有类型修饰的方法
         * 私有方法必须打破封装
         */
        Method show2 = aClass.getDeclaredMethod("show2", String.class, int.class);
        show2.setAccessible(true);
        Object lee = show2.invoke(o, "Lee", 20);
    }
}

//输出结果
无参构造调用了
public java.lang.String com.westore.reflect.Student.toString()
public void com.westore.reflect.Student.show()
public void com.westore.reflect.Student.show1(int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
=====================
public java.lang.String com.westore.reflect.Student.toString()
public void com.westore.reflect.Student.show()
public void com.westore.reflect.Student.show1(int)
private void com.westore.reflect.Student.show2(java.lang.String,int)
==============
空参方法
===============
18
====================
Lee20
8.使用反射越过泛型检查
首先我们得知道泛型是什么,泛型就是给对象加上一层限定,只能存储某类型的数据,泛型的有效期在编译期,运行期会进行自动擦除,也就是.java文件到.class文件的过程中有效,如果我们越过编译期,直接对.class文件进行操作,我们就可以越过泛型检查
public class Demo4 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<Integer> arrayList=new ArrayList<>();
        arrayList.add(100);
        arrayList.add(200);
        //直接添加其他类型会出现以下错误
       /* arrayList.add("我");
        Error:(10, 18) java: 对于add(java.lang.String), 找不到合适的方法
        方法 java.util.Collection.add(java.lang.Integer)不适用*/
        //获取arrlist字节码对象
        Class<? extends ArrayList> aClass = arrayList.getClass();
        //获取方法对象
        Method add = aClass.getMethod("add", Object.class);
        //调用方法
        Object o = add.invoke(arrayList, "我爱你");
        //遍历集合
        for (int i=0;i<arrayList.size();i++){
            System.out.println(arrayList.get(i));
        }
    }
}

//输出结果
100
200
我爱你
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值