Java 反射

1 什么是反射
反射机制允许程序在运行时透过Reflection 相关的API取得任何class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现interfaces(例如Serializable),Exceptions等,也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods。

2 反射的应用场景
1)IoC:IoC通过反射技术将xml配置文件中的信息注入到JavaBean中。
2)自动的在两个POJO间赋值,比如在VO和PO之间自动赋值。
3)将实现类放到配置文件中,然后读取配置文件通过反射机制实例化配置的实现类。开发时提供一个接口,实现类由使用者实现,也就是运行时才知道具体的实现类是谁。
4)ORM框架:ORM框架读取ResultSet对象,然后通过反射机制来构造返回的对象。
5)JUnit:JUnit也使用反射来获取测试类方法列表。

3 反射示例相关的类

public interface IHello {
public void sayHello() throws Exception;
public void sayHello(String greeting) throws Exception;
}


public class Hello extends SuperHello implements IHello{
// private Hello(){}
private String name;
private int value;
private int[] array;
private Map<String,Integer> map ;
public String publicFiled;

public Hello(){}
public Hello(String name,int value){
this.name = name;
this.value = value;
}

public void sayHello() throws Exception {
System.out.println("hello");
}

public void sayHello(String greeting) throws Exception {
System.out.println("hello"+greeting);
}
private void privateSayHello(){
System.out.println("private hello");
}
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}
public String toString(){
return "name="+name+",value="+value;
}
}

public class SuperHello {
private String privateSuperField;
protected String protectedSuperField;
public String publicSuperFiled;
private void privateSuperMethod(){

}
protected void protectedSuperMethod(){

}
public void publicSuperMethod(){

}
}


4 获取类名和类加载器名称
Hello hello = new Hello();
System.out.println(hello.getClass().getName());
System.out.println(hello.getClass().getClassLoader().getClass().getName());

输出:
org.frank1234.reflect.Hello
sun.misc.Launcher$AppClassLoader //属于应用类加载器


5 获取Class类型的对象
Class clazz1 = Class.forName("org.frank1234.reflect.Hello");
Class clazz2 = Hello.class;
Class clazz3 = new Hello().getClass();


6 实例化
Class clazz = Hello.class;
Hello hello = (Hello)clazz.newInstance();
hello.setName("frank1234");
System.out.println(hello);

输出结果:
name=frank1234,value=0


7 获取接口
Class clazz = Hello.class;
Class[] interfaces = clazz.getInterfaces();
for(int i=0;i<interfaces.length;i++){
System.out.println(interfaces[i].getName());
}

输出:
org.frank1234.reflect.IHello

8 获取超类
Class clazz = Hello.class;
Class superClazz = clazz.getSuperclass();
System.out.println(superClazz.getName());


输出:
org.frank1234.reflect.SuperHello


9 获取属性
9.1 getFields和 getDeclaredFields
Class clazz = Hello.class;
Field[] fields = clazz.getFields();
for(int i=0;i<fields.length;i++){
System.out.println(fields[i].getName());
}
System.out.println("----------------");
Field[] declaredFields = clazz.getDeclaredFields();
for(int i=0;i<declaredFields.length;i++){
System.out.println(declaredFields[i].getName());
}

输出结果:
publicFiled
publicSuperFiled
----------------
name
value
protectedField
publicFiled

由此可见通过子类的clazz.getFields()可以获得父类的public属性,子类的public属性, 并不能获取它继承自父类的protected属性。
通过子类的clazz.getDeclaredFields()可以获取子类的全部修饰符的属性,包括private ,protected以及public类型的,但是不能获取从父类继承的属性。


9.2 getField
Class clazz = Hello.class;
Field field = clazz.getDeclaredField("name");
//获取类型
System.out.println(field.getType().getName());
//获取修饰符
System.out.print(Modifier.toString(field.getModifiers()));


输出:
java.lang.String
private

9.3 操作属性
Class clazz = Hello.class;
Hello hello = (Hello)clazz.newInstance();
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
field.set(hello,"frank1234");
System.out.println(hello);

