目录
什么是反射机制?
- 反射是Java编程语言的一个特性。在Java运行状态中,通过给定的Calss对象,利用反射机制获取该Class对象的结构;
- 利用一个具体的对象,使用反射可以动态地调用它的方法和对成员进行访问和赋值;
这种动态获取类的内容、创建对象、以及动态调用对象方法及操作属性的机制,就叫做Java反射机制。
使用射机制的优缺点
- 优点:
增加程序的灵活性,避免将固有逻辑代码写死在代码中
代码整洁和可读性强,可提高代码的复用率
- 缺点:
相对于正常创建对象,在创建对象比较多的情况下反射的性能比较低(原因:在使用反射的过程中调用了大量的底层方法)
破坏代码的安全性(破坏单例)
反射API
反射的api即是对Class对象的操作,而对象主要包含以下内容:
Class对象的组成
包:(Package)
构造方法:(constructor)
字段:(Filed)
函数:(Method)
注解:(Annotation)
接口:(Interface)
父类:(parent)
获取Class对象的四种方式:
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Person person = new Person();
//1.通過Class . 獲取Class對象
Class<Person> clazz01 = Person.class;
//2.通過實例對象獲取
Class<?> clazz02 = person.getClass();
//3.通過Class.forName獲取
Class<?> clazz03 = Class.forName("com.coding.genuse.reflection.pojo.Person");
//4.通過ClassLoader加載实例对象獲取
Class<?> clazz04 = person.getClass().getClassLoader().loadClass("com.coding.genuse.reflection.pojo.Person");
//通過反射實例化對象
Person p1 = clazz01.newInstance();
Person p2 = (Person)clazz02.newInstance();
Person p3 = (Person)clazz03.newInstance();
Person p4 = (Person)clazz04.newInstance();
}
}
通过Class对象获取类的基本信息
public class Demo02 {
public static void main(String[] args) {
Class<Person> clazz = Person.class;
//獲取類的修飾符
int modifier = clazz.getModifiers();
//獲取類包對象/包名
Package pack = clazz.getPackage();
//獲取類的全路徑名稱
String fullClassName = clazz.getName();
//獲取類的簡單名稱
String simpleName= clazz.getSimpleName();
//獲取類加載器
ClassLoader classLoader = clazz.getClassLoader();
//獲取類接口
Class[] interfaces = clazz.getInterfaces();
//獲取父類
Class superClass = clazz.getSuperclass();
//獲取註解信息
Annotation[] annotations = clazz.getAnnotations();
}
}
类的属性操作
public class Demo03 {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<Person> clazz = Person.class;
Person person = (Person) clazz.newInstance();
System.out.println("before change:" + person);
//獲取類的所有屬性(包含繼承的)
Field[] fields = clazz.getFields();
//獲取類中定義的字段(內部)
Field[] declaredFields = clazz.getDeclaredFields();
//通過指定名字獲取屬性
Field nameFiled = clazz.getDeclaredField("name");
//獲取字段修飾符
int modifiers = nameFiled.getModifiers();
//字段強制訪問
nameFiled.setAccessible(true);
//修改字段的值
nameFiled.set(person, "I‘m changed");
System.out.println("after change:" + person);
Field nickNameField = clazz.getDeclaredField("nickName");
nickNameField.setAccessible(true);
//靜態字段賦值
nickNameField.set(null, "靜態字段賦值");
System.out.println("靜態字段賦值:" + person);
}
}
类的方法操作
public class Demo04 {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<Person> clazz = Person.class;
Person person = clazz.newInstance();
//獲取所有成員方法
Method[] methods = clazz.getMethods();
//獲取聲明的成員方法
Method[] declaredMethods = clazz.getDeclaredMethods();
//根據名稱獲取方法
Method studyMethod = clazz.getDeclaredMethod("study");
//調用方法
studyMethod.invoke(person);
System.out.println("before set name:" + person);
Method setNameMethod = clazz.getDeclaredMethod("setName", String.class);
setNameMethod.setAccessible(true);
setNameMethod.invoke(person, "set new name");
System.out.println("after set name:" + person);
Method sayMethod = clazz.getDeclaredMethod("say", String.class);
//反射調用靜態方法
sayMethod.invoke(null, "Hello world");
}
}
类的构造器操作
public class Demo05 {
public static void main(String[] args) throws Exception {
Class<User> clazz = User.class;
//獲取公有的構造器
Constructor[] cons = clazz.getConstructors();
//獲取所有的構造器
Constructor[] constructors = clazz.getDeclaredConstructors();
//獲取無參構造方法
Constructor noParamconstructor = clazz.getConstructor();
//獲取有參構造方法
Constructor constructor = clazz.getConstructor(Integer.class, String.class);
//構造器實例對象
noParamconstructor.newInstance();
//有參構造器實例對象
constructor.newInstance(1, "demo");
}
}
思考问题
反射的使用场景?
有哪些框架使用了反射?