Java反射
一个Java程序执行的基本机制是先把Java源文件,通过Java编译器编译后生成字节码文件(.class),然后再通过ClassLoader机制将这些字节码文件加载到内存中,最后生成相应的实例并执行。而通过Java的反射机制,可以访问程序中已经加载进内存的Java对象的描述,可以访问、检测和修改描述Java对象本身的信息。
一、基本反射技术
1.1 通过反射技术获得Class对象
public class Demo{
public static void main(String args){
// 1.类名.getClass()
Object obj = new Object();
Class c1 = obj.getClass();
// 2.Class.forName();获取class对象
Clss c2 = Class.forName("Student");
// 使用forName()方法和使用new关键字创建对象看起来并没有什么不同。实际上,使用new关键字实例化对象是要经过编译器静态检查的。如果在编译器中要加载的Student类并不存在,那么将无法通过编译。而使用forName()方法是动态加载的,即使要加载的Student类并不存在,编译也是可以通过的,只是在运行时会产生异常。forName()方法返回的是Class实例,不是所加载类的实例。forName()方法多用于加载驱动程序。
// 3. 类名.class
Class c3 = Object.class; // 类
Class c4 = Comparable.class; // 接口
Class c5 = String[].class; // 一维数组
Class c6 = int[][].class; // 二维数组
Class c7 = Override.class; // 注解
Class c8 = ElementType.class; // 枚举
Class c9 = Integer.class; // 基本数据类型
Class c10 = void.class; // void
Class c11= Class.class; // class
// 只要元素类型和维度一样,就是同一个class
int[] a = new int[10];
int[] b = new int[100];
}
}
1.2 使用反射机制生成并操作对象
class Student{
private String name;
private int age;
public Student(){
}
public Student(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo{
public static void main(String[] args){
Class c = null;
Student student = null;
try {
// forName里参数为‘包.类名’的形式。
c = Class.forName("com.XXX.Student");
// 类里必须有无参构造
student = (Student) c.newInstance();
student.setName("张三");
student.setAge(34);
} catch (Exception e) {
e.printStackTrace();
}
// 1. 通过Class类中的getConstructor()方法可以获得类的公有构造器
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
// 输出内容为
// public com.XXX.Student()
// public com.XXX.Student(java.lang.String,int)
}
// 这样可以调用有参构造器创建对象
Student stu = (Student) constructors[1].newInstance("李四", 24);
// 2. getDeclaredConstructors()获得所有类的构造器 包括私有
Constructor[] declaredConstructor = c.getDeclaredConstructors();
// 3. 根据参数获得相应的构造器
Constructor con = c.getConstructor(String.class, int.class);
}
}
1.3 使用反射获取实现的全部接口
interface FirstInterface{
}
interface SecondInterface{
}
interface ThirdInterface{
}
public class Demo implements FirstInterface,SecondInterface,ThirdInterface {
public static void main(String[] args) {
Class[] c = null;
try {
c = Class.forName("com.XXX.Demo").getInterfaces();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
for (Class cc : c) {
System.out.println(cc);
}
// 输出结果:
// interface com.XXX.FirstInterface
// interface com.XXX.SecondInterface
// interface com.XXX.ThirdInterface
}
}
通过Class类的getSuperclass()方法可以获取一个类的父类。
1.4 使用反射获取类的全部属性
class Person{
public String name;
protected String id;
String age;
private String mystery;
public Person(){
}
public Person(String name, String id, String age) {
this.name = name;
this.id = id;
this.age = age;
}
// 省略getter和setter方法
}
public class Test05 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class clz = Class.forName("com.XXX.Person");
// 获取类的名字
System.out.printf(clz.getName()); // 获得包名+类名
System.out.println(clz.getSimpleName()); // 获得包名
// 获得类的属性
Field[] fields = clz.getFields(); // 只能找到public属性的字段
// for (Field field : fields) {
// System.out.println(field);
// }
System.out.println("-----------------");
Field[] declaredFields = clz.getDeclaredFields(); // 找到全部的属性
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
/**
* getField获得指定属性的值只能获得public修饰的字段
*/
// Field name = clz.getField("name");
// System.out.println(name);
/**
* java.lang.String com.XXX.Person.name
* getDeclaredField可以获取所有的指定属性的值
*/
Field name = clz.getDeclaredField("name");
System.out.println(name);
/**
* 获得本类及其父类的全部public的方法
*/
Method[] methods = clz.getMethods();
for (Method method : methods) {
System.out.println("getMethods: "+method);
}
/**
* 获得本类的所有方法 包括private 方法
*/
Method[] declaredMethods = clz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("declaredMethod:"+declaredMethod);
}
/**
* 获得指定方法
*/
Method getName = clz.getMethod("getName", null);
Method setName = clz.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
// 获得指定的构造器
System.out.println("-----------1-------------");
Constructor[] constructors = clz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("------------2------------");
Constructor[] declaredConstructors = clz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
Constructor declaredConstructor = clz.getDeclaredConstructor(String.class, String.class, String.class);
System.out.println(declaredConstructor);
}
}