Java反射 学习笔记

反射: 框架设计的灵魂

框架:半成品软件。可以在框架的基础上进行软件的开发,简化编码

反射:将类的各个组成部分封装为其他对象,这就是反射机制。
将类的成员变量封装为Field对象,构造函数封装为Constructor对象,将成员方法封装为Method对象

反射的好处:

  1. 在程序的运行过程中,操作这些对象。 eg: 在程序中输入这样一行代码:String str="abc"; str.输入str.时会提示你一大堆的方法,这些方法从哪来的,这里就运用了反射机制,你在此处定义了一个字符串,会把字符串的字节码文件加载进内存,在内存中有一个class类对象,它已经把所有的方法抽取出来,封装为Method对象,把所有的方法放进method数组里,提示时,只需把数组里的每一个数组成员拿出来,名字显示出来,展示在列表里就可以了
  2. 可以解耦(降低程序的耦合性),提高程序的可扩展性

在这里插入图片描述
(反射:将类的各个组成部分封装为其他对象,想要获取和操作这些对象关键是获取字节码 Class类对象)
获取Class对象的方式:(三种方式分别对应着java代码经历的三个阶段)

在这里插入图片描述

  1. (Java代码在第一个阶段,意味着你的Java代码只有字节码文件,没有进内存,我们需要手动的加载进内存,生成一个字节码文件,生成一个Class对象)Class.forName("全类名"); 将字节码文件加载进内存,返回Class对象 ------多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  2. (已经将字节码文件加载进内存了,还没有真正的类对象)类名.class; 通过类名的属性class来获取-----多用于参数的传递
  3. (已经有类对象了,通过对象的方法获取)对象.getClass();这个方法封装在object类里,在object类中定义,被所有对象继承下来------多用于对象的获取字节码的方式
    同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个

class对象功能:
获取的功能:
在这里插入图片描述

在反射面前没有私有公有之分,都可以设置 获取到

使用的Person类的定义

package cn.cast.domain;

public class Person {
    private String name;
    private int age;
    public String a;
    protected String b;
    String c;
    private String d;

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

    public Person() {
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
     public void eat(){
        System.out.println("eat...");
    }
    public void eat(String food){
        System.out.println("eat..."+food);
    }
}

Field :成员变量
操作:
1.设置值 void set(Object obj,Object value)
2.获取值get(Object obj)
3.忽略访问权限修饰符的安全检查setAccessible(true);暴力反射

package cn.cast.reflect;

import cn.cast.domain.Person;

import java.lang.reflect.Field;


public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        //1.获取person的Class对象
        Class personclass= Person.class;
        /**
         * 获取成员变量们
         * Field[] getFields():获取所有public修饰的成员变量
         * Field getField(String name) 获取指定名称的public修饰的成员变量
         * Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
         * Field getDeclaredField(String name) 获取指定名称的成员变量
         */
        //1.Field[] getFields()
        Field[] fields=personclass.getFields();
        for(Field field:fields){
            System.out.println(field);
        }
        System.out.println("-----------");
        //2.Field getField(String name)
        Field a=personclass.getField("a");
        //获取成员变量a的值
        Person p=new Person();
        Object value=a.get(p);//以前获取成员变量的值是 p.a  现在是a.get()把对象传进去,因为成员变量是在对象内部存在,我们需要传一个真正的对象
        System.out.println("value = " + value);
        a.set(p,"roxanne");
        System.out.println(p);
        System.out.println("-----------");
        //3.Field[] getDeclaredFields();获取所有的成员变量
        Field[] declaredfields= personclass.getDeclaredFields();
        for (Field declaredfield : declaredfields) {
            System.out.println(declaredfield);
        }
        //4.Field getDeclaredField(String name)
        Field d= personclass.getDeclaredField("d");
        //私有的不能直接被访问,所以我们需要忽略访问权限修饰符的安全检查
        d.setAccessible(true);//暴力反射
        Object value2=d.get(p);
        System.out.println("value2 = " + value2);

    }
}

Constructor:构造方法
创建对象:
T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

package cn.cast.reflect;

import cn.cast.domain.Person;

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

public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        //1.获取person的Class对象
        Class personclass= Person.class;
        /**
         * 获取构造方法们
         * Constructor<?>[] getConstructor()
         * Constructor<T>[] getConstructor(类<?>...parametersTypes)
         * Constructor<T>[] getDeclaredConstructor(类<?>...parametersTypes)  使用私有的构造器创建对象,也需要调用构造器对象的setAccessible()方法来使用
         * Constructor<?>[] getDeclaredConstructor()
         */
        Constructor constructor=personclass.getConstructor(String.class,int.class);//构造方法通过传的参数不同来区分,要求的参数类型是不同参数的class对象
        System.out.println("constructor = " + constructor);//constructor = public cn.cast.domain.Person(java.lang.String,int)
        //创建对象
        Object person=constructor.newInstance("roxanne",23);
        System.out.println("person = " + person);//person = Person{name='roxanne', age=23, a='null', b='null', c='null', d='null'}

        System.out.println("-----------");
        //利用空参来创建
        Constructor constructor1=personclass.getConstructor();//构造方法通过传的参数不同来区分,要求的参数类型是不同参数的class对象
        System.out.println("constructor1 = " + constructor1);//constructor1 = public cn.cast.domain.Person()
        //创建对象
        Object person1=constructor1.newInstance();
        System.out.println("person1 = " + person1);//person1 = Person{name='null', age=0, a='null', b='null', c='null', d='null'}

        Object o=personclass.newInstance();
        System.out.println("o = " + o);//o = Person{name='null', age=0, a='null', b='null', c='null', d='null'}

    }
}

Method:方法对象
执行方法:

Object invoke(Object obj,Object... args)//需要传真实对象和方法实际的参数列表

获取方法名称: String getName:获取方法名

package cn.cast.reflect;

import cn.cast.domain.Person;

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

public class ReflectDemo4 {
    public static void main(String[] args) throws Exception {
        //1.获取person的Class对象
        Class personclass= Person.class;
        /**
         * 获取成员方法们
         * 不带declared的只能获取公共的,带declared不考虑修饰符,什么都能获取到,但要使用setAccessible()暴力反射
         * Method[] getMethods()
         * Method getMethod(String name,类<?>...parameterTypes)
         *
         * Method[] getDeclaredMethods()
         * Method getDeclaredMethod(String name,类<?>...parameterTypes)
         */
         //获取指定名称的方法
        Method eatmethod=personclass.getMethod("eat");//方法三要素 方法名 返回值列表 参数列表,确定一个方法需要两个参数 方法名 参数列表(因为重载是方法名一样 参数列表不一样)
        Person p=new Person();
        //执行方法
        eatmethod.invoke(p);

        Method eatmethod2=personclass.getMethod("eat",String.class);
        eatmethod2.invoke(p,"饭");

        System.out.println("----------");
        //获取所有public修饰的方法
        Method[] methods= personclass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            System.out.println(method.getName());
            //不仅只有你设定的 还有继承自object的方法
        }
        //获取类名
        String className=personclass.getName();
        System.out.println("className = " + className);//className = cn.cast.domain.Perso
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值