反射是什么?
一个类有多个组成部分,例如,构造函数(创建对象,完成对象初始化),成员变量(封装数据),方法(执行功能)。反射就是加载类,并反射出类的各个组成部分;
1、加载类,获取类的字节码可以通过三种形式来获取
Class cl=Class.forName("com.java.xiong.reflet0301.Person");
Class cl1=new Person().getClass();
Class cl2=Person.class;
2、通过获取得到类的字节码之后就可以来反射类:通过Class对象如下的几个方法可以获取类的构造函数,成员变量与方法
Constructor<T> | getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法 |
Constructor<T> | getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法 |
Field | getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 |
Field | getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 |
Method | getMethod(String name,Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 |
Method | getDeclaredMethod(String name,Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 |
实例:
package com.java.xiong.reflet0301;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
public class Test1 {
//反射类的构造函数
//无参构造函数
@Test
public void test() throws Exception{
//获取Class对象
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
//获取类构造函数的对象
Constructor<?> cons=cl.getConstructor();
//获取类的对象
Person person=(Person)cons.newInstance();
System.out.println(person.aa);
}
//带参数的构造函数
@Test
public void test1() throws Exception{
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
//构造函数传入参数的参数类型
Constructor<?> cons=cl.getConstructor(String.class);
//构造函数的参数的值
Person person=(Person)cons.newInstance("xiong");
System.out.println(person.aa);
}
@Test
public void test2()throws Exception{
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
Constructor<?> cons=cl.getConstructor(String.class,int.class);
Person person=(Person)cons.newInstance("xiong",23);
System.out.println(person.aa);
}
//反射类的方法
@Test
public void fc()throws Exception{
//获取Class对象
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
//获取方法的对象
Method method=cl.getMethod("fc");
//执行方法
method.invoke(new Person());
}
@Test
public void fc1()throws Exception{
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
//第一个参数表示方法名 后面的可变参数表示 方法中的参数的参数类型
Method method=cl.getMethod("fc", String.class,int.class);
//一个表示执行者的对象 后面的可变参数表示方法的参数值
method.invoke(new Person(), "xiong",23);
}
@Test
public void fc2()throws Exception{
Class<?>cl=Class.forName("com.java.xiong.reflet0301.Person");
Method method=cl.getMethod("fc", String.class);
//获取方法的返回值
Object []invoke =(Object[]) method.invoke(new Person(),"xiong");
System.out.print(invoke[0]);
}
@Test
public void fc3()throws Exception{
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
//调用类的私有方法用getDeclaredMethod
Method method=cl.getDeclaredMethod("privatefc");
System.out.println(method.getName());
//method.invoke(new Person()); 类私有方法不能执行
method.setAccessible(true);//获取私有访问权限
method.invoke(new Person());
}
@Test
public void fc4()throws Exception{
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
Method method=cl.getMethod("arr", String[].class);
//当反射类的方法的参数是数组时 需要特别的注意
//因为在jdk1.4的时候 当方法有多个参数aa(String a,String b)时 invoke()的方法是invoke(new Person(),new []Object{"a","b"}) 这个Object
//就是表示两个参数 a和b的值 所以jdk1.5时为了兼容1.4 当方法的参数是数组时也是拆开来传入的
//两种方法来解决这个问题
method.invoke(new Person(),new Object[]{new String[]{"1","2"}});
method.invoke(new Person(),(Object)new String[]{"1","2"});
}
//反射类的成员变量
@Test
public void bl()throws Exception{
Person person=new Person();
Class<?> cl=Class.forName("com.java.xiong.reflet0301.Person");
//获取字段
Field file=cl.getField("aa");
Field files=cl.getField("A");
Class<?> types=file.getType();//获取字段的类型
if(types.equals(String.class)){
//获取那个类的对象的字段
String str1=(String)file.get(person);
System.out.println(str1);
file.set(person, "file");
System.out.println(person.aa);
String str2=(String)file.get(person);
System.out.println(str2);
}
System.out.println(files.get(person));
}
}
package com.java.xiong.reflet0301;
public class Person {
public String aa="aa";
public static final int A=1;
//构造函数
public Person(){
System.out.println("Person()");
}
public Person(String name){
System.out.println("Person(String name) name :"+name);
}
public Person(String name,int age){
System.out.println("Person(String name,int age)"+" name:"+name+" age:"+age);
}
//方法
public void fc(){
System.out.println("fc()");
}
public void fc(String name,int age){
System.out.println("fc(String name) name:"+name +"age:"+age);
}
public String [] fc(String name ){
return new String[]{name};
}
private void privatefc(){
System.out.println("privatefc()");
}
public void arr(String []arg){
System.out.println("arr(String []arg)");
}
}