输出结果:
name=frank1234,value=0


10 获取方法
10.1 获取方法
Class clazz = Hello.class;
Hello hello = (Hello)clazz.newInstance();
//获取不带参数的方法
Method method = clazz.getMethod("sayHello");
method.invoke(hello);
//获取方法的修饰符
System.out.println(Modifier.toString(method.getModifiers()));
//获取带参数方法
Method paramMethod = clazz.getMethod("sayHello",new Class[]{String.class});
paramMethod.invoke(hello,new Object[]{" frank1234"});
//获取方法的入参
Class[] classes = paramMethod.getParameterTypes();
for(int i=0;i<classes.length;i++){
System.out.println(classes[i].getName());
}
//获取方法的出参
System.out.println(paramMethod.getReturnType());

输出结果:
hello
public
hello frank1234
java.lang.String
void

10.2 getMethods和getDeclaredMethods
同getDeclaredFields和getFields的区别相同

10.3 调用getter和setter
Class clazz = Hello.class;
Hello hello = (Hello)clazz.newInstance();
String filedname = "name";
//构造settter和getter方法名称
String setterMethodName = "set" + filedname.substring(0,1).toUpperCase()+filedname.substring(1,filedname.length());
String getterMethodName = "get" + filedname.substring(0,1).toUpperCase()+filedname.substring(1,filedname.length());
//获取setter方法,并赋值
Method setterMethod = clazz.getMethod(setterMethodName,String.class);
setterMethod.invoke(hello,"frank1234");
//获取getter方法,并获取返回值
Method getterMethod = clazz.getMethod(getterMethodName);
String name = (String)getterMethod.invoke(hello);
System.out.print(name);

输出结果:
frank1234


11获取构造方法
11.1 获取构造方法并实例化

Class clazz = Hello.class;
//获取默认构造方法,并实例化
Constructor constructor = clazz.getConstructor();
Hello hello = (Hello)constructor.newInstance();
System.out.println(hello);
//获取带参数的构造方法,并实例化
Constructor constructorParam = clazz.getConstructor(String.class,int.class);
Hello helloparam = (Hello)constructorParam.newInstance("frank1234",20);
System.out.println(helloparam);

输出结果:
name=null,value=0
name=frank1234,value=20

11.2 调用私有构造方法
同操作私有属性一样,需要先设置setAccessible(true);才可以调用

13 获取异常
Class clazz = Hello.class;
Method method = clazz.getMethod("sayHello");
for (Class<?> exception : method.getExceptionTypes()) {
System.out.print(exception.getName());
}

输出结果:
java.lang.Exception


14 数组
Class clazz = Hello.class;
Hello hello = (Hello)clazz.newInstance();
Field field = clazz.getDeclaredField("array");
System.out.println(field.getType());
System.out.println(field.getType().getComponentType());

输出结果:
class [I
int

15 获取泛型类型
Class clazz = Hello.class;
Field mapField = clazz.getDeclaredField("map");
Type mapMainType = mapField.getGenericType();
if (mapMainType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)mapMainType;
// 获取基本类型信息,即Map
Type basicType = parameterizedType.getRawType();
System.out.println(basicType);
// 获取泛型类型的泛型参数
Type[] types = parameterizedType.getActualTypeArguments();
for (int i = 0; i < types.length; i++) {
System.out.println("泛型类型是:"+types[i]);
}
} else {
System.out.println("获取泛型类型出错!");
}

输出:
基本类型为:interface java.util.Map
泛型类型是:class java.lang.String
泛型类型是:class java.lang.Integer


16 getTypeParameters
TypeVariable[] tValue = List.class.getTypeParameters();
for(TypeVariable value:tValue){
System.out.println(value.getName());
}
TypeVariable[] map = Map.class.getTypeParameters();
for(TypeVariable value:map){
System.out.println(value.getName());
}

输出:
E
K
V
见List和Map的接口定义:
public interface List<E> extends Collection<E>
public interface Map<K,V>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值