- Class也是类,因此也继承Object类
- Class类对象并不是new出来的,而是系统创建的
- 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
- 每个类的实例都会记得自己是由哪个Class实力所生成
- 通过Class可以完整地得到一个类的完整结构,通过一系列API
- Class对象是存放在堆中的
- 类的字节码二进制数据,是存放在方法区的,有的地方成为类的元数据(包括方法代码,变量名,方法名,访问权限等)
2:(一)传统new对象 ClassLoader类源码
public Class<?> loadClass(String name) throws ClassNotFoundException{
return loadClass(name,false);
}
(二)反射方式 同样进入ClassLoader中
3:
Class cls1=Class.forName("classfullpath");
Class cls2=Class.forName("classfullpath");
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());//cls1与cls2相同,
//所以Class类对象只加载一次(同一个类)
Class常用方法
- 获取Car类对应的Class对象
Class<?> cls=Class.forName(classAllPath)
- 输出cls
System.out.println(cls);//显示cls对象是哪个类的Class对象
System.out.println(cls.getClass());//输出运行类型 java.lang.Class
- 得到包名
cls.getPackage().getName()
- 得到全类名
cls.getName()
- 通过cls创建对象实例
Car car=(Car)cls.newInstance();
- 通过反射获取属性(brand属性)
Field brand=cls.getField("brand");//getField在加载阶段为数组
- 通过反射给属性赋值
brand.set(car,"五菱");
//通过反射给car对象的brand属性赋予“五菱”值
- 得到所有属性(字段)
Field[] fields=cls.getFields();
获取Class对象
- 编译阶段:Class.forName()
//已知全类名,且该类在类路径下多用途配置文件读取类的全路径,加载类 - 加载阶段:类.Class
//已知具体的类,最安全性能最高。多用于参数传递,比如通过反射得到对应构造器对象
3.运行阶段:对象.getClass()
//已知对象实例
类加载器
- 先得到类加载器(car)
ClassLoader classLoader=car.getClass().getClassLoader();
- 通过类加载器得到Class对象
Class cls=classLoader.loadClass(classAllPath);
基本数据类型:数据类型.class
基本数据类型包装类:包装类.TYPE
注:int.class与Integer.TYPE的hashCode()相同
类加载
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载
①静态加载:编译时加载相关类,如果没有则报错,依赖性太强
②动态加载:运行时加载需要的类,如果运行时不用该类则不会报错,降低了依赖性
Dog dog=new Dog();//静态加载
Class cls=Class.forName("Dog")//反射->动态加载
Object o=cls.newInstance();
Method m=cls.getMethod("hi");
m.invoke(o);
类加载时机:
①创建对象时(new)
②子类被加载时,父类也加载
③调用类中的静态成员时
④反射
①~③静态加载
④动态