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");
}
}效果: