1 Class类
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
1.1 获取Class对象的三种方式:
public class Person {
private String name;
public int age;
static{
System.out.println("静态代码块");
}
public Person(){
System.out.println("空参构造");
}
public Person(String name,int age){
this.name=name;
this.age=age;
System.out.println("Person(String name,int age)");
}
private Person(String name){
this.name=name;
System.out.println("Person(String name)");
}
public void eat(){
System.out.println("公共空参方法");
}
public void sleep(String name){
System.out.println("公共有参方法");
}
public void smoke(){
System.out.println("私有空参构造");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
//1.通过getClass方法获取, 通过对象获取
Person p=new Person();
Class c1=p.getClass();
System.out.println(c1);
//2.通过类名获取
Class c2=Person.class;
System.out.println(c2);
System.out.println(c1==c2);
System.out.println(c1.equals(c2));
//3.通过完整的包名+类名获取
Class c3=Class.forName("com.oracle.demo03.Person");
System.out.println(c3);
}
}
2 通过反射获取构造方法并使用
在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示。其中,构造方法使用类Constructor表示。可通过Class类中提供的方法获取构造方法:
public class Demo02 {
//构造方法 Constructor
//成员变量 Field
//成员方法 Method
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//反射获取构造方法
//1.获取Person.Class文件对象
Class c=Class.forName("com.oracle.demo03.Person");
//获取所有公共的构造方法(数组)
/*Constructor[]cons=c.getConstructors();
//遍历
for(Constructor con:cons){
System.out.println(con);
}*/
//获取某个公共构造方法
/*Constructor con1=c.getConstructor(String.class,int.class);
System.out.println(con1);
//通过构造方法创建对象
Object obj=con1.newInstance("张三",18);
System.out.println(obj);*/
//获取所有构造方法数组
/*Constructor[]cons=c.getDeclaredConstructors();
for(Constructor con:cons){
System.out.println(con);
}*/
//获取某个私有构造方法
Constructor con=c.getDeclaredConstructor(String.class);
//System.out.println(con);
//暴力反射
con.setAccessible(true);
Object obj=con.newInstance("熊大");
System.out.println(obj);
}
}
3 通过反射获取成员变量和成员方法并使用
在反射机制中,把类中的成员变量使用类Field表示。可通过Class类中提供的方法获取成员变量:
在反射机制中,把类中的成员方法使用类Method表示。可通过Class类中提供的方法获取成员方法:
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
//获取字节码文件对象
Class c=Class.forName("com.oracle.demo01.Person");
//获取所有的成员变量
/*Field[]fields=c.getDeclaredFields();
//遍历
for(Field field:fields){
System.out.println(field);
}*/
//获取某个成员变量并赋值
/*Field field=c.getDeclaredField("age");
Object obj=new Person();
field.set(obj, 18);
System.out.println(obj);*/
//获取所有成员方法
/*Method[]methods=c.getDeclaredMethods();
//遍历
for(Method method:methods){
System.out.println(method);
}*/
//获取单个成员方法
Method method=c.getMethod("sleep", String.class);
//调用方法
Object obj=c.newInstance();
method.invoke(obj, "张三");
4 反射练习
4.1 泛型擦除
思考,将已存在的ArrayList<Integer>集合中添加一个字符串数据,如何实现呢?
其实程序编译后产生的.class文件中是没有泛型约束的,这种现象我们称为泛型的擦除。那么,我们可以通过反射技术,来完成向有泛型约束的集合中,添加任意类型的元素
public class Demo02 {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
//泛型擦除
ArrayList<Integer>arr=new ArrayList<Integer>();
//获取ArrayList的字节码文件对象
Class c=arr.getClass();
//通过反射的方式获取add方法
Method add=c.getMethod("add", Object.class);
add.invoke(arr, "aaa");
System.out.println(arr);
}
}
4.2 反射配置文件
通过反射配置文件,运行配置文件中指定类的对应方法
读取properties文件中的数据,通过反射技术,来完成Person对象的创建
public class Demo01 {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
//明确配置文件的路径
FileReader fr=new FileReader("src/com/oracle/demo02/config.properties");
//创建Properties集合
Properties pro=new Properties();
//从配置文件中读取键值对到集合中
pro.load(fr);
//从集合中获取完整的包名+类名
String ClassName=pro.getProperty("ClassName");
//获取方法名
String MethodName=pro.getProperty("MethodName");
//通过反射获取字节码文件对象
Class c=Class.forName(ClassName);
//创建对象
Object obj=c.newInstance();
//获取方法
Method method=c.getMethod(MethodName);
//调用方法
method.invoke(obj);
}
}