一、什么是反射机制:
反射机制是运行状态中,对于任意一个类,都能够知道这个类的属性和方法。对于该类对象,都能够调用他的任意一个属性和方法,这种动态的获取类的信息和动态调用对象的方法的功能,称之为Java语言的反射机制。
二、反射机制的功能:
(1)可以在运行状态下,判断任意一个对象所属的类;
(2)可以在运行状态下,构造任意一个类的对象;
(3)可以在运行状态下,判断任意一个类所具有的成员变量和方法;
(4)可以在运行状态下,调用任意一个对象的属性和方法
三、Java为实现反射机制功能所提供的类:
(1)字节码文件类-----java.lang.Class
(2)构造方法类-------java.lang.reflect.Constructor
(3)成员变量类-----java.lang.reflect.Field
(4)方法类------java.lang.reflect.Method
(5)访问权限修饰类-----java.lang.reflect.Modifier
四、常用的功能实现:
1.获取一个类的字节码文件类的对象
第一种方式:通过一个类的对象,调用getClass( )方法
public class Test{
public static void main(String[] args){
ArrayList<Integer> al=new ArrayList<>();
//通过集合对象来调用getClass()方法,来获取ArrayList集合对象al的完整包名和类名
Class<?> classAl= al.getClass();
System.out.println(classAl);
}
}
第二种方式:通过类名调用class属性,获得字节码文件对象
public class Test{
public static void main(String[] args){
ArrayList<Integer> al=new ArrayList<>();
Class<?> classAl= ArrayList.class;
System.out.println(classAl);
}
第三种方式:通过字节码文件类种的静态方法
public static Class<?> forName(String className) throws ClassNotFoundException
注意这里的参数className是类名,如果字节码文件对应的有包----则为包名.类名
public class Test{
public static void main(String[] args) throws ClassNotFoundException{
ArrayList<Integer> al=new ArrayList<>();
//这种方式常用于自定义类
Class<?> classAl=Class.forName("java.util.ArrayList");
System.out.println(classAl);
}
2.根据字节码文件类对象获取该类的父类和实现的接口
import java.util.*;
class GetParent
{
public static void main(String[] args) throws Exception
{
//System.out.println("Hello World!");
// 1. 获得String类的字节码文件类对象
Class<?> classz = Class.forName("java.lang.String");
// 2.获得父类的字节码文件类对象
Class<?> parent = classz.getSuperclass();
System.out.println("父类:" + parent);
// 父类:class java.lang.Object
// 3. 获得所有的接口的字节码文件
Class<?>[] inters = classz.getInterfaces();
System.out.println("所有接口:" + Arrays.toString(inters));
}
}
3.构造任意一个类对象
import java.lang.reflect.Constructor; class User { String name; int age; public User(){} public User(String name, int age){ this.name = name; this.age = age; } public String toString(){ return name + "-" + age; } } class GetConstructor { public static void main(String[] args) throws Exception { Class<?> class1 = Class.forName("User"); // 第一种方式:字节码文件类中的 调用无参的构造方法创建对象 User user = (User)class1.newInstance(); user.name = "张三"; user.age = 16; System.out.println(user); // 第二种方式:获得全部的公共构造方法 Constructor<?>[] cons = class1.getConstructors(); System.out.println(cons.length); // 查看每个构造方法需要的参数 for(int i = 0; i < cons.length; i++){ // 根据构造函数 获得所有的参数的字节码文件类 Class<?>[] params = cons[i].getParameterTypes(); System.out.println("第【"+i+"】构造函数的参数:"); for(int j = 0; j < params.length; j++){ // 获得字节码文件类型名称 System.out.println(params[j].getName()); } } // 根据第2个构造函数来创建对象 User user2 = (User)cons[1].newInstance("小强", 20); System.out.println(user2);
//第三种方式:根据参数获得对应的构造方法
Constructor con = class1.getConstructor(String.class, int.class); User user3 = (User)con.newInstance("鹿晗", 26); System.out.println(user3); } }
4.通过某个类的字节码文件类对象,获得该类的所有属性并且为属性赋值 或者 获得属性值
import java.lang.reflect.*; class Student { String name; private int age; public String sex; protected int num; /* name他的修饰符为0 --- default age他的修饰符为2 --- private sex他的修饰符为1 --- public num他的修饰符为4 --- protected */ public Student(){} public Student(String name, int age, String sex, int num){ this.name = name; this.age = age; this.sex = sex; this.num = num; } public String toString(){ return name + "-" + age; } } class GetField { public static void main(String[] args) throws Exception { Class<?> classz = Class.forName("Student"); // 创建对象 Student stu = (Student)classz.newInstance(); // 获得该类中声明的所有属性 Field[] fields = classz.getDeclaredFields(); for(int i = 0; i < fields.length; i++){ // 获得每个属性的访问权限 int modify = fields[i].getModifiers(); System.out.println(fields[i].getName() + "他的修饰符为" + modify); // 属性类型对应的字节码文件类对象 Class<?> type = fields[i].getType(); System.out.println(type); } // 获得单独的某个属性 Field field = fields[0]; // name // 为stu对象的属性name赋值 field.set(stu, "小明"); // 获得属性的值 String obj = (String)field.get(stu); System.out.println(obj);
// 2. 根据字段名获得对应的属性 Field ageField = classz.getDeclaredField("age"); // 打开私有属性的访问权限 ageField.setAccessible(true); ageField.set(stu, 10); Integer ite = (Integer)ageField.get(stu); System.out.println(ite.intValue()); } }
5.利用反射机制获得该类的所有公共方法并且创建该类对象调用该方法
import java.lang.reflect.*; import java.util.*; class Worker { String name; int age; Worker(){} Worker(String name, int age){ this.name = name; this.age = age; } public String toString(){ return name + "-" + age; } public void work(){ System.out.println("工作"); } public void eat(String food, int num){ System.out.println("吃" + food + num); } } class GetMethod { public static void main(String[] args) throws Exception { Class<?> classz = Class.forName("Worker"); // 利用反射机制创建对象 Worker w = (Worker)classz.newInstance(); // 1.利用该类的字节码文件对象获得该类的所有公共方法 Method[] methods = classz.getMethods(); System.out.println(Arrays.toString(methods)); //2.利用该类的字节码文件对象和方法名获得该类的对应的公共方法 Method m = classz.getMethod("work"); // 由哪个对象执行该方法 m.invoke(w); Method eat = classz.getMethod("eat", String.class, int.class); // 执行该方法传参 eat.invoke(w, "鱼香肉丝", 2); } }