最近在学习SpringBoot的知识,动起手来学习的时候才发现SpringBoot项目采用了大量的反射机制,晕,作为一个应届毕业生,以前学习反射的时候给我的感觉就是,这个到底用来干嘛的,好像没啥用啊,而且接触的地方也不是非常的多,接触比较多的地方还是JDBC注册驱动的那条语句:

Class.forName("com.mysql.jdbc.Driver");  //注册数据库驱动

  这样肯定是不行的,想要学好SpringBoot的第一步,就是把反射学好。于是,我决定重新把遗忘的而重要的知识捡起来,重新好好地学一下。

  我们带着个两个问题来学:反射是什么?反射怎么用?


  反射是什么?

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

  要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

  这里用一个类,Person类的加载过程来具体说明一下,如下图

这里补充一下,当我们的JVM把Person.class加载到内存的时候,会同步的产生关于这个文件的Class对象,这个对象里面封装的就是Person的信息,而且,不管我们new Person()使用多少次,我们的JVM只会为它创建一个Class对象。

我们反射的本质就是得到Class对象之后,通过调用Class中的方法反向的获取Person对象的各种信息。


  反射怎么用?

  一、Class对象的获取

   通过上面的讲解,我们知道,要使用反射的关键就是获取到Class对象,然后通过调用Class对象里面的方法,获取到我们想要知道的东西,比如这个类的包路径,都有什么方法等等。而获取Class对象的方法一共有三个,这里一一介绍。

  1.Object ——> getClass(),通常应用在:比如你传过来一个 Object

package ydy;

/**
* 获取Class对象的三种方法之第一种
* @author dengyan.yao
*
*/
public class Reflection {
public static void main(String[] args) { //获取Class对象的第一种方法
Person person = new Person();//new的时候产生了一个Person对象和一个Class对象
Class perClass = person.getClass();//获取Class对象
System.out.println("获取到的对象:" + perClass); }
}

  

  2、类名.class 的方式得到,该方法最为安全可靠,程序性能更高 

package ydy;

/**
* 获取Class对象的三种方法之第二种
* @author dengyan.yao
*
*/
public class Reflection {
public static void main(String[] args) { //获取Class对象的第二种方法
Class perClass = Person.class;
System.out.println("获取到的对象:" + perClass); }
}

  

  3、通过 Class 对象的 forName() 静态方法来获取,用的最多

package ydy;

