java的反射
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java的反射相关的知识,希望对你有一定的参考价值。
2017年 3月11号 周六 晴
前言:理解java的反射能更好的理解spring的运行机制。
因为spring的两大核心技术是Ioc(Inversion of Control,控制反转,有时也称为依赖注入,即DI,Dependcy Injection)和AOP(Aspect Oriented Programming,面向切面编程,即纵向的编程)。Ioc实现原理是java反射机制,Aop实现原理是java的动态代理。
java的反射机制概念:
java的反射机制是运行状态中,对于任意一个类,都能够知道此类的所有属性和方法,对于任意一个对象,都能调用该对象的任意一个方法和属性。这种动态获取信息及动态调用对象方法即为java的反射机制。
java反射机制主要提供以下功能
1 在运行时判断任意一个对象所属的类
2 在运行时构造任意一个类的对象
3 在运行时判断任意一个类所具有的成员变量和方法
4 在运行是调用任意一个对象的方法
5 生成动态代理
在jdk中,主要由以下类来实现java的反射机制,这些类都位于java.lang.reflect包中。
Class:表示正在运行的java应用程序中的类和接口。Class类是java反射中最重要的一个功能类,所有获取对象信息(包括方法,构造方法,访问权限)都由它来实现
Field:提供有关类或接口的属性信息,以及对它的动态访问权限
Constructor:提供关于类的单个构造方法的信息以及对它的访问权限
Method:提供关于类或接口中某个方法信息
Array类:提供动态创建数组,以及访问数组元素的静态方法
在java.lang.Object类中定义了getClass()方法,因此对于任意一个java对象,都可以通过此方法获取对象类型。
Class类是Reflection API中的核心类,它有一下方法:
1 获取对象类型
a getName():获取类的完整名字
b getFields():获得类的public类型的属性
c getDeclareFields():获得类的所有属性
d getMethods():获得类的public类型的方法
e getDeclaredMethods():获取类的所有方法
f getMethod(String name,Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数的构造方法。
g getConstrutors():获得类的public类型的构造方法
h newInstance():通过类的不带参数的构造方法创建这个类的一个对象
2 通过默认构造方法创建一个新的对象
Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
此代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例
3 获得对象的所有属性
Filed fileds[]=classType.getDeclareFields();
Class类的getDeclaredFields()方法返回类的所有属性,包括public,protected,default(默认)和private访问级别的属性
4 获得每个属性响应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性复制到新对象中。典型代码如下:
for(int i=0;i Field field=fields[i];
String filedName=field.getName();
String firstLetter=fieldName.substring(0,1).toUpperCase();
String getMethodName="get"+firstLetter+fieldName.substring(1);//获得和属性对应的getXXX()方法名字
String setMethodName="set"+firstLetter+fieldName.substring(1);//获得和属性对应的setxxx()方法的名字
Method getMethod=classType.getMethod(getMethodName, new Class[]{});//获得和属性对应的getxxx()方法
Method setMethod=classType.getMethod(setMethodName, new Class[]{field.getType()});//获得和属性对应的setxxx()方法
Object value=getMethod.invoke(object,new Object[]{});//调用原对象的getXXX()方法
System.out.println(fieldName+":"+value);
setMethod.invoke(objectCopy,new Object[]{value});}
Method类的invoke(Object obj,new Object args[])方法接收的参数必须为对象,如果参数的基本类型数据,必须转换成相应包装类型的对象。
Invoke()方法的返回值总是对象,如果实际被调用的方法的返回值类型是基本类型数据,那么invoke()方法会把它转换为相应的包转类的对象,再将其返回
java.lang.Array类提供了动态创建和访问数组元素的各种静态方法。如下所示代码的ArrayTester1类的main()方法创建一个长度为10的字符串数组,接着把索引位置为5的元素设为hello,然后在读取索引位置为5的元素的值。
import java.lang.reflect.Array; public class ArrayTest1 { public static void main(String[] args) throws Exception { Class classType = Class.forName("java.lang.String"); //创建一个长度为10的字符串数组 Object array = Array.newInstance(classType, 10); //把索引位置为5的元素设置为hello Array.set(array, 5, "hello"); //读取索引位置为5的元素的值 String s = (String) Array.get(array, 5); System.out.println(s); } }
关于java反射机制中的应用简单例子
例子1:通过对象获取完整的包名和类名
package qianyu.com; class Hello{ public void say(){ System.out.println("hello,Everyone"); } } public class Demo1 { public static void main(String[] args) { Demo1 demo = new Demo1(); System.out.println("demo:"+demo.getClass()); System.out.println("demo:"+demo.getClass().getName()); Hello hello = new Hello(); System.out.println("hello:"+hello.getClass()); System.out.println("hello:"+hello.getClass().getName()); } }
运行结果如下:
demo:class qianyu.com.Demo1
demo:qianyu.com.Demo1
hello:class qianyu.com.Hello
hello:qianyu.com.Hello
如上所示:通过java的反射机制,可以在运行过程中获取对象完整的路径,实际上,在java中所有类的对象其实都是Class的实例
例子2:实例化Class类对象
package qianyu.com; class Hello1{ public void say(){ System.out.println("hello,Everyone"); } } public class Demo2 { public static void main(String[] args) { Class<?> demo1=null; Class<?> demo2=null; Class<?> demo3=null; Class<?> demo4=null; try { demo1 = Class.forName("qianyu.com.Demo2"); } catch (ClassNotFoundException e) { e.printStackTrace(); } demo2 = new Demo2().getClass(); demo3=Hello.class; demo4=Hello1.class; System.out.println("本代码中Demo2类名称"+demo1.getName()); System.out.println("本代码中Demo2类名称"+demo2.getName()); System.out.println("同一个包中hello类名称"+demo3.getName()); System.out.println("本代码中hello1类名称"+demo4.getName()); } }
运行结果如下:
本代码中Demo2类名称qianyu.com.Demo2
本代码中Demo2类名称qianyu.com.Demo2
同一个包中hello类名称qianyu.com.Hello
本代码中hello1类名称qianyu.com.Hello1
以上是关于java的反射的主要内容,如果未能解决你的问题,请参考以下文章