类的加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
- 加载
就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象
- 连接
验证 是否有正确的内部结构,并和其他类协调一致。
准备 负责为类的静态成员分配内存,并设置默认初始化值。
解析 将类的二进制数据中的符号引用替换为直接引用。
- 初始化
类加载器的组组成:
- Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载,比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
- Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录
- System ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
理解:
1.程序运行时,类加载器将class文件载入数据共享区,并在堆中创建了一个class文件的对象。
2.在什么情况会初始化类(不是):
(1)创建类的实例
(2)初始化类的某个子类
(3)使用反射方式来强制创建某个类或接口对应的java.lang.Class对象 暂时写3种。
3.为什么用反射(运行时起作用)?
(1)为添加新功能(类)而不修改原有代码,要使用这个新功能时,通过这个class文件对象,拿出相应功能执行。拿出的方式,解剖的方式就是反射。程序通过反射从class文件把功能拿出来执行,随时给个新的类,随时都能运行。
(2)类先加载进入共享区,然后加载器给文件创建一个class文件对象,反射区解剖,用户无权创建和销毁这个对象。
获取class文件对象的三种方式
//1. Person p=new Person; Class c1=p.getClass(); //2. Class c2=Person.class; //3.字符串要包名.类名 Class c3=ClassForName("包名.类名");
注:第三种和前两种的区别
前两种你必须明确Person类型.
后面是指定这种类型的字符串就行.这种扩展更强.我不需要知道你的类.我只提供字符串,按照配置文件加载就可以了。
Class类似于String的引用类型。
获取构造器:
除private修饰外的构造器
Class c=Class.forName("wei.Person"); //获取除private修饰的多个构造器 Constructor []cons=c.getConstructors(); //获取除private修饰的, 指定参数类型所对应的构造方法,不写参数是空参构造器 Constructor cons1=c.getConstructor(String.class,int.class); //通过构造方法创建Object对象 Object obj=cons1.newInstance("lili",15); //父类Object不能调用子类的方法特有,要转型 Person p=(Person)obj; p.method3();
Class c=Class.forName("wei.Person"); //可直接获得运行时对象,前提是类又空参构造器 Object obj=c.newInstance();
注:同理获取所有构造器
改用调用getDeclaredConstructor()和getDeclaredConstructors()。
但不推荐这么做,因为破坏了类的封装性。
获取之后要传私有属性需要将 构造器引用.setAccessible(true),参数值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。参数值为 false 则指示反射的对象应该实施 Java 语言访问检查。
这个是父类的方法。
获取成员变量
- 返回一个成员变量
public Field getField(String name) 获取指定的 public修饰的变量
public Field getDeclaredField(String name) 获取指定的任意变量
- 返回多个成员变量
public Field[] getFields() 获取所有public 修饰的变量
public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)
例如:Field nameField = c.getField("name");
设置成员变量
public void set(Object obj, Object value)
在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值
public Object get(Object obj)
返回指定对象obj中,此 Field 对象表示的成员变量的值
例如:
Field ageField = c.getField("age"); ageField.get(obj); ageField.set(obj, 23);
获取方法
- 返回获取一个方法:
public Method getMethod(String name, Class<?>... parameterTypes)
获取public 修饰的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
获取任意的方法,包含私有的
参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型
- 返回获取多个方法:
public Method[] getMethods() 获取本类与父类中所有public 修饰的方法
public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)
例如: //获取一个方法: //public void method1() Method method = c.getMethod("method1", null);
使用方法
Method m4 = c.getMethod("method4", String.class); m4.invoke(obj, "啦啦啦");