Java高级-Java反射机制
1.反射概述
什么是反射?
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象方法的功能称为Java语言的反射机制。
简单来说,反射机制指的是程序在运行时能够获取自身和信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息,包括访问修饰符、父类、实现的接口、属性和方法的所有信息,并可在运行时创建对象、修改属性(包括私有的)、调用方法(包括私有的)。
2.反射机制
动态编译:运行时确定类型,绑定对象、动态编译最大限度发挥了java的灵活性,体现了多态的应用,用以降低类之间的耦合性。
反射的缺点:对性能有一点影响。使用反射是一种解释操作,这类操作总是慢于直接执行的相同操作。
3.Class对象:
Class对象是Reflection故事起源。要想操纵类中的属性和方法,都必须从获取Class对象开始
Class类没有公共的构造方法,Class对象是在加载类时,由Java虚拟机以及通过调用类加载器中的方法自动构造的,因此不能显式地声明一个Class对象。
Class对象的获取方式:
object.getClass():对象的getClass方法获取
class.getSuperclass():获取当前class的父类class
.class属性:通过类名.class属性,获取类的class
Class.forName(类名):通过传入的字符串格式的类名获取class
.TYPE:基本数据类型包装类的TYPE属性获取class
Demo:
package pkg1.classtype; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ClassDemo { public static void main(String[] args) throws Exception { test1(); test2(); test3(); } public static void test1(){ Employee employee=new Employee("zs", 22); //获取Class对象 Class<?> class1 = employee.getClass(); //class1 = Employee.class; //try { //class1 = Class.forName("pkg1.classtype.Employee"); //} catch (ClassNotFoundException e) { //// TODO Auto-generated catch block //e.printStackTrace(); //} System.out.println("普通类 类名:"+class1.getName()); System.out.println("父类名:"+class1.getSuperclass().getName()); //获取基础数据类型的Class对象 Class<?> class2 = int.class; //class2 = Integer.TYPE;//获取包装类对应的基础数据类型class System.out.println("基础数据类型 类名:"+class2.getName()); //基本数据类型Class没有父类 System.out.println("父类:"+class2.getSuperclass()); //包装类的Class对象 Class<?> class3 = Integer.class; System.out.println("基础数据包装类 类名:"+class3.getName()); //基本数据类型Class没有父类 System.out.println("父类名:"+class3.getSuperclass().getName()); System.out.println("——————————————————————————————————————————"); } public static void test2() throws Exception{ //获取类关联的Class对象 Class<?> class1 = Class.forName("pkg1.classtype.Employee"); //通过反射构造实例 //Employee employee = (Employee)class1.newInstance();//无参构造方法,相当于 .getConstructor(new Class[]{}).newInstance(new Class[]{}) //带参数的构造函数,传入参数类型Class列表,参数值列表 Employee employee = (Employee)class1.getConstructor(new Class[]{String.class,int.class}).newInstance(new Object[]{"zhangsan",24}); System.out.println(employee); //获取Class对象的指定公共方法 Method methodToString = class1.getDeclaredMethod("toString", new Class[]{}); System.out.println(methodToString.getName()); String desc = (String)methodToString.invoke(employee, new Object[]{}); System.out.println("invoke result:"+desc); //获取Class对象的私有方法 Method methodWork = class1.getDeclaredMethod("work", new Class[]{}); System.out.println(methodWork.getName()); methodWork.setAccessible(true);//设置私有方法可被访问 methodWork.invoke(employee, new Object[]{});//调用私有方法,但不建议这么做 //获取Class对象的所有方法 //method.getModifiers()为访问修饰符,1为Public,2为private,4为protected Method []methods = class1.getDeclaredMethods(); for(Method method:methods){ System.out.println(method.getName()+" "+method.getModifiers()+" "+method.getReturnType()); } Field fieldName = class1.getDeclaredField("name"); fieldName.setAccessible(true);//设置属性可访问 fieldName.set(employee,"li si");//修改属性值 System.out.println(fieldName.get(employee));//输出属性值 System.out.println("——————————————————————————————————————————"); } //使用反射来创建数组 public static void test3() throws Exception{ //创建一维数组 Class<?> classStr = Class.forName("java.lang.String"); Object array = Array.newInstance(classStr, 5); Array.set(array, 0, "hello");//在数组下标0位置赋值 System.out.println(Array.get(array,0));//取数组下标0位置的值 //创建二维数组 int [] dimens = {3,3}; Object array2 = Array.newInstance(int.class,dimens);//二维数组 Object array2_3 = Array.get(array2,2);//获取第三行,是一个一维数组 Array.setInt(array2_3,2,100);//给第三行第三列赋值 int [][]arr = (int[][])array2; System.out.println(arr[2][2]); System.out.println("——————————————————————————————————————————"); } } class Employee{ public Employee() { super(); } public Employee(String name, int age) { super(); this.name = name; this.age = age; } private String name; 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; } private int age; @Override public String toString() { return "Employee [name=" + name + ", age=" + age + "]"; } private void work(){ System.out.println("I am working"); } }
效果: