Java反射的理解

一、Java内存模型 

先了解一下JVM(虚拟机),java之所以能跨平台就是因为这个东西,你可以理解成一个进程,程序,只不过他的作用是用来跑你的代码的。

假如你写了一段代码:Object o=new Object();

运行了起来!

首先JVM会启动,你的代码会编译成一个.class文件,然后被类加载器加载进jvm的内存中,你的类Object加载到方法区中,创建了Object类的class对象到堆中,注意这个不是new出来的对象,而是类的类型对象,每个类只有一个class对象,作为方法区类的数据结构的接口。jvm创建对象前,会先检查类是否加载,寻找类对应的class对象,若加载好,则为你的对象分配内存,初始化也就是代码:new Object()。

上面的流程就是你自己写好的代码扔给jvm去跑,跑完就over了,jvm关闭,你的程序也停止了。

为什么要讲这个呢?因为要理解反射必须知道它在什么场景下使用。

题主想想上面的程序对象是自己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容器就会根据你的需求去动态加载,你的程序就能健壮地运行。
 
 

二、Java反射机制

含义:所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底的了解自身的情况为下一步的动作做准备。 

Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method。

Java反射的作用:在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。

Java 反射机制主要提供了以下功能:

在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法


三、Java反射用法

1、获取类对象的方法

 Class<?> cl = Class.forName("java.lang.String");
Class<?> cl = String.class;
String str = "111";
Class<?> cl = str.getClass

2.获取字段信息的方法

Class<?> cl = String.class;
//获取公有的指定成员变量(包括继承的公有变量都能访问到但是私有和受保护的属性访问不到)
Field field = cls.getField("变量名");
//获取公有所有成员变量(私有的和受保护的访问不到)
Field[] fields = cls.getFields();
//获取以声明的指定变量(私有、公有、受保护的都能访问到,但是不包括继承的) 
Field field1 = cls.getDeclaredField("变量名");
//获取所有以声明的变量
 Field[] fields1 = cls.getDeclaredFields();

3、获取方法信息的方法

 //返回某个类的指定的公用(public)方法,包括其继承类的公用方法。
Method method = cl.getMethod("方法名");
//返回某个类的所有公用(public)方法.
Method[] methods = cl.getMethods();
//返回类或接口声明的指定方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。可以传方法名和方法的参数类型,多个参数逗号隔开。
Method method = cl.getDeclaredMethod("方法名", String.class);
//返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method[] methods = c.getDeclaredMethods();

4、获取构造器的方法

//获取该Class对象公有的使用特殊参数类型的构造函数,与父类构造无关
Constructor<?> constructor = cl.getConstructor(参数类型);
//获取该Class对象所有公有的构造函数
 Constructor[] constructors = c.getConstructors();
//获取该Class对象指定的声明的构造函数包括公有、私有、受保护的,与父类构造无关
Constructor<?> constructor1 = c.getDeclaredConstructor(参数类型)
//获取该Class对象所有声明的构造函数
Constructor[] constructors1 = c.getDeclaredConstructors();

四、总结

当我们用getDeclaredField("变量名")获取到声明指定变量时,直接修改该属性的值时,需要调用field.setAccessible(true),这时才能修改该变量的值,因为该变量可能是私有的或者是受保护的不允许直接修改,而当我们这样做了就违背了java面向对象封装的原则,并且在有些业务上当你不了解有些私有属性不能被修改时,你就可以通过反射获取该类的所有set方法,通过调用set方法去改变具体属性值。

这个是用来将字符串首字母转大写的方法,进行字母的ascii编码前移

//将传进来的字段名首字母大写
    private static String getMethodName(String fildeName) throws Exception{
        byte[] items = fildeName.getBytes();
        items[0] = (byte) ((char) items[0] - 'a' + 'A');
        return new String(items);
    }

大神们这些都是个人理解哪里有一样的想法或建议欢迎评论!!!!!!!

 
如果一个人没有梦想,和咸鱼有什么区别?
原文地址:https://www.cnblogs.com/dashuaiguo/p/9896439.html