什么是反射?
JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 java 语言的反射机制。
为什么使用反射?
先明确两个概念,静态编译和动态编译。
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
我们可以明确的看出动态编译的好处,而反射就是运用了动态编译创建对象。
使用反射基础
Person
package com.cqyti.stx.senior.oop.reflect_;
/**
* @author JH_Y
* @version 1.0
*/
class Person {
private String id;
public String username;
public void sayHello(String username) {
System.out.println("你好,我是" + username);
}
private void personInfo(String id) {
System.out.println("我的身份证ID是" + id);
}
}
ReflectDemo
package com.cqyti.stx.senior.oop.reflect_;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author JH_Y
* @version 1.0
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class<?> clazz = Class.forName("com.cqyti.stx.senior.oop.reflect_.Person");
/*
clazz.getField(); //根据方法名,获取反射类申明的public方法
clazz.getDeclaredField(); //根据方法名,获取反射类申明任意方法
*/
Field[] declaredFields = clazz.getDeclaredFields();//获取反射类申明的所有属性
for (Field f : declaredFields) {
System.out.println(f.getName());
}
Field[] fields = clazz.getFields();//获取反射类申明的所有public属性
for (Field f : fields) {
System.out.println(f.getName());
}
Method[] declaredMethods = clazz.getDeclaredMethods();//获取反射类申明的所有方法
for (Method m : declaredMethods) {
System.out.println(m.getName());
}
/*
sayHello
personInfo
*/
//获取反射类以及父类的所有public方法
Method[] methods = clazz.getMethods();
for (Method m : methods) {
System.out.println(m.getName());
}
/*
以下除了sayHello都是属于Object类的public方法,(clone 、finalize 、registerNatives不是public修饰,所以没有出现)
sayHello
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
*/
//根据方法名以及参数类型获取反射类申明的私有方法
Method personInfoMethod = clazz.getDeclaredMethod("personInfo", String.class);
personInfoMethod.setAccessible(true);
System.out.println(personInfoMethod.getName());
/*
personInfo
*/
/*
调用方法
1. 传统调用: 对象.对象方法---》只能使用该类公有方法,无法使用私有方法
2. 反射调用: 方法对象.invoke(对象,方法所需参数) ---》可以使用该类的公有、私有方法,前提是 personInfoMethod.setAccessible(true);
*/
Person person = (Person) clazz.newInstance();
person.sayHello("tom");
personInfoMethod.invoke(person, "123456789");
}
}