一、类图:
二、基本介绍:
1. Class也是类,因此也继承了Object类。
2. Class类的对象不是new出来的,是系统创建的。
类加载器ClassLoader有个方法LoadClass(),将某个类对应的Class对象生成在堆中。
通过调试可以发现:
传统方法new一个类的时候,调用了loadClass()方法
使用反射,也是调用loadClass()方法
3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次。(加载过程中用loadClass()方法创建)
4.每个类的实例,都会与自己类的Class对象(实例)相关联
也就是说一个类不管实例化多少对象,这些对象都和这个类的Class对象相关联
5.通过Class对象可以完整地得到一个类的完整结构,调用相应的API
6.Class对象是存放在堆当中的。
7.类的字节码二进制数据,是存放在方法区的。有的地方称为类的元数据(包括 方法代码、变量名、方法名、访问权限等)
即 类加载之后,除了在 堆中生成Class对象 ,还会 在方法区中生成一个该类的字节码二进制数据 。
详情: hotpot java虚拟机Class对象是放在 方法区 还是堆中 ? - 知乎
三、常用方法
//获取Class类对象,?表示不确定的类型
Class<?> aClass = Class.forName("Class_.Cat");
//1.显示aClass对象是哪个类的对象 结果为Class_.Cat
System.out.println(aClass);
//2.显示aclass的运行类型 结果为java.long.Class
System.out.println(aClass.getClass());
//3.显示aclass类对象所属的类的包名 结果为Class_
System.out.println(aClass.getPackage().getName());
//4.得到完整类名 结果为Class_.Cat
System.out.println(aClass.getName());
//5.生成对象实例
Object o = aClass.newInstance();
//6.得到该类的某个属性(此处仅能调用共有属性) 在Cat中name默认为小米,所以输出小米
Field name = aClass.getField("name");
System.out.println(name.get(o));
//7.给属性赋值 因为重新赋值小红,所以输出小红。
name.set(o,"小红");
System.out.println(name.get(o));
//8.获取所有属性
Field[] fields = aClass.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i].getName());
}
四、获取Class类对象的方法
在三个阶段有不同的获取方法:
1.编译阶段:Class.forName()
2.加载阶段:类.class
3.运行阶段: 对象.getClass()
4.也可以通过 类加载器ClassLoader得到某个类的Class对象。
//1.getName()
// 多用于配置文件,读取类全路径,加载类
Class<?> aClass = Class.forName("Class_.Cat");
System.out.println(aClass);//2.通过.class获取,该方法最安全可靠,性能最高
// 多用于参数传递,比如通过反射得到对应构造器对象
System.out.println(Cat.class);//3.通过该类的对象的.getClass()方法获得
// 多用于通过创建好的对象获取Class对象
Cat cat = new Cat();
System.out.println(cat.getClass());//4.通过类加载器(有四种加载器)得到Class对象
ClassLoader classLoader = cat.getClass().getClassLoader();
Class<?> aClass1 = classLoader.loadClass("Class_.Cat");
System.out.println(aClass1);//5.基本数据类型(int,char,boolean,float,double,byte,long,short)可以
//通过 Class cls = 基本数据类型.class
Class<Integer> integerClass = int.class;
System.out.println(integerClass);//6.基本数据类型对应的包装类可以通过.TYPE 得到Class对象
Class<Integer> type = Integer.TYPE;
System.out.println(type);
五、哪些类型有Class对象
1.外部类,成员内部类,静态内部类,局部内部类,匿名内部类
2.interface:接口
3.数组
4.enum:枚举
5.annotation:注解
6.基本数据类型
7.void
System.out.println(Integer.class);//外部类
System.out.println(Serializable.class);//接口
System.out.println(Integer[].class);//数组
System.out.println(Deprecated.class);//注解
System.out.println(Thread.State.class);//枚举
System.out.println(int.class);//基本数据类型
System.out.println(void.class);//void
System.out.println(Class.class);//Class自身
六、动态加载和静态加载
基本说明:
反射机制是Java实现动态语言的关键,通过反射实现类动态加载。
1. 静态加载:编译时加载相关的类,如果没有就报错,依赖性强。
2. 动态加载:运行时加载需要的类,如果运行时不用该类,则不报错(该类不存在或有其他问题),降低依赖性。