反射
1.反射理论
当程序完成编译之后,会在堆内存的方法区中生成一个Class对象,该对象包含了类的所有信息,我们可以通过该对象操作类在运行时的属性、行为。
2.类的加载
2.1类的生命周期
加载---->验证---->准备---->解析---->初始化---->使用----->卸载
2.2类加载器Classloader
2.2.1类加载器的分类
类加载器分为
- 启动类加载器(也叫根类加载器)Bootstrap Classloader
- 扩展类加载器
- 应用程序类加载器
- 自定义类加载器
启动类加载器:
由c/c++实现,我们是无法访问的,主要加载rt.jar文件下的class文件或者sun.boot.class.path路径下的内容。
扩展类加载器:
负责加载Java的扩展库JAVA_HOME/jre/lib/ext/*.jar或者java.ext.dirs路径下的内容。
应用程序类加载器:
加载我们自己编写的java文件产生的class文件
自定义类加载器:
用户自己定义的类加载器,用于满足一些特殊需求
获取类加载器:
/*
@author Nian
@Date 2022/8/12 14:08
@purpose
@Note two method to get ClassLoader
*/
public class GetClassLoader {
public static void main(String[] args) {
//1.
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("systemClassLoader = " + systemClassLoader);
//2.
ClassLoader classLoader = Person.class.getClassLoader();
System.out.println("classLoader = " + classLoader);
}
}
2.2.2类加载机制
类的加载机制为双亲委派机制
如下图:
双亲委派机制的大体意思就是:
我们在加载一个类的时候,不管能不能加载都会将加载任务一直向上委派,如果上面的加载不了再往回委派,最终回到可以加载这个类的类加载器。
3.Class类
官方文档:
Calss类常用方法解释:
getField:获取指定常用类属性
getDeclareFields:获取全部常用类属性
getMethod:获取指定类方法
getDeclareMethods:获取全部类方法
getDeclareConstructor:获取指定类的构造方法
getDeclareConstructors:获取全部类的构造方法
3.1获取Class对象的四种方式:
/*
@author Nian
@Date 2022/8/12 10:07
@purpose four method to get class
@Note
*/
public class GetClass {
private String name;
public static void main(String[] args) throws NoSuchFieldException {
//1.
Class<Person> personClass = Person.class;
System.out.println("method1 = " + personClass);
//2.get class by class instance
Person person = new Person();
Class<? extends Person> aClass = person.getClass();
System.out.println("method2 = " + aClass);
//3.get class by Class static method forName(),forName need the class path
try {
Class<?> aClass1 = Class.forName("com.etime.reflect.getclassinfo.Person");
System.out.println("method3 = " + aClass1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//4.get class by classloader
//get classloader have two method :(1)ClassLoader.getSystemClassLoader() (2)youClass.class.getClassLoader
//(1)
try {
Class<?> aClass1 = ClassLoader.getSystemClassLoader().loadClass("com.etime.reflect.getclassinfo.Person");
System.out.println("method4.1 = " + aClass1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//(2)
try {
Class<?> aClass1 = Person.class.getClassLoader().loadClass("com.etime.reflect.getclassinfo.Person");
System.out.println("method4.2 = " + aClass1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
class InnerClass{
}
}
4.反射的使用
目标类:
import java.io.Serializable;
/*
@author Nian
@Date 2022/8/12 11:34
@purpose
@Note
*/
public class Person implements Serializable {
private String name;
private String idCard;
private int age;
public Person(){
}
private Person(String name, String idCard, int age){
this.name = name;
this.idCard = idCard;
this.age = age;
}
private Person(int age){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
private int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private void emo(String s){
System.out.println(s+"emo");
}
private static int add() throws ArithmeticException{
return 0;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", idCard='" + idCard + '\'' +
", age=" + age +
'}';
}
}
4.1获取类的全限定名称以及所在包的名字
/*
@author Nian
@Date 2022/8/12 15:04
@purpose
@Note
*/
public class FullyQualifiedNameAndPackage {
public static void main(String[] args) {
Class<Person> personClass = Person.class;
//get full qualified name
String name = personClass.getName();
System.out.println("name = " + name);
//get package name
Package aPackage = personClass.getPackage();
System.out.println("aPackage = " + aPackage);
String name1 = aPackage.getName();
System.out.println("name1 = " + name1);
}
}
4.2获取类的基本信息
import java.lang.reflect.Modifier;
/*
@author Nian
@Date 2022/8/18 18:59
@purpose get class's modifiers,super class,
@Note
*/
public class getClassBasicInfo {
public static void main(String[] args) {
Class<Person> personClass = Person.class;
//get class's modifiers,like public,static,final and so on
int modifiers = personClass.getModifiers(); //it return a int type data
String string = Modifier.toString(modifiers); //get modifier String by use Modifier class's toString method
System.out.println(string);
System.out.println(modifiers);
//judge this class isPublic
boolean aPublic = Modifier.isPublic(modifiers);//like method isPublic in class Modifier is have isPrivate,isFinal...
System.out.println(aPublic);
System.out.println("--------------------------");
//get class's super class
Class<? super Person> superclass = personClass.getSuperclass();
System.out.println(superclass);
System.out.println("---------------------------\n");
//gets interfaces implemented by Person class
Class<?>[] interfaces = personClass.getInterfaces();
for(Class<?> i : interfaces){
System.out.println(i);
}
}
}
4.3获取并操作类的属性
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
/*
@author Nian
@Date 2022/8/18 19:29
@purpose
@Note
*/
public class GetFields {
public static void main(String[] args) {
Class<Person> personClass = Person.class;
//get public field
Field[] fields = personClass.getFields();
for(Field field : fields){
System.out.println(field.getName());
Class<?> type = field.getType(); //get field type
System.out.println(type);
}
PrintLine.printLine();
//get all field
Field[] declaredFields = personClass.getDeclaredFields();
for(Field field : declaredFields){
System.out.println(field.getName());
}
PrintLine.printLine();
//get field modifiers
for(Field field : declaredFields){
int modifiers = field.getModifiers();
System.out.print(field.getName() + ":");
System.out.println(Modifier.toString(modifiers));
}
PrintLine.printLine();
//access class fields and get or set field value
try {
//use constructor new a instance(this knowledge point is at getConstructor)
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class, String.class, int.class);
declaredConstructor.setAccessible(true);
Person person = declaredConstructor.newInstance("王五", "5303", 19);
//get field
Field field = personClass.getDeclaredField("name");
//get field value
field.setAccessible(true);
Object o = field.get(person);
System.out.println(o); //王五
//set field value
field.set(person, "赵四");
System.out.println(person); //Person{name='赵四', idCard='5303', age=19}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
4.4获取并操作类的方法
4.4.1 获取并操作类的普通方法
import java.lang.reflect.Method;
/*
@author Nian
@Date 2022/8/18 21:09
@purpose
@Note
*/
public class GetMethod {
public static void main(String[] args) {
Class<Person> personClass = Person.class;
//get all declared method
Method[] declaredMethods = personClass.getDeclaredMethods();
for(Method method : declaredMethods){
System.out.println(method.getName());
//get method parameter types,name,exception types,return type,modifiers
//here just get exception type and return type,because others is got in getConstructor,they are same
//get exception types
Class<?>[] exceptionTypes = method.getExceptionTypes();
for(Class<?> exception: exceptionTypes){
System.out.println(exception.getName());
}
//get return type
Class<?> returnType = method.getReturnType();
System.out.println(returnType.getName());
}
//get specified method and invoke this method
try {
//get a specified method need this method name and it's parameters type
Method emo = personClass.getDeclaredMethod("emo",String.class);
emo.setAccessible(true);
Person person = personClass.newInstance();
//ues method invoke() to let this method run,invoke() method need a class object
//and parameter if it have parameter,and the class object is this method included class's object
emo.invoke(person,"oh~~~~");
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.4.2 获取并操作类的构造方法
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
/*
@author Nian
@Date 2022/8/18 19:43
@purpose get Constructor object by Class class object
@Note if want to get Constructor object that constructor is private,need use method getDeclaredConstructor
*/
public class GetConstructor {
public static void main(String[] args) {
Class<Person> personClass = Person.class;
//get public constructors
Constructor<?>[] constructors = personClass.getConstructors(); //this method just get public constructor
for(Constructor<?> constructor : constructors){
constructor.setAccessible(true); //let this construct can accessible
System.out.println(constructor.isAccessible());
System.out.println("constructor:" + constructor.getName());
//get constructor modifiers
int modifiers = constructor.getModifiers();
System.out.println("modifiers:" + Modifier.toString(modifiers));
//get constructor parameter types
Class<?>[] parameterTypes = constructor.getParameterTypes();
System.out.print("parameterTypes: ");
for(Class<?> type : parameterTypes){
System.out.print(type.getName() + "\t");
}
System.out.println("\n");
}
//get Constructor object which constructor have parameter then
// use this Constructor object construct class instance
try {
Constructor<Person> declaredConstructor =
personClass.getDeclaredConstructor(String.class, String.class, int.class);
declaredConstructor.setAccessible(true); //if not cancel security check,this constructor can't use
Person person = declaredConstructor.newInstance("王五","142525",18);
System.out.println(person.getName());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
4.4解析类的注解
目标类:
/*
@author Nian
@Date 2022/8/21 15:16
@purpose
@Note
*/
import java.lang.annotation.*;
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String author();
}
/*
@author Nian
@Date 2022/8/21 15:21
@purpose
@Note
*/
@MyAnnotation(author = "念")
public class MyClass {
}
测试类:
/*
@author Nian
@Date 2022/8/21 15:26
@purpose
@Note
*/
public class GetAnnotationInfoTest {
public static void main(String[] args) {
Class<MyClass> myClassClass = MyClass.class;
//judge class is use an annotation
boolean isAnnotationPresent = myClassClass.isAnnotationPresent(MyAnnotation.class);
System.out.println(isAnnotationPresent); //true
if(isAnnotationPresent){
MyAnnotation annotation = myClassClass.getAnnotation(MyAnnotation.class);
//get annotation field value
String author = annotation.author();
System.out.println(author); //念
}
}
}