记得之前写了一篇 JSON 转实体的文章, 里面就用到了 java 反射的文章, 但是当时只是了解到反射这个知识点, 并没有深入的了解, 寒假闲来无事觉顶深入整理一下 java 反射的知识, 一下都是个人学习反射的总结, 不到之处, 还望大神指点!!!
反射顾名思义就是和 java 编译相反的过程, 这里实现的效果就是通过类名来进行实例化类对象并对类进行操作. 具体看下
获取父类和所有的接口
首先我们的 java 类是可以继承和实现多个接口的, 那么我们如何通过 java 反射获取 java 类的父类和接口呢?
首先我们在这里新建一个 Annimal 作为父类
- public class Annimal {
- private String AnnimalName;
- public void eat(){
- System.out.println("Annimal is eatting");
- }
- public void run(){
- System.out.println("Annimal is running");
- }
- }
然后再新建一个 Behaviour 接口
- public interface Behaviour {
- public String haviour="test";
- public void sayHello();
- public void isAngury();
- public void love();
- }
现在让我们新建一个 Dog 类并让 Dog 类继承 Annimal 类并实现 Behavour 这个接口
public class Dog extends Annimal implements Behaviour
Dog 源码
- public class Dog extends Annimal implements Behaviour{
- private String dogName;
- public void fuck(String name){
- System.out.println("fuck To :"+name);
- }
- @Override
- public void sayHello() {
- // TODO Auto-generated method stub
- System.out.println("Dog sayHello");
- }
- @Override
- public void isAngury() {
- // TODO Auto-generated method stub
- System.out.println("Dog isAngury");
- }
- @Override
- public void love() {
- // TODO Auto-generated method stub
- System.out.println("Dog love");
- }
- }
测试
下面我们开始进行测试, 首先我们通过 Class 类来获取类的 class 对象
Class<?> target=Class.forName("tom.change.Reflect. 获取父类和所有接口. Dog");
然后通过 getSuperClass 和 getInterfaces 这两个方法就可以获取到父类和所有的接口
- // 获取 Dog 类的父类
- Class<?> parent=target.getSuperclass();
- // 获取该类继承的所有类
- Class<?> intefaces[]=target.getInterfaces();
最后看程序运行的效果图
获取所有的属性 (getDeclaredFields)
在 Java 类中出了类与类中关系, 每个类还有具有特定的属性, 那么我们如何通过反射来获取 Java 类中的属性呢. 下面我写了一个 user 类, 其中的属性为
Dog 类:
private String dogName;
那么下面我们来试试到底能不能获取上面的几个属性. 同样通过类路径获取 class 对象
Class<?> clazz=Class.forName("tom.change.Reflect. 获取父类和所有接口. Dog");
然后通过 class 对象的 getDeclaredFields 方法获取本地类的属性, 这个方法是无法获取继承父类和接口中的属性, 如果非要获取你可以先通过该类获取到父类, 然后在去获取父类的 class 对象, 在去获取父类中属性.
- for (int i = 0; i <fields.length; i++) {
- // 获取字段的修饰权限符
- System.out.println(Modifier.toString(fields[i].getModifiers())+"@@@"+fields[i].getName());
- }
这里说一下, 获取后用 Field 来接受, 这个类 getModifiers 是获取该属性的属性的, 私有还是公共还是保护的.
这里获取字段后, 通过 Field 的 set 方法就可以给属性设置, 不管属性的对外状态. 前提是开启权限
- field.setAccessible(true);
- field.set(object, "21131084");
这里的 object 是 class 的一个实例化对象
获取类中的所有的方法 (getMethods)
在上面我们已经获取了类中所有的属性, 那么下面我们自然就是获取类中的所有的方法了. 同样的步骤上面已经有了, 这里不赘述了, 只不过和上面的不同的地方就是获取 class 对象后我们调用 getMethods 方法.
public void tom.change.Reflect. 获取父类和所有接口. Dog.fuck(java.lang.String)
public void tom.change.Reflect. 获取父类和所有接口. Dog.sayHello()
public void tom.change.Reflect. 获取父类和所有接口. Dog.love()
public void tom.change.Reflect. 获取父类和所有接口. Dog.isAngury()
public void tom.change.Reflect. 获取父类和所有接口. Annimal.run()
public void tom.change.Reflect. 获取父类和所有接口. Annimal.eat()
- 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 final void java.lang.Object.wait() 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()
大家有没有疑问, 为什么有一些莫名的方法出现, 有些方法甚至我们的 Dog 和继承类中都没有出现过, 这是怎么回事呢. 首先 getMethods 获取类本身的方法这是肯定的. 继承的类我们也是可以获取的, 这就解释了为什么我们的获取方法中有 Annimal 类中的方法,. 那么后面那些 Object 类的方法是哪里来的呢, 大家还记得吗所有的类都是继承 Object 类的.
类中方法的调用 (getMethod)
在上面我们获取了方法后, 通过 getMethod 获取指定的方法, 该方法返回的是 Method 对象, 然后通过 Method 里的 invoke 方法调用指定的方法. 在调用的时候需要传入 class 实力化对象, 有参数的话我们还需要传入参数.
public Object invoke(Object obj, Object... args)
源码显示, 方法需要参数有多少这里就传入多少, 这里是通用的.
在通过 getMethod 获取 Method 的时候我们需要传入方法参数的类型
- ```
- public Object invoke(Object obj, Object... args)
- ```
- ```
- public Method getMethod(String name, Class<?>... parameterTypes)
- ```
获取所有构造函数 (getConstructors)
Java 类中最后应该还剩下构造函数了, 既然是反射, 我们就要将类反射的干干晶晶的. 获得 class 对象后我们通过 getConstructors 获取构造函数, 该方法返回的是 Constructor 集合. 在 Constructor 类中 getParameterTypes 获取构造函数中的参数, 有个这个我们就可以自己进行类的构造了.
总结
到这里我们的反射已经完全可以操作一个类了. 有人会问这有啥意思呢, 在我们 Javaweb 中, 哪些知名的框架源码里必须有反射, 通过反射我们能够实现注解这个功能. 当然注解还有其他知识, 以后知道在介绍. 再比如说我们将 map 与实体进行映射这里就需要反射区获取 Java Bean 中的属性并将 map 的值赋值. 不管怎么样, 反射是我们 Java 的重要知识, 学会它对自己以后的架构方面试有很大的帮助的.
源码下载
加入战队
# 加入战队
微信公众号
来源: https://www.cnblogs.com/zhangxinhua/p/11495412.html