反射:一个类有多个部分组成,如:成员变量,方法,构造方法等。
反射就是加载类,并解刨出类的各个组成部分。
加载类:forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装(常用)
另外两中得到class对象的方式: 类名.class ; 对象.getClass
解刨类:Class对象提供了如下常用方法:
用于public访问权限
Public Constructor getConstructor(Class<?>..parameterTypes)
Public Method getMethod(String name,Class<?>...parameterTypes)
Public Field getField(String name)
用于private私有访问权限
Public ConstructorgetDeclaredConstructor(Class<?>..parameterTypes)
Public Method getDeclaredMethod(String name,Class<?>...parameterTypes)
Public Field getDeclaredField(String name)
下面用一些例子来具体的理解一下:反射构造函数、反射方法、反射字段。
例子看着比较多,但都比较简单,大同小异,只是有点细节需要注意!
用 JUnit Test 测试运行
Person.java
import java.io.InputStream;
import java.util.List;
public class Person {
//反射类字段(平常说的属性)
public String name="JAVA";
private int password=123456;
private static int age=18;
//反射类的构造函数
public Person()
{
System.out.println("无参数");
}
public Person(String name)
{
System.out.println("String name");
}
public Person(String name,int age)
{
System.out.println(name+"..."+age);
}
private Person(List list)
{
System.out.println("list");
}
//反射类的方法
public void meth()
{
System.out.println("无参方法");
}
public void meth(String name,int age)
{
System.out.println(name+"..."+age);
}
private void meth(InputStream in)
{
System.out.println(in);
}
public static void meth(int num)
{
System.out.println(num);
}
public Class[] meth(String name,int[] age)
{
return new Class[]{String.class};
}
public static void main(String args[])
{
System.out.println("main函数");
}
}
loadClassTest.java(反射构造函数)
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List; //和Person中导入的包要一致
import org.junit.Test;
//反射类的构造函数,创建类对象
public class loadClassTest {
//反射构造函数:public Person()
@Test
public void test1() throws Exception
{
Class clazz=Class.forName("com.yong.reflect.Person");//获得路径,加载类到内存中
Constructor c=clazz.getConstructor(null); //解析无参的构造函数,并得到对象,括号内为可变参数
Person p=(Person) c.newInstance(null);//调用构造函数创建Person对象
System.out.println(p.name); //打印结果: 无参数 JAVA
}
//反射构造函数:public Person(String name)
@Test
public void test2() throws Exception
{
Class clazz=Class.forName("com.yong.reflect.Person");
Constructor c=clazz.getConstructor(String.class);
Person p=(Person) c.newInstance("创建Person(String name)对象");
System.out.println(p.name); //打印结果:String name JAVA
}
//反射构造函数:public Person(String name,int age)
@Test
public void test3() throws Exception
{
Class clazz=Class.forName("com.yong.reflect.Person");
Constructor c=clazz.getConstructor(String.class,int.class);
Person p=(Person) c.newInstance("XXXXX",11);
System.out.println(p.name); //打印结果: XXXXX...11 JAVA
}
//反射构造函数:private Person(List list)
@Test
public void test4() throws Exception
{
Class clazz=Class.forName("com.yong.reflect.Person");
//因为该构造方法私有,因此需要用getDeclaredConstructor方法
Constructor c=clazz.getDeclaredConstructor(List.class);
//暴力反射:无论你是什么权限,都给你打开,让外界访问
//私有方法外界不能访问,但反射可以!
c.setAccessible(true);
Person p=(Person) c.newInstance(new ArrayList());
System.out.println(p.name); //打印结果: list JAVA
}
//创建对象的另一种途径
//test5的代码等效于test1
@Test
public void test5() throws Exception
{
Class clazz=Class.forName("com.yong.reflect.Person");
Person p=(Person) clazz.newInstance();
System.out.println(p.name); //打印结果: 无参数 JAVA
}
}
reflectMethod.java(反射方法)
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import org.junit.Test;
//反射类的方法
public class reflectMethod {
@Test
//反射类的方法public void meth()
public void method1() throws Exception
{
Person p=new Person();
Class clazz=Class.forName("com.yong.reflect.Person");
Method method=clazz.getMethod("meth", null);
method.invoke(p, null);//用invoke让方法跑起来,前面的参数为调用的对象,后面的参数为对象的参数
//打印结果:无参数 无参方法 在创建p对象的时候打印无参数
//上一句,调用的meth方法,打印的 无参方法
}
@Test
//反射类的方法public void meth(String name,int age)
public void method2() throws Exception
{
Person p=new Person();
Class clazz=Class.forName("com.yong.reflect.Person");
Method method=clazz.getMethod("meth", String.class,int.class);
method.invoke(p, "流年",90); //打印结果:无参数 流年...90
}
@Test
//反射类的方法private void meth(InputStream in)
public void method3() throws Exception
{
Person p=new Person();
Class clazz=Class.forName("com.yong.reflect.Person");
Method method=clazz.getDeclaredMethod("meth", InputStream.class);//private权限,需要暴力打开
method.setAccessible(true);
method.invoke(p, new FileInputStream("c:\\temp.txt")); //c盘目录下要有此文件
//打印结果:无参数 java.io.FileInputStream@1e59128
}
@Test
//反射类的方法public static void meth(int num)
public void method4() throws Exception
{
//注意:静态方法在调用时不需要对象!!!!!!
//因此不需要创建对象,下面invoke的第一个参数也不需要传入参数!!!!
Class clazz=Class.forName("com.yong.reflect.Person");
Method method=clazz.getMethod("meth",int.class);
method.invoke(null,10086); //打印结果:10086
}
@Test
//反射类的方法public Class[] meth(String name,int[] age)
public void method5() throws Exception
{
Person p=new Person();
Class clazz=Class.forName("com.yong.reflect.Person");
Method method=clazz.getMethod("meth",String.class,int.class);
method.invoke(p, "Class数组",89); //打印结果:无参数 Class数组...89
}
@Test
//反射类方法:public static void main(String args[])
public void method6() throws Exception
{
Class clazz=Class.forName("com.yong.reflect.Person");
Method method=clazz.getMethod("main",String[].class);
//method.invoke(null,new String[]{"bb","aa"}); 报错!!!
/* JDK1.5升级后为了兼容JDK1.4所带来的问题:
*JDK1.4: invoke会从数组中取出多个值,将一个个的值取出后(将数组拆成一个个的值),
*在赋予到数组的参数上面去,因为传递的数组中是两个值,所以main方法应该是
* main(String a1,String a2),但main函数中main(String args[])是一个数组,
* 所以需要将整个数组看做一个整个的参数(下面那种写法)
*/
method.invoke(null,new Object[]{new String[]{"bb","aa"}}); // 打印结果:main函数*/
}
}
reflectionField.java(反射字段)
import java.lang.reflect.Field;
import org.junit.Test;
//反射字段
public class reflectionField {
@Test
//反射字段 public String name="JAVA";
public void test1() throws Exception
{
Person p=new Person();
Class clazz=Class.forName("com.yong.reflect.Person");
Field f=clazz.getField("name");
String name=(String) f.get(p);//获得对象中的字段
System.out.println(name); //打印结果:无参数 JAVA
Class type=f.getType();
System.out.println(type); //打印出name的类型:class java.lang.String
//重新设置字段的值
f.set(p, "XXXXXXXXX");
System.out.println(p.name); //打印结果:XXXXXXXXX
}
@Test
//反射字段 private int password=123456;
public void test2() throws Exception
{
Person p=new Person();
Class clazz=Class.forName("com.yong.reflect.Person");
Field f=clazz.getDeclaredField("password");
f.setAccessible(true);
System.out.println(f.get(p)); //打印结果:无参数 123456
}
@Test
//反射字段 private static int age=18;
public void test3() throws Exception
{
Person p=new Person();
Class clazz=Class.forName("com.yong.reflect.Person");
Field f=clazz.getDeclaredField("age");
f.setAccessible(true);
System.out.println(f.get(p)); //打印结果:无参数 18
}
}