Java反射
前言
前一段时间,曾经学习Mybatis-plus,阅读源码解决过不少问题,便萌生想要去阅读Spring框架源代码,以便在今后的面试和工作中能有出色的表现,有朋友建议我在阅读源码之前,应该对java的基础知识(反射等)和设计模式这一块有很深的理解,好吧,我工作以来,这些东西很久没有关注过。承认学习过,但是,中了那句话的毒(学习是为了更好的遗忘),因此,对这一块内容进行特别整理一下。
我们编写的Java代码,并不是可以直接运行的,而是需要由Java虚拟机经过编译,形成class文件。然后才能去执行。因为Java是面向对象的,每一个程序都是由一个或者多个对象组成,在我们运行程序时,整个对象会随着代码翻译成class文件。对于java中的反射,我的理解是:通过程序,获取到class文件中的内容;通过Java反射,我们能动态获取类中的内容;
在这里,要注意一下: 一个类是由不同的属性 方法(函数)组成;
在这里,我们先创建一个对象,方便后面演示:
public class User { public void setNameAndSex(String name,String sex){
|
如何创建反射类对象
/**
|
执行之后,输出的内容为:
Reflect.User java.lang.String java.lang.String |
代码中,用到的类型,都是引用类型;
如果是基本类型的包装类型,获取到它的Class对象内容是:
Class btype = Boolean.TYPE; |
输出结果为:
Boolean:boolean Byte:byte Integer:int Float:float Double:double |
获取到对象的构造函数
User user = new User(); |
后天打印输出内容为:
getConstructors:public Reflect.User() getConstructors:public Reflect.User(int,java.lang.String,java.lang.String,java.lang.String) |
上述代码中的getConstructors() 方法,可以获取到“所有”的构造函数,这里的所有并不是真正意义上的所有,而是所有的public类型的构造函数;什么意思?比如:User类中的构造函数:
private User(int id){ |
这个构造函数,我们就无法通过getConstructors 获取到,因为它是私有的;
如果我需要获取到该怎么办呢?
可以使用getDeclaredConstructors()方法,代码如下:
System.out.println("-------------------------获取到私有构造函数--------------------"); |
代码结果如下:
-------------------------获取到私有构造函数-------------------- declaredConstructors:public Reflect.User() declaredConstructors:private Reflect.User(int) declaredConstructors:public Reflect.User(int,java.lang.String,java.lang.String,java.lang.String) -------------------------获取到私有构造函数-------------------- |
如果我想获取到某一个构造函数:
---- 获取到无参构造函数:
final Constructor constructor = userClass.getConstructor(); |
---- 获取到带参构造函数:
Class[] p={int.class,String.class,String.class,String.class}; |
---- 获取到私有构造函数
Constructor declaredConstructor = userClass.getDeclaredConstructor(new Class[]{int.class}); |
如果我想获取到这个构造函数中,可以传递哪些类型的参数:
System.out.println("--------------------------获取到构造函数的类型-------------------------"); Class[] p={int.class,String.class,String.class,String.class};
|
控制台输出内容为:
--------------------------获取到构造函数的类型------------------------- 构造函数类型:int 构造函数类型:java.lang.String 构造函数类型:java.lang.String 构造函数类型:java.lang.String --------------------------获取到构造函数的类型------------------------- |
我已经知道了如何获取到这个对象(或者说是类)的构造函数,我如何利用已经知道的构造函数:去创建对象呢?
User user = new User(); User user1 =(User) constructor1.newInstance(10, "11", "12", "13"); //实例化对象 |
上面调用的是public 类型的构造函数,如果我想通过private 类型的构造函数创建对象,应该如何使用呢?
System.out.println("-------------------------通过私有构造函数创建对象-----------------------"); |
虽然可以使用这种方式来通过private方法来创建对象,但是这样做,会破坏代码的私密性,毕竟人家设置私有构造函数并不是希望外界来做调用的;
后台输出:
-------------------------通过私有构造函数创建对象----------------------- 通过私有化构造函数创建对象:15 -------------------------通过私有构造函数创建对象----------------------- |
获取对象的方法
System.out.println("-------------------------获取到所有方法--------------------"); User user = new User(); |
控制台输出:
-------------------------获取到所有方法-------------------- public java.lang.String Reflect.User.getName() public int Reflect.User.getId() public void Reflect.User.setName(java.lang.String) public void Reflect.User.setSex(java.lang.String) public void Reflect.User.setDescr(java.lang.String) public java.lang.String Reflect.User.getDescr() public void Reflect.User.setId(int) public java.lang.String Reflect.User.getSex() 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() -------------------------获取到所有方法-------------------- |
我们可以看到,获取到的方法中,全部是public;因为Object类是所有类的父类,所以,获取到的方法中,也包含了父类中的public方法;这里测试了一下,如果我向User类中增加方法protected Object clone()方法,这个方法并不能获取到;所以这里的“所有”也并不是全部的方法;
@Override |
如果我想获取到所有的方法,应该怎么做呢?
System.out.println("-------------------------获取到方法(包括私有)--------------------"); User user = new User();
|
PS:有这样一个现象,从一个类中获取到所有的构造函数到获取到所有的方法,调用的方法中都包含有Declared字样,这里先简单的理解成,只要包含有这样的字段,就可以不受权限限制(public private protected 默认);随心所以的获取到指定的构造函数 属性 方法等;
如果我想获取到其中某一个方法,该如何做呢?
Method getName = userClass.getMethod("getName"); |
如果我想获取到带参的方法,该如何做呢?
Method setNameAndSex = userClass.getMethod("setNameAndSex", String.class, String.class); |
如果我想获取私有函数的方法,该如何做呢?
Method setOtherId = userClass.getDeclaredMethod("setOtherId", int.class); |
现在,我已经知道如何获取函数,那么,如果我想调用已经获取到的函数,该如何做呢?
System.out.println("-------------------------调用对象的函数-----------------------"); |
控制台输出内容为:
-------------------------调用对象的函数----------------------- 获取到设置的name:zpy -------------------------调用对象的函数----------------------- |
获取到对象的属性
System.out.println("-------------------------获取到类的所有属性-----------------------"); User user = new User(); |
控制台输出:
public java.lang.String Reflect.User.descr |
和上面提到获取到所有构造函数 和 所有函数的方式一样,只能获取到public类型的属性,如果我想获取到所有的属性,那么我该如何去做呢?
System.out.println("-------------------------获取到类的所有属性(包含私有)-----------------------"); |
控制台输出为:
-------------------------获取到类的所有属性(包含私有)----------------------- 获取到当前字段:private int Reflect.User.id 获取到当前字段:private java.lang.String Reflect.User.name 获取到当前字段:private java.lang.String Reflect.User.sex 获取到当前字段:public java.lang.String Reflect.User.descr -------------------------获取到类的所有属性(包含私有)----------------------- |
现在,我已经能够获取到对应的属性,现在如果我想针对获取到树形赋值,该如何做呢?
User user = new User(); Field name1 = userClass.getDeclaredField("name"); |
控制台输出内容为:
234 |