1、类的加载过程
当程序主动的使用了某个类,该类还未被加载到内存中,则系统会通过上面的三个步骤对类进行初始化:
- 类的加载: 将类的class文件读入内存,并为之创建一个java.lang.Class对象
- 类的链接:将类的二进制数据合并到JRE中
- 类的初始化:JVM负责对类进行初始化
2、什么时候发生类的初始化
2.1、类的主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化main方法所在的类
- new一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
- 当初始化一个类,如果父类没有被初始化,则会先去初始化它的父类
2.1、类的被动引用(不会发生类的初始化)
- 当访问一个静态域时,只要真正声明这个域的类才会被初始化。如通过子类引用父类的静态变量,不会导致子类的初始化
- 通过数组定义类的引用,不会触发此类的初始化
- 引用常量
3、获取类运行时的结构
获得类的信息
package reflection;import java.lang.reflect.Field;public class Demo3 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {Class c1 = Class.forName("reflection.User3");// 获取类名System.out.println(c1.getName()); // 包名 + 类名System.out.println(c1.getSimpleName());// 获取属性Field[] fields = c1.getDeclaredFields();for (Field field : fields) {System.out.println(field);}// 获得指定属性的值Field name = c1.getDeclaredField("name");System.out.println(name);}}// 实体类class User3 {private String name;private int id;private int age;// 无参构造public User3() {}public User3(String name, int id, int age) {this.name = name;this.id = id;this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", id=" + id +", age=" + age +'}';}}
4、动态创建对象的执行方法
创建类的对象:调用Class对象的newInstance()方法
- 类必须有一个无参构造器
- 类的构造器的访问权限需要足够
调用指定的方法:通过反射,调用类中方法,通过Method类完成
import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Demo4 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {// 获得Class对象Class c1 = Class.forName("reflection.User");// 构造一个对象(无参数构造)User user = (User) c1.newInstance();System.out.println(user);// 通过构造器创建对象Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);User user2 = (User) constructor.newInstance("demo", 1, 11);System.out.println(user2);// 通过反射调用普通方法User user3 = (User) c1.newInstance();Method setName = c1.getDeclaredMethod("setName", String.class);setName.invoke(user3, "joinmouse");System.out.println(user3.getName());}}
5、获取泛型信息
Java采用泛型擦除机制来引入泛型,Java中的泛型仅仅是给编译器的javac使用,确保数据的安全性和免去强制类型转换问题,但是一旦编译完成,所有泛型和有关的类型都会被擦除
为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType、TypeVaribale、WildcardType几种类型来代表能不能归一到Class类中的类型但有何原始类型齐名的类型
public class Demo5 {public void test01(Map<String, User> map, List<User> list) {System.out.println("test01");}public static void main(String[] args) throws NoSuchMethodException {Method method = Demo5.class.getMethod("test01", Map.class, List.class);// 获取泛型Type[] genericParameterTypes = method.getGenericParameterTypes();for(Type genericParameterType : genericParameterTypes) {System.out.println(genericParameterType);// 判断类型属于参数化类型if(genericParameterType instanceof ParameterizedType) {Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();for (Type actualTypeArgument : actualTypeArguments) {System.out.println(actualTypeArgument);}}}}}// 打印信息java.util.Map<java.lang.String, reflection.User>class java.lang.Stringclass reflection.Userjava.util.List<reflection.User>class reflection.User
6、获取注解信息
反射操作注解:getAnnotations
ORM:Object relationship Mapping 对象关系映射
利用反射和注解完成类和表结构的映射关系
import java.lang.annotation.*;import java.lang.reflect.Field;public class Demo6 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {Class c1 = Class.forName("reflection.Student2");// 通过反射获得注解Annotation[] annotations = c1.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}// 获得注解value的值Table table = (Table) c1.getAnnotation(Table.class);String value = table.value();System.out.println(value);// 获得类指定的注解Field field = c1.getDeclaredField("id");FieldDb annotation = field.getAnnotation(FieldDb.class);System.out.println(annotation.columnName());System.out.println(annotation.type());System.out.println(annotation.length());}}@Table("db_student")class Student2 {@FieldDb(columnName = "db_id", type="int", length = 10)private int id;@FieldDb(columnName = "db_age", type="int", length = 10)private int age;@FieldDb(columnName = "db_name", type="varchar", length = 30)private String name;public Student2() {}public void Student2(int id, int age, String name) {this.id = id;this.age = age;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student2{" +"id=" + id +", age=" + age +", name='" + name + '\'' +'}';}}// 类名的注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface Table {String value();}// 属性的注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface FieldDb {String columnName();String type();int length();}
