框架的基石:Java反射

本文是 Java 基础系列的第一篇,关于 Java 反射的学习。在我们所熟知的各种框架中,都必须基于这门技术。而且在工作中,我们也会手动去封装一些功能或者改写一些第三方的功能,这时候熟悉掌握反射是必须的过程。希望这篇文章能帮到各位小伙伴,如有错误,还望指正。

反射的定义
  • 反射是对类本身进一步抽象而来的。抽象是面向对象的一大特性,我们在开发中,会对某些业务属性进行抽象,但是我们有没有想过,类本身也是可以继续抽象的,类们都有包名、属性、构造器和方法等等一些共有的东西,那么可以把他们再进一步的抽象出来。再进一步而言,Class 类是对 .class 文件字节码的抽象,而类中的方法、属性是单独各自成为一个类的。字节码文件对应着 java 原文件,改变字节码就意味着从根本上改变了对应的类。
  • 先有Class,才能有类中的方法、属性等等。Class 描述类本身,Feild 类中属性,Method 类中方法,Constructor类中构造器,Annotation类中注解,Package 类所属的包。
    在这里插入图片描述
反射的具体使用
1. 三种方式获取 Class
  • 通过全类名:
// 注意 class 是关键字
Class clazz = Class.forName("包名.类名");
  • 如果不知道全类名,可以类名.class获取:
Class clazz = 类名.class;
  • 在 java 中我们通常能看到某些对象的创建是通过工厂模式或者其他的不是直接 new 对象来创建的出来的,在接收该对象的时候,可能使用的父类接收,所以我们没办法直接通过上述两种方式获取到Class。那我们可以用以下这种方式获取:
Class clazz = 对象.getClass();
2. 用Class对象获取类信息

如类:

package cn.joncy.reflect;

public class Hero extends Person implements A{
   	private String name;
    public int age;

    public String toString(){
        return 	name+","+age;
    }
}
  • 获取该类的修饰符
int modifiers = clazz.getModifiers();  // modifiers = 1
  • 获取类名
String name = clazz.getName();	// cn.joncy.reflect.Hero
String simpleName = clazz.getSimpleName();	// Hero
  • 获取包名
Package p = clazz.getPackage();	// cn.joncy.reflect
  • 获取父类
Class sclass = clazz.getSuperclass();	// cn.joncy.reflect.Person
  • 获取所有的父接口
Class[] classes = clazz.getInterfaces();
for(Class c:classes){
    System.out.println(c.getName());  // cn.joncy.reflect.A
}
  • 获取默认无参构造方法创建对象
Class clazz = Class.forName("cn.joncy.reflect.Hero");
Hero hero = (Hero) clazz.newInstance();		//默认调用无参数构造方法创建对象
  • 获取类中属性
// 只能获取公有的属性,但是包含继承过来的父类属性
Field nameField = clazz.getField("name");
int modifiers = nameField.getModifiers();//属性的修饰符 1
Class fclass = nameField.getType();//获取属性的类型 int
String fname = nameField.getName();//获取属性名字 age

// 只能获取公有的和私有的属性,但是只能获取本类中的属性
Field f = clazz.getDeclaredField("name");// name
3. 操作类属性
Hero hero = (Hero)clazz.newInstance();
Field f = clazz.getDeclaredField("name");//name名字
// 设置
f.setAccessible(true);
f.set(hero, "jc");
// 获取
String name = (String) f.get(hero);
4. 操作类方法
  • 获取方法中的描述
int mm = m.getModifiers();	// 修饰符
Class mrt = m.getReturnType();	// 返回值类型
String mn = m.getName();	// 方法名字
Class[] mpts = m.getParameterTypes();	// 参数列表
Class[] mets = m.getExceptionTypes();	// 异常类型
  • 反射执行某个方法
Class clazz = Hero.class;
Hero h = (Hero)clazz.newInstance();
Method m = clazz.getMethod("test2",String.class);
String result = (String)m.invoke(h,"参数1");

Method m = clazz.getDeclaredMethod("test1");	//获取本类中的私有或公有方法
System.out.println(m.getName());	// 获取方法名字
m.setAccessible(true);	// 设置使用权
m.invoke(p);	
  • 获取所有公有的方法,包括父类
Method[] ms = clazz.getMethods();
5. 操作构造方法
  • 获取构造器的描述
Constructor con = clazz.getConstructor();
Constructor[] cons = clazz.getConstructors();
clazz.getDeclaredConstructor();
clazz.getDeclaredConstructors();
con.getModifiers(); // 修饰符
con.getName();	// 名字
con.getParameterTypes();	// 参数类型
con.getExceptionTypes();	// 	异常类型
  • 反射创建对象
Constructor con = clazz.getConstructor(String.class);
con.setAccessible(true);
Hero h = (Hero)con.newInstance("name");
反射的案例
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值