1.反射机制
静态语言:JAVA 和C++
反射:可以借助于反射API可以获取任何类的内部信息,并可以直接操作任意对象的内部属性、方法、泛型等。
实现获得Class类的方法有哪些:
- 类名.class
- Class.forName("类的绝对路径")
- 对象.getClass () 方法
- 包装类.type
package com.chapter02_注解和反射.reflection;
/**
* @author Lenovo
* @date 2024/3/12
* @time 19:59
* @project Chapter01_Java_多线程
**/
public class TestReflection01 {
public static void main(String[] args) throws ClassNotFoundException {
//第一种方法 对象.getClass() 方法;
Student student = new Student();
System.out.println("名字是:"+student.name);
Class<? extends Student> c1 = student.getClass();
System.out.println(c1.hashCode());
//第二种通过Class.forName()得到
Class<?> c2 = Class.forName("com.chapter02_注解和反射.reflection.Student");
System.out.println(c2.hashCode());
//第三种:类名.class :
Class<Student> c3 = Student.class;
System.out.println(c3.hashCode());
System.out.println("父类是:"+c3.getSuperclass());
//第四种:包装类.TYPE
Class<Integer> c5 = Integer.TYPE;
System.out.println("--------------------------------------");
System.out.println(c5.hashCode());
System.out.println(c5.getName());
System.out.println("Integer的父类为:"+c5.getSuperclass());
}
}
class Person{
String name;
int age ;
public Person(){
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student extends Person{
String name ="学生";
int age =18;
public Student(){
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
class Teacher extends Person{
String name="老师";
int age =35;
public Teacher(){
}
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
}
哪些类有class对象:
类加载器:把类装载到内存中,
系统类加载器(应用加载器)、扩展类加载器(是系统类加载器的父类)、引导类加载器(根加载器,C++编写,java获取不到。 加载rt.jar包)
2.通过反射动态获得类的完整结构和信息
package com.chapter02_注解和反射.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author Lenovo
* @date 2024/3/13
* @time 9:20
* @project Chapter01_Java_多线程
**/
public class TestReflection02 {
public static void main(String[] args) throws NoSuchMethodException {
Human human = new Human();
Class<? extends Human> c1 = human.getClass();
/**
* 1.通过反射获得属性;
*/
Field[] fields = c1.getFields(); //只能拿到public的属性
for (Field field : fields) {
//迭代
System.out.println(field);
}
/**
* 2. getDeclaredFields:能拿到所有的属性
*/
System.out.println("-----------------------------------");
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("-----------------------------------");
//通过反射获得方法:
/**
* 3. 获取具体的类:需要同时传入类名和参数类型:
*/
Method getName = c1.getMethod("getName", null);
System.out.println("getName方法:"+getName);
Method setName = c1.getMethod("setName", String.class);
System.out.println("setName方法:"+setName);
/**
*4. 只能拿到public类型的方法:
*/
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println("只能拿到public的方法:"+method);
}
/**
*5. 能拿到所有的方法:
*/
System.out.println("-----------------------------------");
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
/**
* 6. 通过反射获得构造器:
*/
System.out.println("-----------------------------------");
Constructor<?>[] constructors = c1.getConstructors();
for (Constructor<?> cons : constructors) {
System.out.println("拿到的是public类型的构造器:"+cons);
}
/**
*7. 能拿到所有的构造器
*/
System.out.println("-----------------------------------");
Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
/**8. 获取到父类
*
*/
System.out.println("-----------------------------------");
Class<?> superclass = c1.getSuperclass();
System.out.println("父类:"+superclass);
}
}
class Human{
public String name;
public int age;
private int id;
public Human(){
}
public Human(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
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;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private void test(){
}
}
3.通过反射动态创建对象去执行方法:
package com.chapter02_注解和反射.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author Lenovo
* @date 2024/3/13
* @time 9:59
* @project Chapter01_Java_多线程
**/
public class TestReflection03 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
/**
* 通过反射去动态操作类的属性和方法;
*/
System.out.println("--------------------------------------");
Class<?> c1 = Class.forName("com.chapter02_注解和反射.reflection.User");
User user1 = (User) c1.newInstance(); //实例化对象;
System.out.println(user1);
/**
* 2. 通过构造器创建对象:
*/
System.out.println("--------------------------------------");
Constructor<?> UserCons = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) UserCons.newInstance("小明",18,12); //通过构造器创建对象,与之前new 出来构造器是一样的
System.out.println(user2.getName());
/**
* 3. 通过反射操作方法
*/
System.out.println("--------------------------------------");
Method setName = c1.getMethod("setName", String.class);
setName.invoke(user2,"小芳"); //invoke (对象,参数);
System.out.println(user2.getName());
/**
* 4.通过反射操作属性:
*/
System.out.println("--------------------------------------");
Field name = c1.getDeclaredField("name");
//私有的属性或者方法获取不到,可以使用 setAccessiable(true):
name.setAccessible(true); //true:关闭安全检测开关
name.set(user2,"狂神"); //name.set方法:
//获取属性
System.out.println("name:"+user2.getName());
}
}
class User{
private String name;
private int age;
private int id;
public User() {
}
public User(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
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;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
注意:如果属性和方法都是私有的,想要去操作,可以通过setAccessiable(true)将安全检测关闭。关闭检测会提高系统的系统,比起反射调用要提高几十倍。