Java-Day-34
Class 类特性
-
Class 也是类,因此也继承 Object 类
-
Class 类对象不是 new 出来的,而是系统创建的
- 通过类加载器 ClassLoader 类中的的 loadClass 方法
-
对于某个类的 Class 类对象,在内存中只有一份
-
不管是传统方法还是反射方法,一个类只会进一次 ClassLoad 类的 loadClass() 方法
/* 同是通过ClassLoad类加载 Dog 类的Class对象 public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } */ Class cls1 = Class.forName("com.hspJava.Dog"); Class cls2 = Class.forName("com.hspJava.Dog"); System.out.println(cls1.hashCode()); System.out.println(cls2.hashCode()); // hashCode值相同
-
-
每个类的实例都会记得自己是由哪个 Class 实例所生成
-
通过 Class 可以完整地得到一个类的完整结构,通过一系列 API
-
Class 对象是存放在堆的
- 在 Class 类阶段 ( 加载阶段 )
-
类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据 ( 包括方法代码、变量名、方法名、访问权限等等 )
- 在加载阶段还会生成一个方法区,内含一个该类的字节码二进制数据 ——> 引入到堆内 Class 类对象的这层关系,二进制数据转成 Class 类对象 ( 其实是种数据结构 ) 后操作更加容易
Class 类的常用方法
String className = "com.zyz.Dog";
Class cls = Class.forName(className);
System.out.println(cls); // 输出为类所在路径,即指明是哪个类的Class对象:class com.zyz.Dog
System.out.println(cls.getClass()); // 输出为运行类型:class java.lang.Class
// 得到包名
System.out.println(cls.getPackage().getName()); // com.zyz
// 得到全类名
System.out.println(cls.getName()); // com.zyz.Dog
// 通过cls创建对象实例
Dog dog = (Dog) cls.newInstance(); //
System.out.println(dog); // com.zyz.Dog@5ca881b5
// 通过反射获取属性
Field name = cls.getField("name");
System.out.println(name.get(dog)); // 土豆
// 通过反射给属性赋值
name.set(dog, "球球"); // 属性.set在(对象, 赋新值)
System.out.println(name.get(dog)); // 球球
// 得到所有的属性(字段)
Field[] fields = cls.getFields();
for (Field f: fields) {
System.out.print(f.getName() + "~"); // name~age~
}
Class 对象的获取方法
Class.forName()
- 在代码 / 编译阶段
- 前提:已知一个类的全类名,且该类在路径下,可通过 Class 类的静态方法 forName() 获取,可能抛出 ClassNotFoundException
- 应用场景:多用于配置文件,读取类全路径,加载类
类.class
- Class 类 / 加载阶段 ( 堆中已有类对象 )
- 前提:已知具体的类,该方式最为安全可靠,程序性能
- 应用场景:多用于参数传递,比如通过反射得到对应构造器对象
对象.getClass
-
就是之前一直用的获取运行类型的方法,就是在此运行阶段去找关联的在堆里的 Class 类对象,就是其在编译阶段真正加载进来的字节码文件的类,就是运行类型
-
运行阶段 ( 对象已经有了 )
-
前提:已知某个类的实例,调用该实例的 getClass() 方法获取 Class 对象
-
应用场景:多用于有对象实例,即通过创建好的对象,获取 Class 对象
类加载器
- 还可以通过类加载器得到 Class 对象
代码实例
// 1.Class.forName
String classAllPath = "com.zyz.Dog"; // 此处全路径应是通过读取配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1);
// 2.类名.class
Class cls2 = Dog.class;
System.out.println(cls2);
// 3.对象.getClass()
Dog dog = new Dog();
Class cls3 = dog.getClass();
System.out.println(cls3);
// 4.通过类加载器[四种]来获取到类的Class对象
// (1)先得到类加载器dog
ClassLoader classLoader = dog.getClass().getClassLoader();
// (2)通过来加载器得到Class对象
Class cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4);
// 上述输出全为 class com.zyz.Dog
// cls1、2、3、4其实是同一个对象,输出全部相同
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
System.out.println(cls3.hashCode());
System.out.println(cls4.hashCode());
剩下两种比较特别的
- 基本数据类型 ( int, char, boolean, float, double, byte, long, short ) 按如下方式得到 Class 类对象
Class cls = 基本数据类型.class;
- 基本数据类型对应的包装类,可以通过 .TYPE 得到 Class 类对象
Class type = 包装类.TYPE;
- 代码实例 ( 可知 int 与 Integer 实际上哈希值都是一样的,只是底层在自动装箱和拆箱 )
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
// 看似为尖括号里的包装类,但输出可见还是最初的基本数据类型
System.out.println(integerClass); // int
System.out.println(characterClass); // char
Class<Integer> type = Integer.TYPE;
Class<Character> type1 = Character.TYPE;
System.out.println(type); // int
System.out.println(type1); // char
// 但int与Integer哈希值都是一样的,只是底层是自动装箱和拆箱
System.out.println(integerClass.hashCode());
System.out.println(type.hashCode());
具有 Class 对象的类型
- 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
- interface:接口 —— 可看作一种特殊的类
- 数组
- enum:枚举
- annotation:注解
- 基本数据类型
- void
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; // 枚举(线程中的State就是枚举enum修饰的)
Class<Long> cls7 = long.class; // 基本数据类型
Class<Boolean> cls8 = Boolean.class; // 包装类
Class<Void> cls9 = void.class; // void
Class<Class> cls10 = Class.class; // Class本身也是有的
System.out.println(cls1); //class java.lang.String
System.out.println(cls2); //interface java.io.Serializable
System.out.println(cls3); //class [Ljava.lang.Integer;
System.out.println(cls4); //class [[F
System.out.println(cls5); //interface java.lang.Deprecated
System.out.println(cls6); //class java.lang.Thread$State
System.out.println(cls7); //long
System.out.println(cls8); //class java.lang.Boolean
System.out.println(cls9); //void
System.out.println(cls10); //class java.lang.Class
标签:Java,对象,class,System,Day,println,Class,out
From: https://www.cnblogs.com/zhu-ya-zhu/p/17568638.html