目录
一、类加载器
1.概述
2.过程
(1)类加载时机
(2)类加载过程
加载
验证
准备
解析
初始化
3.分类
(1)启动类加载器(Bootstrap ClassLoader):虚拟机内置的类加载器,底层是c++,最顶层
(2)平台类加载器(Platform Classloader):负责加载JDK中一些特殊的模块
(3)系统类加载器(System Classloader):负责加载用户类路径上所指定的类库,也称为应用程序类加载器
(4)自定义类加载器(这是自定的,用的不多)
4.双亲委派模型
5.常用方法
二、反射
1.概述
2.作用
3.反射的操作
(1)获取Class对象
(2)class对象的内部结构
(3)Class类中的常用方法
(4)获取Constructor对象
(5)Constructor类常用方法
(6)利用其构造对象创建User对象
(7)Filed类中常用方法
(8)通过反射获取成员变量
(9)Method类的常用方法
(10)通过反射获取成员方法并运行
一、类加载器
1.概述
类加载器:负责将.class文件(存储的物理文件)加载在到内存中
2.过程
(1)类加载时机
类在什么时候会被加载到内存中?
-
创建类的实例(对象)
-
调用类的类方法(静态方法)
-
访问类/接口的类变量,或者为该类变量赋值(静态变量)
-
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
-
初始化某个类的子类
-
直接使用java.exe命令来运行某个主类
总结:用到就加载,不用不加载
(2)类加载过程
-
加载:
-
验证:
-
准备
-
解析
-
初始化
加载
-
通过一个类的全限定名来获取此类的二进制字节流(通过包名+类名【全限定名】,获取这个类,准备用流进行传输)
-
将这个字节流所代表的静态存储结构转化为运行时数据结构(通过上步得到的流,将其字节码文件加载到内存中)
-
在内存中生成一个代表这个类的java.lang.Class对象(类加载到内存之后,虚拟机会创建一个该类的class对象来存储类中对应的内容)
任何类被使用时,系统都会为之建立一个java.lang.Class对象
验证
-
确保Class文件字节流中包含的信息符合当前虚拟机的要求,且不会危害虚拟机本身(检查文件中的信息是否符合虚拟机的规范,有没有安全隐患)
准备
-
负责为类的类变量(static修饰的变量)分配内存,并设置默认初始化值(初始化静态变量)
解析
-
将类的二进制数据流中的符号引用替换为直接引用(如果本类中用到了其他的类,此时需要找到其对应的类)
初始化
-
根据程序员通过程序制定的主观计划去初始化类变量和其他资源(静态变量赋值以及初始化其他资源)
3.分类
(1)启动类加载器(Bootstrap ClassLoader):虚拟机内置的类加载器,底层是c++,最顶层
(2)平台类加载器(Platform Classloader):负责加载JDK中一些特殊的模块
(3)系统类加载器(System Classloader):负责加载用户类路径上所指定的类库,也称为应用程序类加载器
(4)自定义类加载器(这是自定的,用的不多)
4.双亲委派模型
类加载器之间的层次关系,称之为类加载器的双亲委派模型
在这个模型当中,要求除了顶层的启动类加载器之外,其余的类加载器都应该有自己的父类加载器
这里的父子关系是逻辑上的继承,如想用自定义类加载器加载一个字节码文件,首先,它不会自己去尝试加载,而是将加载任务委派给其父类加载器去完成
一直委托到最顶层,这些加载器都有其各自的加载范围,当父类加载器无法完成这个加载请求的时候,它就会一层一层的往下返回,直到返回到能完成加载
的类加载器中,完成加载请求
//获取系统类加载器
classLoader systemclassLoader = classLoader.getSystemclassLoader():
//获取系统类加载器的父加载器,平台类加载器
ClassLoader classLoader1 = systemClassLoader.getParent();
//获取平台类加载器的父加载器 --- 启动类加载器
ClassLoader classLoader2 = classLoader1.getparent();
system.out.println("系统类加载器+ systemClassLoader);
system.out.printIn("平台类加载器”+ classLoader1);
System.out.printIn("系统类加载器”+ classLoader2);
5.常用方法
方法名 | 说明 |
---|---|
static ClassLoader getSystemClassLoader() | 获取系统类加载器 |
InputStream getResourceAsStream(String name) | 加载某一个资源文件 参数:文件路径 返回值:字节流对象 |
二、反射
1.概述
Java反射机制:
-
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
-
对于任意一个对象都能够调用它的任意属性和方法;
-
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制
Java反射机制(简洁说明):
-
无视修饰符获取类里面所有的属性和方法先获取配置文件中的信息
-
动态获取信息并创建对象和调用方法
2.作用
普通方式创建对象
-
无法访问私有属性和方法
用反射创建对象
-
反射调用私有属性:能无视权限修饰符
-
反射调用私有方法:能无视权限修饰符
总结:利用反射调用它类中的属性和方法时,能无视修饰符
举例:
如果用户有1个需求,并调用其特定方法
接收到程序后又更改需求n次
普通方式:
创建对象1,写其特有方法,get,set,构造,toString,在主方法中创建对象1,调用对象1的方法,再将代码打包发送,之后接收到第一次需求更改消息
创建对象2,写其特有方法,get,set,构造,toString,在主方法中删除对象1和其方法调用,重新创建对象2,调用对象2的方法,再将代码打包发送,之后接收到第二次需求更改消息
创建对象3,写其特有方法,get,set,构造,toString,在主方法中删除对象2和其方法调用,重新创建对象3,调用对象3的方法,再将代码打包发送,之后接收到第三次需求更改消息
...
创建对象n,写其特有方法,get,set,构造,toString,在主方法中删除对象,n-1和其方法调用,重新创建对象n,调用对象n的方法,再将代码打包发送,之后接收到第N次需求更改消息
总结:不灵活,需求更改要改代码
反射方式:动态获取信息,动态调用对象方法
会先将用户所有可能的需求全部过一遍,然后创建n个对象
创建对象1,写好特定方法,get,set,构造,toString,
创建对象2,写好特定方法,get,set,构造,toString,
创建对象3,写好特定方法,get,set,构造,toString,
...
创建对象n,写好特定方法
然后写一个配置文件
配置文件:
-
要创建对象的全类名(全限定名)
-
要调用的方法名
在主方法中读取配置文件的信息,读到什么就创建什么对象,读到什么方法就调用什么方法
用户更改需求时,不需要更改主方法中的代码,修改配置文件即可
总结:灵活
3.反射的操作
利用class对象来创建的
(1)获取Class对象
-
加载前(源代码阶段):用Class的静态方法forName(String 全类名)
-
已经进入到内存中(Class对象阶段):直接类名.class即可
-
已经手动创建对象时new 对象名(运行时阶段):对象.getClass()
public class User {
private String name;
private Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
private void run(){
System.out.println("User is running");
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Reflection01 {
public static void main(String[] args) {
//第一种
Class userClass1 = null;
Class userClass2 = null;
Class userClass3 = null;
try {
userClass1 = Class.forName("reflection.User");
System.out.println(userClass1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//第二种
userClass2 = User.class;
System.out.println(userClass2);
//第三种
userClass3 = new User().getClass();
System.out.println(userClass3);
//检查
System.out.println(userClass1 == userClass2);
System.out.println(userClass1 == userClass3);
System.out.println(userClass2 == userClass3);
}
}
(2)class对象的内部结构
(3)Class类中的常用方法
方法名 | 返回值类型 | 说明 |
---|---|---|
getConstructors() | Constructor<?>[] | 返回一个包含 Constructor对象的数组, Constructor对象反映了由该 class对象表示的类的所有公共构造函数 |
getDeclaredConstructors() | Constructor<?>[] | 返回反映由该 class对象表示的类声明的所有构造函数的 constructor对象的数组。 |
getConstructor(Class<?> ... parameterTypes) | Constructor< T > | 返回一个 constructor对象,该对象反映由该 class对象表示的类的指定公共构造函数。 |
getDeclaredConstructor(Class<?> ... parameterTypes) | Constructor< T > | 返回一个 Constructor对象,该对象反映由此 class对象表示的类或接口的指定构造函数。 |
getFields() | Field[ ] | 返回所有公共成员变量对象的数组 |
getDeclaredFields() | Field[ ] | 返回所有成员变量对象的数组 |
getField(String name) | Field | 返回单个公共成员变量对象 |
getDeclaredField(String name) | Field | 返回单个成员变量对象 |
getMethods() | Method[ ] | 返回所有公共成员方法对象的数组,包括继承的 |
getDeclaredMethods() | Method[ ] | 返回所有成员方法对象的数组,不包括继承的 |
getMethod(String name, Class<?>... parameterTypes) | Method | 返回单个公共成员方法对象 |
getDeclaredMethod(String name, Class<?>... parameterTypes) | Method | 返回单个成员方法对象 |
(4)获取Constructor对象
User对象
public class User {
private String name;
private Integer age;
public Long id;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
private User(String name){
this.name = name;
}
public User(String name, Integer age, Long id) {
this.name = name;
this.age = age;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
private void run(){
System.out.println("User is running");
}
private void run(String name,Long id){
System.out.println("id为"+id+"的用户:"+name+" is running");
}
private String run(String name,Long id,Integer age){
return "id为"+id+"的用户:"+name+"年龄:"+age+" is running";
}
public void work(){
System.out.println("User is working");
}
public void work(String name){
System.out.println(name + " is working");
}
public String work(String name,Long id){
return "id为"+id+"的用户:"+name+" is working";
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
测试:
public class Reflection02 {
public static void main(String[] args) {
Class<User> userClass = User.class;
Constructor<?>[] constructors01 = userClass.getConstructors();
for (int i = 0; i < constructors01.length; i++) {
System.out.println(constructors01[i]);
}
System.out.println("----------------------------------------------------");
Constructor<?>[] constructors02 = userClass.getDeclaredConstructors();
for (int i = 0; i < constructors02.length; i++) {
System.out.println(constructors02[i]);
}
}
}
(5)Constructor类常用方法
方法名 | 返回值类型 | 说明 |
---|---|---|
T newInstance(Object... initargs) | 创建出来的对象 | 根据指定的构造方法创建对象 |
(6)利用其构造对象创建User对象
public class Reflection03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//利用有参构造创建User对象
method01();
//利用无参构造创建User对象
method02();
//空参简写
method03();
//利用私有构造创建User对象,(暴力反射)
method04();
}
private static void method04() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> userClass = Class.forName("reflection.User");
final Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class);
//被private修饰的是不能直接使用的
//如果用反射强行获取需要临时取消访问检查
declaredConstructor.setAccessible(true);
User user = (User) declaredConstructor.newInstance("san");
System.out.println(user);
}
private static void method03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<?> userClass = Class.forName("reflection.User");
//在Class类中,有一个newInstance方法,可以利用空参直接创建对象
//此方法已过时,替换为getDeclaredConstructor().newInstance()
User user1 = (User)userClass.newInstance();
User user2 = (User)userClass.getDeclaredConstructor().newInstance();
System.out.println(user1);
System.out.println(user2);
}
private static void method02() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> userClass = Class.forName("reflection.User");
Constructor<?> constructor = userClass.getConstructor();
User user1 = (User) constructor.newInstance();
System.out.println(user1);
}
private static void method01() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class<?> userClass = Class.forName("reflection.User");
Constructor<?> constructor = userClass.getConstructor(String.class, Integer.class);
User user2 = (User) constructor.newInstance("小明", 29);
System.out.println(user2);
}
}
(7)Filed类中常用方法
方法名 | 返回值类型 | 说明 |
---|---|---|
set(Object object,Object value) | void | 给指定对象的成员变量赋值 |
get(Object obj) | Object | 返回指定对象的Field的值 |
(8)通过反射获取成员变量
-
获取class对象
-
获得Field对象
-
赋值或获取值
public class Reflection04 {
public static void main(String[] args) throws NoSuchFieldException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
Class<User> userClass = User.class;
// method01(userClass);
// method02(userClass);
// method03(userClass);
// method04(userClass);
// method05(userClass);
method06(userClass);
}
private static void method06(Class<User> userClass) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Field name = userClass.getDeclaredField("name");
User user = userClass.getDeclaredConstructor().newInstance();
//取消访问检查
name.setAccessible(true);
//更改值
name.set(user,"小明");
//获取值
Object o = name.get(user);
System.out.println(user);
System.out.println(o);
}
private static void method05(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Field id = userClass.getDeclaredField("id");
//利用set方法赋值
//先创建一个User对象
User user = userClass.getDeclaredConstructor().newInstance();
//获得对象之后就可以赋值
id.set(user,1000L);
System.out.println(user);
}
private static void method04(Class<User> userClass) throws NoSuchFieldException {
final Field name = userClass.getDeclaredField("name");
System.out.println(name);
}
private static void method03(Class<User> userClass) throws NoSuchFieldException {
//想要获取到的成员变量必须是真实存在的,且必须是public修饰的
Field id = userClass.getField("id");
System.out.println(id);
}
private static void method02(Class<?> userClass) {
for (Field declaredField : userClass.getDeclaredFields()) {
System.out.println(declaredField);
}
}
private static void method01(Class<?> userClass) {
Field[] fields = userClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
}
}
(9)Method类的常用方法
方法名 | 返回值类型 | 说明 |
---|---|---|
invoke(Object o,Object... args) 参数一:用o对象调用该方法 参数二:调用方法的传递的参数(如果没有就不用写) | Object | 在具有指定参数的指定对象上调用此 方法 对象表示的基础方法。 调用方法 |
(10)通过反射获取成员方法并运行
-
获取class对象
-
获取Method对象
-
运行方法
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection05 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<User> userClass = User.class;
//获取所有公共成员方法
method01(userClass);
System.out.println("--------------------------------");
//获取所有成员方法(包括继承的)
method02(userClass);
System.out.println("--------------------------------");
//获取单个公开成员方法
method03(userClass);
//获取单个成员方法
method04(userClass);
//运行成员方法
//运行公开成员方法(无参无返回值)
method05(userClass);
//运行公开成员方法(有参无返回值)
method06(userClass);
//运行成员方法(无参无返回值)
method07(userClass);
//运行成员方法(有参无返回值)
method08(userClass);
//运行公开成员方法(有返回值)
method09(userClass);
//运行成员方法(有返回值)
method10(userClass);
}
private static void method10(Class<User> userClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
User user = userClass.getDeclaredConstructor().newInstance();
Method run = userClass.getDeclaredMethod("run", String.class, Long.class, Integer.class);
run.setAccessible(true);
String invoke = (String) run.invoke(user, "小王", 201L,10);
System.out.println(invoke);
}
private static void method09(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
User user = userClass.getDeclaredConstructor().newInstance();
Method work = userClass.getMethod("work", String.class, Long.class);
work.setAccessible(true);
String invoke = (String) work.invoke(user, "小王", 200L);
System.out.println(invoke);
}
private static void method08(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
User user = userClass.getDeclaredConstructor().newInstance();
Method run = userClass.getDeclaredMethod("run",String.class,Long.class);
run.setAccessible(true);
run.invoke(user,"小王",200L);
}
private static void method07(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
User user = userClass.getDeclaredConstructor().newInstance();
Method run = userClass.getDeclaredMethod("run");
run.setAccessible(true);
run.invoke(user);
}
private static void method06(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
User user = userClass.getDeclaredConstructor().newInstance();
Method work = userClass.getMethod("work",String.class);
work.invoke(user,"小明");
}
private static void method05(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
User user = userClass.getDeclaredConstructor().newInstance();
Method work = userClass.getMethod("work");
work.invoke(user);
}
private static void method04(Class<User> userClass) throws NoSuchMethodException {
Method run = userClass.getDeclaredMethod("run", String.class, Long.class);
System.out.println(run);
}
private static void method03(Class<User> userClass) throws NoSuchMethodException {
Method work = userClass.getMethod("work");
System.out.println(work);
}
private static void method02(Class<User> userClass) {
Method[] declaredMethods = userClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
}
private static void method01(Class<User> userClass) {
Method[] methods = userClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}