/**
* 获取Class对象的三种方法之第三种
* @author dengyan.yao
*
*/
public class Reflection {
public static void main(String[] args) { //获取Class对象的第三种方法
Class perClass;
try {
perClass = Class.forName("ydy.Person");//这里的String路径是类的全路径,从包名到类名
System.out.println("获取到的对象:" + perClass);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}

  

  二、反射的简单使用

  反射的使用主要就是获取到了Class对象之后,通过调用Class对象的方法来操纵,使用Person对象的一些属性,这里主要使用第三种方式来获取Class对象,并且列举一些简单的使用。

  

  1、获取成员变量并调用

  定义一个Person类,里面添加一些属性:

package ydy;

public class Person {
public String name;//公开的name
private Double weight;//私有的weight
protected char sex; //受保护的sex
int age; //默认的age
@Override
public String toString() {
return "Person [name=" + name + ", weight=" + weight + ", sex=" + sex + ", age=" + age + "]";
} }

  编写测试类Test:

package ydy;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; /**
* 获取成员变量并调用
* @author dengyan.yao
*
*/
public class Test {
public static void main(String[] args) throws Exception{
//获取Class对象
Class perClass = Class.forName("ydy.Person");
//获取字段
System.out.println("获取所有字段");
Field[] fieldArray = perClass.getDeclaredFields();
for (Field field : fieldArray) {
System.out.println(field);
}
System.out.println("获取所有共有字段");
fieldArray = perClass.getFields();
for (Field field : fieldArray) {
System.out.println(field);
}
System.out.println("获取所有共有字段并调用");
Field f = perClass.getField("name");
System.out.println(f);
//获取Person对象
Object per = perClass.getConstructor().newInstance();
//为字段设置值
f.set(per, "反射");
//验证
Person person = (Person)per;
System.out.println("验证名字:" +person.name);
}
}

  测试结果:

获取所有字段
public java.lang.String ydy.Person.name
private java.lang.Double ydy.Person.weight
protected char ydy.Person.sex
int ydy.Person.age
获取所有共有字段
public java.lang.String ydy.Person.name
获取所有共有字段并调用
public java.lang.String ydy.Person.name
验证名字:反射

  

  2、获取成员变量并调用

  Person类

package ydy;

public class Person {

	//---------------构造方法-------------------
//默认的构造方法
Person(String str){
System.out.println("(默认)的构造方法 s = " + str);
} //无参构造方法
public Person(){
System.out.println("调用了公有、无参构造方法执行了。。。");
} //有一个参数的构造方法
public Person(char name){
System.out.println("姓名:" + name);
} //有多个参数的构造方法
public Person(String name ,int age){
System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。
} //受保护的构造方法
protected Person(boolean n){
System.out.println("受保护的构造方法 n = " + n);
} //私有构造方法
private Person(int age){
System.out.println("私有的构造方法 年龄:"+ age);
}
}

  测试类

package ydy;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; /**
* 获取构造方法并调用
* @author dengyan.yao
*
*/
public class Test {
public static void main(String[] args) throws Exception{
//1.加载Class对象
Class clazz = Class.forName("ydy.Person"); //2.获取所有公有构造方法
System.out.println("所有公有构造方法");
Constructor[] conArray = clazz.getConstructors();
for(Constructor c : conArray){
System.out.println(c);
} System.out.println("所有的构造方法(包括:私有、受保护、默认、公有)");
conArray = clazz.getDeclaredConstructors();
for(Constructor c : conArray){
System.out.println(c);
} System.out.println("获取公有、无参的构造方法");
Constructor con = clazz.getConstructor();
System.out.println("con = " + con);
//调用构造方法
Object obj = con.newInstance(); System.out.println("获取私有构造方法,并调用");
con = clazz.getDeclaredConstructor(char.class);
System.out.println(con);
//调用构造方法
con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
obj = con.newInstance('男');
}
}

  测试结果

所有公有构造方法
public ydy.Person(java.lang.String,int)
public ydy.Person(char)
public ydy.Person()
所有的构造方法(包括:私有、受保护、默认、公有)
private ydy.Person(int)
protected ydy.Person(boolean)
public ydy.Person(java.lang.String,int)
public ydy.Person(char)
public ydy.Person()
ydy.Person(java.lang.String)
获取公有、无参的构造方法
con = public ydy.Person()
调用了公有、无参构造方法执行了。。。
获取私有构造方法,并调用
public ydy.Person(char)
姓名:男

  

  3、获取成员方法并调用

  Person类

package ydy;

public class Person {
public void eat(String s){
System.out.println("调用了:公有的,String参数的eat(): s = " + s);
}
protected void paly(){
System.out.println("调用了:受保护的,无参的paly()");
}
void run(){
System.out.println("调用了:默认的,无参的run()");
}
private String study(int age){
System.out.println("调用了,私有的,并且有返回值的,int参数的study(): age = " + age);
return "abcd";
}
}

  测试类

package ydy;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; /**
* 获取成员方法并调用
* @author dengyan.yao
*
*/
public class Test {
public static void main(String[] args) throws Exception{
//获取Class对象
Class stuClass = Class.forName("ydy.Person"); //获取所有公有方法
System.out.println("获取所有的”公有“方法");
stuClass.getMethods();
Method[] methodArray = stuClass.getMethods();
for(Method m : methodArray){
System.out.println(m);
} //获取所有方法
System.out.println("获取所有的方法,包括私有的");
methodArray = stuClass.getDeclaredMethods();
for(Method m : methodArray){
System.out.println(m);
} //获取特定的共有方法
System.out.println("获取公有的eat()方法");
Method m = stuClass.getMethod("eat", String.class);
System.out.println(m);
//实例化一个Student对象
Object obj = stuClass.getConstructor().newInstance();
m.invoke(obj, "反射"); System.out.println("获取私有的study()方法");
m = stuClass.getDeclaredMethod("study", int.class);
System.out.println(m); m.setAccessible(true);//解除私有限定
Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
System.out.println("返回值:" + result); }
}

   测试结果

获取所有的”公有“方法
public void ydy.Person.eat(java.lang.String)
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 java.lang.String java.lang.Object.toString()
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()
获取所有的方法,包括私有的
void ydy.Person.run()
public void ydy.Person.eat(java.lang.String)
private java.lang.String ydy.Person.study(int)
protected void ydy.Person.paly()
获取公有的eat()方法
public void ydy.Person.eat(java.lang.String)
调用了:公有的,String参数的eat(): s = 反射
获取私有的study()方法
private java.lang.String ydy.Person.study(int)
调用了,私有的,并且有返回值的,int参数的study(): age = 20
返回值:abcd

  


  

  总结

  1.反射的定义:

  在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能

  2.反射的用法:

  主要是通过获取Class对象之后调用Class的方法来使用,获取Class对象的方法有三个,分别是:

    对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object

    类名.class 的方式得到,该方法最为安全可靠,程序性能更高

    通过 Class 对象的 forName() 静态方法来获取,用的最多

SpringBoot学习系列之一(反射)的更多相关文章

  1. 【.Net 学习系列】-- 反射的简单用法

    新建两个项目:类库(Model)和控制台应用程序(ReflectTest). 在[Model]中添加一个类[User]: namespace Model { public class User { p ...

  2. Python学习系列之反射

    反射的定义 根据字符串的形式去某个对象中操作成员 根据字符串的形式去某个对象中寻找成员 根据字符串的形式去某个对象中设置成员 根据字符串的形式去某个对象中删除成员 根据字符串的形式去某个对象中判断成员 ...

  3. Java反射学习系列-绪论

    Java反射学习系列-绪论 https://blog.csdn.net/hanchao5272/article/details/79358924

  4. 源码学习系列之SpringBoot自动配置(篇一)

    源码学习系列之SpringBoot自动配置源码学习(篇一) ok,本博客尝试跟一下Springboot的自动配置源码,做一下笔记记录,自动配置是Springboot的一个很关键的特性,也容易被忽略的属 ...

  5. 源码学习系列之SpringBoot自动配置(篇二)

    源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...

  6. SpringBoot源码学习系列之SpringMVC自动配置

    目录 1.ContentNegotiatingViewResolver 2.静态资源 3.自动注册 Converter, GenericConverter, and Formatter beans. ...

  7. SpringBoot源码学习系列之异常处理自动配置

    SpringBoot源码学习系列之异常处理自动配置 1.源码学习 先给个SpringBoot中的异常例子,假如访问一个错误链接,让其返回404页面 在浏览器访问: 而在其它的客户端软件,比如postm ...

  8. SpringBoot源码学习系列之嵌入式Servlet容器

    目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...

  9. 快速体验Spring Boot了解使用、运行和打包 | SpringBoot 2.7.2学习系列

    SpringBoot 2.7.2 学习系列,本节内容快速体验Spring Boot,带大家了解它的基本使用.运行和打包. Spring Boot 基于 Spring 框架,底层离不开 IoC.AoP ...

随机推荐

  1. HDU 5113:Black And White(DFS)

    题目链接 题意 给出一个n*m的图,现在有k种颜色让你对这个图每个格子染色,每种颜色最多可以使用col[i]次,问是否存在一种染色方案使得相邻格子的颜色不同. 思路 以为是构造题,结果是爆搜.对于每一 ...

  2. Codeforces Gym101097I:Sticks (思维)

    http://codeforces.com/gym/101097/attachments 题意:现在有k种颜色的木棍,每种颜色有ni根木棍,每根木棍有一个长度,问是否有三根木棍可以组成三角形,并且这三 ...

  3. spring源码深度解析— IOC 之 bean 的初始化

    一个 bean 经历了 createBeanInstance() 被创建出来,然后又经过一番属性注入,依赖处理,历经千辛万苦,千锤百炼,终于有点儿 bean 实例的样子,能堪大任了,只需要经历最后一步 ...

  4. python 微信红包生成器

    #红包生成思路#200 块钱 10个红包#0-200 的一个轴,随机取9个点,分成10段, 每一段的值表示一个红包的大小 #把输入的 money值 * 100 拿到的数值就是分, 不用再考虑单位是元的 ...

  5. 基于SpringBoot从零构建博客网站 - 设计可扩展上传模块和开发修改头像密码功能

    上传模块在web开发中是很常见的功能也是很重要的功能,在web应用中需要上传的可以是图片.pdf.压缩包等其它类型的文件,同时对于图片可能需要回显,对于其它文件要能够支持下载等.在守望博客系统中对于上 ...

  6. c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...

  7. Python C3 算法 手动计算顺序

    Python C3 算法 手动计算顺序   手动计算类继承C3算法原则: 以所求类的直接子类的数目分成相应部分 按照从左往右的顺序依次写出继承关系 继承关系第一个第一位,在所有后面关系都是第一个出现的 ...

  8. mongon库加上权限认证后,java程序连接异常

    现象: linux库中mongo库,用超级管理员添加了一个超级管理员,并加了认证. 通过spring等相关的配置文件获取Mongo数据库连接,抛出异常,如下: Caused by: org.sprin ...

  9. kuangbin专题专题四 Heavy Transportation POJ - 1797

    题目链接:https://vjudge.net/problem/POJ-1797 思路:请参考我列出的另一个题目,和这个题目要求的值相反,另一个清楚后,这个写的解释就明白了. 另一个类似题目的博客:h ...

  10. Java编程思想:通配符(后面有两个小节,研究的不够深入)

    import java.util.*; public class Test { public static void main(String[] args) { } } /* 15.9 边界 要点: ...