反射浅析

为什么要使用反射呢

一般情况下的程序对象是自己new的,程序相当于写死了给jvm去跑。但是,如果一个服务器上突然遇到某个请求哦要用到某个类,哎呀但没加载进jvm,是不是要停下来自己写段代码,new一下,启动一下服务器,(脑残?)!

反射是什么呢?当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器来说不言而喻,举个例子我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,通过Class tc = Class.forName(“com.java.dbtest.TestConnection”);通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则传入的参数就变成另一个了。这时候就可以看到反射的好处了,这个动态性就体现出java的特性了!举多个例子,大家如果接触过spring,会发现当你配置各种各样的bean时,是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。

在这里插入图片描述

简单理解就是不再直接new对象了,而是间接的获取class对象

类加载器把 .java 文件通过编译之后变成了 .class 文件。可知.clsss 字节码文件是拥有 .java 文件的所有东西。

一个java程序的加载就是把所对应的 .class 文件加载到内存的方法区,在内存中有一个 .class 文件对应的内存区域,这个内存区域包含了java所有的内容(成员变量,成员方法,构造方法等)

在这里插入图片描述

获取类对象的三种方法

1、static Class forName(String name):通过类名来获取,是静态方法,传入的参数是一个完整的(包名+类名)

2、Class类名.class:通过类名来调用,获取当前类对应的属性

3、Class类对象.getClass():通过类对象来调用,获取当前Class类对象

public class Reflect {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是:"+person.name);
        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        //方式二:forname获得
        Class c2 = Class.forName("com.qfedu.Student");
        System.out.println(c2.hashCode());
        //方式三:通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

    }
}
class Person{
    public String name;
    public Person(){

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
class Student extends Person{
    public Student(){
        this.name="学生";
    }
}
class Teacher extends Person{
    public Teacher(){
        this.name="老师";
    }
## 获取Constructor类对象

Constructor[] getConstructors();获取当前类内所有的非私有化的构造方法
Constructor[] getDeclaredConstructors();获取当前类所有的构造方法,包括私有
Constructor getConstructor(Class…initParmeterType);根据指定的参数类型获得相应的非私有化方法
Constructor getDeclaredConstructor(Class…initParmeterType)根据指定的参数类型获得相应的构造方法,包含私有的
Object newInstance(Object…initParmeters)获取当前类的对象

public class GetConstructors {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> aClass = Class.forName("com.qfedu.reflect.Person");
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);//3
        }
        System.out.println("===========");
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);//4
        }
        System.out.println("======");
        Constructor<?> constructor = aClass.getConstructor(null);
        System.out.println(constructor);//无参数的构造
        Constructor<?> constructor1 = aClass.getConstructor(int.class);
        System.out.println(constructor1);//int类型构造方法
        Constructor<?> constructor2 = aClass.getConstructor(String.class);
        System.out.println(constructor2);

        Constructor<?> constructor3 = aClass.getDeclaredConstructor(int.class, String.class);
        System.out.println(constructor3);
        System.out.println("======");
        Object o = constructor.newInstance(null);
        System.out.println(o);
        Object o1 = constructor1.newInstance(10);
        System.out.println(o1);
        System.out.println("======");
        constructor3.setAccessible(true);//暴力反射获取反射的内容,私有的不能进行赋值
        //setAccessible(true)
        Object laoxing = constructor3.newInstance(3, "Laoxing");
        System.out.println(laoxing);

    }

获取Method类对象

Method[] getMethods();获取当前类的非私有化成员方法,包括从父类继承过来在子类可以使用的方法
Method[] getDeclaredMethods();获取当前类所有的成员方法,但不包括从父类继承过来的在子类可以使用的方法
Method[] getMethod(String methodName,Class...parameterType);获取类内指定的方法,和参数类型的非私有化方法
Method[] getDeclaredMethod(String methodName,Class...parameterType);获取类内指定的方法,和参数类型的方法,包括了私有化的方法
Object invoke(Object obj,Object...args)
Object obj:调用当前方法的类对象
Object...args:执行当前方法的需要的实际参数列表
public class GetMethodsObject {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> aClass = Class.forName("com.qfedu.reflect.Person");
        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 game = aClass.getMethod("game", null);
        System.out.println(game);
        Method game1 = aClass.getMethod("game", String.class);
        System.out.println(game1);
        System.out.println("========");
        Method testPrivate = aClass.getDeclaredMethod("testPrivate", null);
        Method testPrivate1 = aClass.getDeclaredMethod("testPrivate", String.class);
        System.out.println(testPrivate);
        System.out.println(testPrivate1);

        System.out.println("-===========");
        
        Person person = new Person();
        System.out.println(person);
        Object o = aClass.getConstructor(null).newInstance(null);
        System.out.println(o);
        game.invoke(o, null);//这个方法必须得会!!!
        game1.invoke(aClass.getConstructor(null).newInstance(null), "我无敌了,你们随便送!!!");

        testPrivate.setAccessible(true);
        testPrivate.invoke(aClass.getConstructor(null).newInstance(null), null);
        testPrivate1.setAccessible(true);
        testPrivate1.invoke(aClass.getConstructor(null).newInstance(null), "heheda");
        
    }
}

获取Field类对象

Field[] getFields();获取非私有化成员属性的类对象。返回的是一个数组
Field[] getDeclaredFields();获取所有成员属性的类对象。包含私有的,返回的是一个数组
Field getField(String FieldName);通过成员变量的名字获取指定的成员变量,不能获取私有的成员变量
Field getDeclaredField(String FieldName);通过成员变量的名字获取指定的成员变量,可以获取私有化的成员变量
void set(Object obj,Object value);给当前对象的属性进行赋值
Object get(Object obj);获取类对象属性的值
public class GetFieldObject {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> aClass = Class.forName("com.qfedu.reflect.Person");
        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("======");
        Field test = aClass.getField("test");
        System.out.println(test);//非私有化的成员变量
        Field id = aClass.getDeclaredField("id");
        System.out.println(id);
        //获取Person对象
        Person person = (Person)aClass.getConstructor(null).newInstance(null);
        id.setAccessible(true);
        id.set(person, 20);

        test.set(person, 100);
        System.out.println(person);
        System.out.println(id.get(person));

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值