-
package com.hspedu.reflection.class_; import com.hspedu.Cat; import java.util.ArrayList; /** * @author 韩顺平 * @version 1.0 * 对Class类特点的梳理 */ public class Class01 { public static void main(String[] args) throws ClassNotFoundException { //看看Class类图 //1. Class也是类,因此也继承Object类 //Class //2. Class类对象不是new出来的,而是系统创建的 //(1) 传统new对象 /* ClassLoader类 public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } */ //Cat cat = new Cat(); //(2) 反射方式, 刚才老师没有debug到 ClassLoader类的 loadClass, 原因是,我没有注销Cat cat = new Cat(); /* ClassLoader类, 仍然是通过 ClassLoader类加载Cat类的 Class对象 public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } */ Class cls1 = Class.forName("com.hspedu.Cat"); //3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次 Class cls2 = Class.forName("com.hspedu.Cat"); System.out.println(cls1.hashCode());//这两个值一样 //Cat类对应一个Class对象 //Dog类对应一个Class对象 System.out.println(cls2.hashCode()); Class cls3 = Class.forName("com.hspedu.Dog"); System.out.println(cls3.hashCode()); } }
-
Class类的常用方法
package com.hspedu.reflection.class_; import com.hspedu.Car; import java.lang.reflect.Field; /** * @author 韩顺平 * @version 1.0 * 演示Class类的常用方法 */ public class Class02 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException { String classAllPath = "com.hspedu.Car"; //1 . 获取到Car类 对应的 Class对象 //<?> 表示不确定的Java类型 Class<?> cls = Class.forName(classAllPath); //2. 输出cls System.out.println(cls); //显示cls对象, 是哪个类的Class对象 com.hspedu.Car System.out.println(cls.getClass());//输出cls运行类型 java.lang.Class //3. 得到包名 System.out.println(cls.getPackage().getName());//包名 //4. 得到全类名 System.out.println(cls.getName()); //5. 通过cls创建对象实例 Car car = (Car) cls.newInstance(); System.out.println(car);//car.toString() //6. 通过反射获取属性 brand Field brand = cls.getField("brand"); System.out.println(brand.get(car));//宝马 //7. 通过反射给属性赋值 brand.set(car, "奔驰"); System.out.println(brand.get(car));//奔驰 //8 我希望大家可以得到所有的属性(字段) System.out.println("=======所有的字段属性===="); Field[] fields = cls.getFields(); for (Field f : fields) { System.out.println(f.getName());//名称 } } }
通过反射获取属性值和传统方式是相反的brand.get(car)。传统car.brand
-
获取Class类对象
package com.hspedu.reflection.class_; import com.hspedu.Car; /** * @author 韩顺平 * @version 1.0 * 演示得到Class对象的各种方式(6) */ public class GetClass_ { public static void main(String[] args) throws ClassNotFoundException { //1. Class.forName String classAllPath = "com.hspedu.Car"; //通过读取配置文件获取 Class<?> cls1 = Class.forName(classAllPath); System.out.println(cls1); //2. 类名.class , 应用场景: 用于参数传递 Class cls2 = Car.class; System.out.println(cls2); //3. 对象.getClass(), 应用场景,有对象实例 Car car = new Car(); Class cls3 = car.getClass();//运行类型 System.out.println(cls3); //4. 通过类加载器【4种】来获取到类的Class对象 //(1)先得到类加载器 car ClassLoader classLoader = car.getClass().getClassLoader(); //(2)通过类加载器得到Class对象 Class cls4 = classLoader.loadClass(classAllPath); System.out.println(cls4); //cls1 , cls2 , cls3 , cls4 其实是同一个对象 System.out.println(cls1.hashCode()); System.out.println(cls2.hashCode()); System.out.println(cls3.hashCode()); System.out.println(cls4.hashCode()); //5. 基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象 Class<Integer> integerClass = int.class; Class<Character> characterClass = char.class; Class<Boolean> booleanClass = boolean.class; System.out.println(integerClass);//int //6. 基本数据类型对应的包装类,可以通过 .TYPE 得到Class类对象 Class<Integer> type1 = Integer.TYPE; Class<Character> type2 = Character.TYPE; //其它包装类BOOLEAN, DOUBLE, LONG,BYTE等待 System.out.println(type1); System.out.println(integerClass.hashCode());//同一个 System.out.println(type1.hashCode());//同一个 } }
-
哪些类型有Class对象
package com.hspedu.reflection.class_; import java.io.Serializable; /** * @author 韩顺平 * @version 1.0 * 演示哪些类型有Class对象 */ public class AllTypeClass { public static void main(String[] args) { Class<String> cls1 = String.class;//外部类 Class<Serializable> cls2 = Serializable.class;//接口 Class<Integer[]> cls3 = Integer[].class;//数组 Class<float[][]> cls4 = float[][].class;//二维数组 Class<Deprecated> cls5 = Deprecated.class;//注解 //枚举 Class<Thread.State> cls6 = Thread.State.class; Class<Long> cls7 = long.class;//基本数据类型 Class<Void> cls8 = void.class;//void数据类型 Class<Class> cls9 = Class.class;// System.out.println(cls1); System.out.println(cls2); System.out.println(cls3); System.out.println(cls4); System.out.println(cls5); System.out.println(cls6); System.out.println(cls7); System.out.println(cls8); System.out.println(cls9); } }
-
java动态加载,静态加载
-
类加载流程图
package com.hspedu.reflection.classload_; /** * @author 韩顺平 * @version 1.0 * 我们说明一个类加载的链接阶段-准备 */ public class ClassLoad02 { public static void main(String[] args) { } } class A { //属性-成员变量-字段 //老韩分析类加载的链接阶段-准备 属性是如何处理 //1. n1 是实例属性, 不是静态变量,因此在准备阶段,是不会分配内存 //2. n2 是静态变量,分配内存 n2 是默认初始化 0 ,而不是20 //3. n3 是static final 是常量, 他和静态变量不一样, 因为一旦赋值就不变 n3 = 30 public int n1 = 10; public static int n2 = 20; public static final int n3 = 30; }
package com.hspedu.reflection.classload_; /** * @author 韩顺平 * @version 1.0 * 演示类加载-初始化阶段 */ public class ClassLoad03 { public static void main(String[] args) throws ClassNotFoundException { //老韩分析 //1. 加载B类,并生成 B的class对象 //2. 链接 num = 0 //3. 初始化阶段 // 依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并 /* clinit() { System.out.println("B 静态代码块被执行"); //num = 300; num = 100; } 合并: num = 100 */ //new B();//类加载 //System.out.println(B.num);//100, 如果直接使用类的静态属性,也会导致类的加载 //看看加载类的时候,是有同步机制控制 /* protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { //正因为有这个机制,才能保证某个类在内存中, 只有一份Class对象 synchronized (getClassLoadingLock(name)) { //.... } } */ B b = new B(); } } class B { static { System.out.println("B 静态代码块被执行"); num = 300; } static int num = 100; public B() {//构造器 System.out.println("B() 构造器被执行"); } }