首先我们需要知道什么是反射?反射是用来干什么的。
答:一个类有多个组成部分,反射就是加载类,并解析出类的各个组成部分。一般在框架中才会使用反射技术。反射技术是一种打破了常规的私有方法不能被外部访问的特例。但是调用私有方法或字段必须用setAccessible(true)方法,即暴力反射。
接下来看代码部分来讲解反射的一些常用的用法。反射函数,反射字段,反射技术创建对象。
首先是一个要发射的类Person,代码如下
package Day01;
import java.util.List;
public class Person {
private String name="zhangsan";
private int age;
public Person(){
System.out.println("无参构造方法被调用了");
}
public Person(String name,int age){
this.name=name;
this.age=age;
System.out.println("name="+name+"age="+age);
}
private Person(List list){
System.out.println("list方法被调用了");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void sing(){
System.out.println("sing");
}
public void talk(String name,int age){
System.out.println("姓名:"+name+"年龄:"+age);
}
public static void aa(int a){
System.out.println("aa"+a);
}
public static void main(String[] args) {
System.out.println("main");
}
}
接下来是一个类Reflect主要用来讲解反射的基础
package Day01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Reflect {
/**
*
* @用反射构造函数创建对象
*/
@Test
public void test1() throws Exception {
// 1.加载类方式1
Class clazz1 = Class.forName("Day01.Person");// 包名.类名
// 2.加载类方式2
Class clazz2 = new Person().getClass();
// 3.加载类方式3
Class clazz3 = Person.class;
// 反射构造函数public Person()
Constructor c = clazz1.getConstructor(null);
Person p = (Person) c.newInstance(null);
System.out.println(p);
}
@Test
public void test2() throws Exception {
Class clazz = Class.forName("Day01.Person");
// 反射构造函数public Person(String name,int age)
Constructor c = clazz.getConstructor(String.class, int.class);
c.newInstance("李四", 18);
}
@Test
public void test3() throws Exception {
Class clazz = Class.forName("Day01.Person");
// 反射构造函数private Person(List list)
// Constructor c=clazz.getConstructor(List.class);错误,因为该方法为私有的,所以要用getDeclaredConstructor();
Constructor c = clazz.getDeclaredConstructor(List.class);
c.setAccessible(true);// 暴力反射,可以获得私有型数据,如果没有这句话将会抛出java.lang.IllegalAccessException异常
Person p = (Person) c.newInstance(new ArrayList());
}
@Test
public void test4() throws Exception {
Class clazz = Class.forName("Day01.Person");
Person p = (Person) clazz.newInstance();// 实现原理就是调用了无参构造方法。等效于test1()
}
/**
* 反射类的方法
*/
@Test
public void test5() throws Exception {
Person p = new Person();
Class clazz = Class.forName("Day01.Person");
// 反射公共无参方法public void sing()
Method m = clazz.getMethod("sing", null);// 第一个参数书方法名,第二个参数是参数类型
m.invoke(p);// 调用方法 第一个参数为 对象,后面可变参数为形参。
}
@Test
public void test6() throws Exception {
Person p = new Person();
Class clazz = Class.forName("Day01.Person");
// 反射public void talk(String name,int age)
Method m = clazz.getMethod("talk", String.class, int.class);// 第一个参数书方法名,第二个参数是参数类型
m.invoke(p, "张三", 18);// 调用方法 第一个参数为 对象,后面可变参数为形参。
}
@Test
public void test7() throws Exception {
Class clazz = Class.forName("Day01.Person");
// 反射public static void aa(int a)静态
Method m = clazz.getMethod("aa", int.class);// 第一个参数书方法名,第二个参数是参数类型
m.invoke(null, 18);// 静态方法不需要对象,所以传null
}
@Test
public void test8() throws Exception {
Class clazz = Class.forName("Day01.Person");
// 反射public static void main(String[] args) ;与其他不一样,特殊
Method m = clazz.getMethod("main", String[].class);
m.invoke(null, new Object[] { new String[] { "aa", "bb" } });// 由于jdk1.4之前数组会才分,所以应该让他拆分之后仍为数组
// m.invoke(null, (Object)new String[]{"aa","bb"});//此法也行 欺骗虚拟机不拆分即可。
}
/**
* 反射类的字段
*
*/
@Test
public void test9() throws Exception {
Class clazz = Class.forName("Day01.Person");
Field field = clazz.getDeclaredField("name");// private String
// name="zhangsan";
Class type = field.getType();// 获得字段类型
System.out.println(type);
Person p = new Person();
field.setAccessible(true);// 访问私有属性的字段或者方法要暴力破解
if (type.equals(String.class)) {
String value = (String) field.get(p);// 获取字段值
System.out.println(value);
}
/*
* else if(){ 其他一些判断之类的 }
*/
}
}