类加载器
类加载时机
- 创建类的实例(对象)
- 调用类的类方法(方法为静态方法)
- 访问类或者接口的类变量,或者为该类变量赋值(静态变量)
- 使用反射的方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
类加载的过程
加载
链接
初始化
类加载器的分类
- 启动类加载器(Bootstrap Classloader):虚拟机内置的类加载器;
- 平台类加载器(Platform Classloader):负责加载JDK中一些特殊的模块;
- 系统类加载器(System.Classloader):负责加载用户类路径上所指定的类库。
双亲委派模型
public class ClassLoaderTest1 {
public static void main(String[] args) {
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//获取系统类加载器的父加载器,即平台类加载器
ClassLoader parent1 = systemClassLoader.getParent();
//获取平台类加载器的父加载器,即启动类加载器
ClassLoader parent2 = parent1.getParent();
System.out.println("系统类加载器"+systemClassLoader);
System.out.println("平台类加载器"+parent1);
System.out.println("启动类加载器"+parent2);
}
}
类加载器常用方法
方法名 | 说明 |
---|---|
public static ClassLoader getSystemClassLoader() | 获取系统类加载器 |
public InputStream getResourceAsStream(String name) | 加载某一个资源文件 |
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ClassLoaderTest2 {
public static void main(String[] args) throws IOException {
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//利用加载器去加载一个指定的文件
//参数:文件的路径
//返回值:字节流
InputStream is = systemClassLoader.getResourceAsStream("prop.properties");
Properties prop = new Properties();
prop.load(is);
System.out.println(prop);
is.close();
}
}
反射
概述
Java反射机制
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法(无视修饰符);这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制(先获取配置文件中的信息,动态获取信息并创建对象和调用方法)。
获取class对象
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException {
//Class类中的静态方法forName("全类名")
//全类名:包名+类名
Class clazz = Class.forName("reflect.Student");
System.out.println(clazz);
//通过class属性获取
Class clazz2 = Student.class;
System.out.println(clazz2);
//利用对象的getClass方法来获取class对象
//getClass方法是定义在Object类中的
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz3);
}
}
获取Constructor对象
package reflect2;
public class Student {
private String name;
private int age;
//私有的有参构造方法
private Student(String name){
System.out.println("name的值为:"+ name);
System.out.println("private...Studet...有参构造方法");
}
//公共的无参构造方法
public Student(){
System.out.println("public...Student...无参构造方法");
}
//公共的有参构造方法
public Student(String name,int age){
System.out.println("name的值为:"+name+"age的值为:"+age);
System.out.println("public...Student...有参构造方法");
}
}
package reflect2;
import java.lang.reflect.Constructor;
public class ReflectTest2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
//1.获取class对象
Class clazz = Class.forName("reflect2.Student");
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("---------------");
//Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("---------------");
//Constructor<T> getConstructor(Class<?>...parameterTypes):返回单个公共构造方法对象
//小括号中,一定要跟构造方法的形参保持一致
Constructor constructor = clazz.getConstructor();
System.out.println(constructor);
Constructor constructor1 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor1);
System.out.println("---------------");
//Constructor<T> getDeclaredConstructor(class<?>...parameterTypes):返回单个构造方法对象
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
}
}
利用Constructor创建对象
- T newInstance(Object…initargs):根据指定的构造方法创建对象;
package reflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectTest3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取class对象
Class clazz = Class.forName("reflect2.Student");
//获取构造方法对象
Constructor constructor = clazz.getConstructor(String.class,int.class);
//利用newInstance创建Student对象
Student student = (Student) constructor.newInstance("huahua", 18);
System.out.println(student);
System.out.println("---------------");
Constructor constructor1 = clazz.getConstructor();
Student student1 = (Student) constructor1.newInstance();
System.out.println(student1);
System.out.println("---------------");
//获取一个私有的构造方法并创建对象
//获取一个私有化的构造方法
Constructor constructor2 = clazz.getDeclaredConstructor(String.class);
//被private修饰的成员,不能直接使用
//如果反射强行获取并使用,需要临时取消访问检查
constructor2.setAccessible(true);
//创建对象
Student student2 = (Student) constructor2.newInstance("huahua");
System.out.println(student2);
}
}
小结
- 获取class对象
- 三种方式-------Class.forName(“全类名”)
- 获取里面的构造方法对象
- getConstructor(Class<?>…parameterTypes)
- getDeclaredConstructor(Class<?>…parameterTypes)
- 如果是public的,直接创建对象
- newInstance(Object…initargs)
- 如果是非public的,需要临时取消检查,然后在创建对象
- setAccessible(boolean) 暴力反射
获取Field对象
- Field[] getFields():返回所有公共成员变量对象的数组
- Field[] getDeclaredFields():返回所有成员变量对象的数组
- Field getField(String name):返回单个公共成员变量对象
- Field getDeclaredField(String name):返回单个成员变量对象
package reflect3;
public class Student {
public String name;
public int age;
public String gender;
private int money = 300;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", money=" + money +
'}';
}
}
package reflect3;
import java.lang.reflect.Field;
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//Field[] getFields():返回所有公共成员变量对象的数组
//获取class对象
Class clazz = Class.forName("reflect3.Student");
//获取Field对象
Field[] fields = clazz.getFields();
//遍历
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-----------");
//Field[] getDeclaredFields():返回所有成员变量对象的数组
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("-----------");
//Field getField(String name):返回单个公共成员变量对象
//想要获取的成员变量必须是真实存在的,且必须是public修饰的
Field name = clazz.getField("name");
System.out.println(name);
System.out.println("-----------");
//Field getDeclaredField(String name):返回单个成员变量对象
Field money = clazz.getDeclaredField("money");
System.out.println(money);
}
}
获取Field对象赋值或获取值
- void set(Object obj,Object value):给obj对象的成员变量赋值为value
- Object get(Object obj):返回由该Field表示的字段在指定对象上的值
package reflect3;
import java.lang.reflect.Field;
public class ReflectTest2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
//void set(Object obj,Object value):给obj对象的成员变量赋值为value
//Object get(Object obj):返回由该Field表示的字段在指定对象上的值
//获取class对象
Class clazz = Class.forName("reflect3.Student");
//获取name这个Field对象
Field name = clazz.getField("name");
//利用set方法进行赋值
//先创建一个Student对象
Student student = (Student) clazz.newInstance();
//有了对象才可以给指定对象进行赋值
name.set(student,"花花");
System.out.println(student);
System.out.println("-------------");
//获取成员变量Field对象
Field money = clazz.getDeclaredField("money");
//取消一下访问检查
money.setAccessible(true);
//调用get方法来获取值
//创建一个对象
//获取指定对象的money值
Object o = money.get(student);
System.out.println(o);
}
}
反射获取成员方法并运行
获得Method对象
- Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
- Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
- Method getMethod(String name,Class<?>…parameterTypes):返回单个公共成员方法对象
- Method getDeclaredMethod(String name,Class<?>…parameterTypes):返回单个成员方法对象
package reflect4;
public class Student {
//私有的,无参返回值
private void show(){
System.out.println("私有的show方法,无参返回值");
}
//公共的无参无返回值
public void function1(){
System.out.println("function1方法,无参无返回值");
}
//公共的,有参无返回值
public void function2(String name){
System.out.println("function2方法,有参无返回值,参数为"+name);
}
//公共的,无参有返回值
public String function3(){
System.out.println("functon3方法,无参有返回值");
return "aaa";
}
//公共的,有参有返回值
public String function4(String name){
System.out.println("function4方法,有参有返回值,参数为"+name);
return "bbb";
}
}
package reflect4;
import java.lang.reflect.Method;
public class ReflectTest1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
//获取class对象
Class clazz = Class.forName("reflect4.Student");
//获取成员方法对象
Method[] methods = clazz.getMethods();
//遍历
for (Method method : methods) {
System.out.println(method);
}
System.out.println("--------------");
//Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method[] methods1 = clazz.getDeclaredMethods();
for (Method method : methods1) {
System.out.println(method);
}
System.out.println("--------------");
//Method getMethod(String name,Class<?>...parameterTypes):返回单个公共成员方法对象
Method function1 = clazz.getMethod("function1");
System.out.println(function1);
System.out.println("--------------");
//获取一个有形参的方法function2
Method function2 = clazz.getMethod("function2", String.class);
System.out.println(function2);
System.out.println("--------------");
//Method getDeclaredMethod(String name,Class<?>...parameterTypes):返回单个成员方法对象
Method show = clazz.getDeclaredMethod("show");
System.out.println(show);
}
}
利用Method对象运行方法
- Object invoke(Object obj,Object…args):运行方法
- 参数一:用obj对象调用该方法
- 参数二:调用方法传递的参数(如果没有就不写)
- 返回值:方法的返回值(如果没有就不写)
package reflect4;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
//获取class对象
Class clazz = Class.forName("reflect4.Student");
//获取里面的Method对象 function4
Method function4 = clazz.getMethod("function4", String.class);
//运行function4
//创建一个Student对象,当作方法的调用者
Student student = (Student) clazz.newInstance();
//运行方法
Object result = function4.invoke(student, "花花");
System.out.println(result);
}
}