新手应该了解的反射基本使用

新手应该了解的反射基本使用

前置了解:泛型

泛型

​在Java中的泛型简单来说就是:在创建对象或调用方法的时候才明确下具体的类型

​使用泛型的好处就是代码更加简洁(不再需要强制转换),程序更加健壮(在编译期间没有警告,在运行期就不会出现ClassCastException异常)

1、通过反射调接口

​Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。

​从问题出发:BindBox类里面有有1024个以open开头的函数,每个函数对应返回1~1024的之间的整数且不重复,问哪一个方法返回666?(不可查看源码,源码可能是加密的)

​ 1)、获得类对象,间接通过类对象获得类的相关信息

	  //拿到所有的公共方法(包括从父类继承过来的方法),返回结果是一个数组
	 Method[ ] methods = BindBox.class.getMethods();
	 
	 打印数组
	 for(Method method : methods) {
	 	System.out.println(method);
	 }
	 打印出来的数组:public final int com.ithem.BindBox.open_fhjkalf(long,int)
	 包括的信息有访问修饰符、final、返回值类型、包名、类名、方法名、抛出异常等
	 
	 for(Method method : methods) {
	 	System.out.println(method.getName());//只含有方法名
	 }
	 
	 for(Method method : methods) {
	 	if(method.getName().startsWith("open")){筛选出open打头的方法名
	 		//进一步处理
	 		System.out.println(method.getName());
	 	}	
	 }

​ 2)、调用每一个open方法,查看返回值等不等于666

	method.invoke(null);//执行某个方法,null为能执行的所有方法
	 for(Method method : methods) {
	 	if(method.getName().startsWith("open")){筛选出open打头的方法名
	 		//进一步处理
	 		if(method.invoke(null).equals.(666)){
	 			System.out.println(method.getName());
	 		}	
	 	}	
	 }

①、得到 Class 的三种方式

//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
//  类型的对象,而我不知道你具体是什么类,用这种方法
  Person p1 = new Person();
  Class c1 = p1.getClass();

//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
//  这说明任何一个类都有一个隐含的静态成员变量 class
  Class c2 = Person.class;

//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,class必须是类全名称,返回Class,需要强转为Class<类型>
//   但可能抛出 ClassNotFoundException 异常
  Class c3 = Class.forName("com.ys.reflex.Person");
  or Class<?> cls = Class.forName("com.ys.reflex.Person");

②、通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等

查阅 API 可以看到 Class 有很多方法:

  getName():获得类的完整名字。
  getFields():获得类的public类型的属性。
  getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
  getMethods():获得类的public类型的方法。
  getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
  getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
  getConstructors():获得类的public类型的构造方法。
  getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
  newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

总结:

​Java反射提供了在运行时获取类各个信息的能力,用类加载的方法,把类名、父类、接口、变量、方法、虚方法记录下来。

​在编译器写的代码是 .java 文件,经过javac 编译会变成 .class 文件,class 文件会被JVM装载运行(这里就是真正运行着我们所写的代码(虽然是被编译过的),也就所谓的运行时。

​反射是直接获取加载了方法区的类模板,所以可以拿到整个类的所有东西,看似是打破了封装特性,但实际上反射的真正作用是为了解偶以及实现动态性,所以框架上不用反射不行,否则达不到那种解偶程度和动态性程度。

​要理解反射,需要抛开我们日常写的业务代码。以更高的维度或者说是抽象的思维去看待我们所写的“工具”,所谓的“工具”:在单个系统使用叫做“Utils”、被多个系统使用打成jar包叫做“组件”、组件继续发展壮大就叫做“框架”,一个好用的“工具”是需要兼容各种情况的。

​例如SpringMVC 你在方法上写上对象,传入的参数就会帮你封装到对象上,Mybatis可以让我们只写接口,不写实现类,就可以执行SQL。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值