|
|
@@ -0,0 +1,78 @@
|
|
|
+package course;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author WanJl
|
|
|
+ * @version 1.0
|
|
|
+ * @title Demo05
|
|
|
+ * @description 反射--Class
|
|
|
+ * @create 2026/8/12
|
|
|
+ */
|
|
|
+public class Demo05 {
|
|
|
+ /*
|
|
|
+ 获取Class对象的方式有三种,但是殊途同归,同一个类无论通过哪种方式,得到的都是同一个对象,JVM对每个类只加载一份字节码。
|
|
|
+ 方式一: 类名.class
|
|
|
+ 直接调用类名.class变量,这种方式最直接最简单,编译期就会进行类型检查,不允许运行时才失败。前提就是需要在编译期就知道类名。
|
|
|
+ Class<Object> objectClass = Object.class; //JVM需要在编译期就知道这个类是存在的,才行。
|
|
|
+ Class<String> stringClass = String.class;
|
|
|
+ 方式二: 对象.getClass()
|
|
|
+ getClass()是Object类中定义的方法,所有的对象都能调用,这种方式需要先有一个对象实例,适合在已经拿到对象想要知道它是什么类型的时候使用。
|
|
|
+ Animal animal=new Teacher(); //父类的引用指向子类的对象--多态
|
|
|
+ Class<? extends Animal> aClass = animal.getClass();
|
|
|
+ 方式三: Class.forName("全类名")
|
|
|
+ Class.forName("全类名")是Class类提供的静态方法,参数是字符串形式的全类名(包名+类名),它是三种方式中最灵活的一种,
|
|
|
+ 类名以字符串的形式传入,可以是变量、配置文件的内容、网络传过来的数据都可以。
|
|
|
+ 所以它也是框架最常用的方式。注意:全类名写错了或类不存在的时候或抛出ClassNotFoundException异常 受检异常必须要处理的。
|
|
|
+ Class.forName("com.wanjl.Student");
|
|
|
+
|
|
|
+ 注意:
|
|
|
+ forName()传错全类名会抛异常ClassNotFoundException异常
|
|
|
+ 基本类型(int\double\byte...)也有对应的Class对象 int.class
|
|
|
+ int.class == Integer.TYPE
|
|
|
+ 数组也有Class对象 int[].class
|
|
|
+ 类加载的时机:
|
|
|
+ Class.forName()在返回Class之前会执行类的静态初始化块(static块);
|
|
|
+ 类名.class和对象.getClass不会触发静态代码块
|
|
|
+
|
|
|
+
|
|
|
+ */
|
|
|
+ public static void main(String[] args) throws ClassNotFoundException {
|
|
|
+ //方式一:类名.class 编译期确定,最安全
|
|
|
+ Class<Student> clazz1 = Student.class;
|
|
|
+ Class<Integer> integerClass = int.class;
|
|
|
+ Class<Integer> integerClass1 = Integer.TYPE;
|
|
|
+ System.out.println(integerClass1==integerClass); //true
|
|
|
+
|
|
|
+ int[] arr=new int[10];
|
|
|
+ Class<? extends int[]> aClass = arr.getClass();
|
|
|
+ Class<int[]> aClass1 = int[].class;
|
|
|
+
|
|
|
+ //方式二:对象.getClass() 需要有对象
|
|
|
+ Object student=new Student();
|
|
|
+ Class<?> clazz2 = student.getClass();
|
|
|
+
|
|
|
+ //方式三:Class.forName("全类名")
|
|
|
+ Class<?> clazz3 = Class.forName("course.Student");
|
|
|
+
|
|
|
+ //三种方式获取的到的对象是同一个对象,也就是 clazz1==clazz2==clazz3
|
|
|
+
|
|
|
+ System.out.println("clazz1==clazz2 : "+ (clazz1==clazz2));
|
|
|
+ System.out.println("clazz2==clazz3 : "+ (clazz2==clazz3));
|
|
|
+ System.out.println("clazz3==clazz1 : "+ (clazz3==clazz1));
|
|
|
+ System.out.println(clazz1);
|
|
|
+ System.out.println(clazz2);
|
|
|
+ System.out.println(clazz3);
|
|
|
+
|
|
|
+ //通过Class对象直接查看完整的类型信息
|
|
|
+ System.out.println("类名:"+clazz1.getName());
|
|
|
+ System.out.println("简单类名:"+clazz1.getSimpleName());
|
|
|
+ System.out.println("父类:"+clazz1.getSuperclass().getName());
|
|
|
+ System.out.println("包名:"+clazz1.getPackage().getName());
|
|
|
+ // Person.class不会加载静态代码块
|
|
|
+ //Class<Person> personClass = Person.class;
|
|
|
+ //当前案例看不出来,但是反序列化就可以看出对象.getClass()不加载静态代码块
|
|
|
+ // Class<? extends Person> personClass = new Person().getClass();
|
|
|
+ //forName("course.Person") 一定会触发静态代码块
|
|
|
+ Class.forName("course.Person");
|
|
|
+ }
|
|
|
+
|
|
|
+}
|