1、类加载器
1.1类加载时机
创建类的实例
调用类的类方法
访问类或者接口的类变量,或者为该类变量赋值
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
初始化某个类的子类
直接使用java.exe命令来运行某个主类
1.2常见的类加载器
Bootstrap class loader
虚拟机的内置类加载器,通常表示为null,用来加载Java的核心库(jre/lib/rt.jar)
Platform class loader
拓展类加载器,用来加载Java的扩展库(jre/ext/*.jar)
System class loader
应用程序类加载器,根据Java应用的类路径(CLASSPATH)来加载自定义的类
2、反射
2.1概念
将类的各个组成部分封装成其他对象,就是反射机制
2.2获取Class对象的方式
Class.forName(“全路径类名”)
通过Class类的静态方法forName传入全路径类名
类名.class
通过class属性获取
对象名.getClass()
通过Object类的getClass方法获取
注意
一个类的Class对象在内存中只有一个,多次获取的是同一个对象
package com.itfenghua01;
public class classDemo02 {
public static void main(String[] args) throws ClassNotFoundException {
//类名.class ,获取Class对象
Class<classLoaderDemo> c1 = classLoaderDemo.class;
System.out.println(c1);
Class<classLoaderDemo> c2 = classLoaderDemo.class;
System.out.println(c1==c2);
System.out.println("---------------");
classLoaderDemo s= new classLoaderDemo();
//对象名.Class ,获取Class对象
Class<? extends classLoaderDemo> c3 = s.getClass();
System.out.println(c1==c3);
System.out.println("---------------");
//Class 的静态方法 Class.forName("全路径")获取class对象名
Class<?> c4 = Class.forName("com.itfenghua01.classLoaderDemo");
System.out.println(c1==c4);
}
}
2.3Class对象的功能
2.3.1获取成员变量
Field[] getFields()
获取所有public修饰的成员变量
Field getField(String name)
获取指定的public修饰的成员变量
Field[] getDeclaredFields()
获取所有的public/private修饰的成员变量
Field getDeclaredField(String name)
获取指定的public/private修饰的成员变量
2.3.2获取构造方法
Constructor[] getConstructors()
获取所有的public修饰的构造方法
Constructor[] getDeclaredConstructors()
获取所有的public/private修饰的构造方法
Constructor getConstructor(Class…clazz)
获取指定的public的修饰的构造方法
Constructor getDeclaredConstructor(Class…clazz)
获取指定的public/private修饰的构造方法
2.3.3获取成员方法
Method[] getMethods()
获取所有的public修饰的成员方法
Method getMethod(String name,Class…clazz)
获取指定的public修饰的成员方法
Method[] getDeclaredMethods()
获取所有的public/private修饰的成员方法
Method getDeclaredMethod(String name,Class…clazz)
获取指定的public/private修饰的成员方法
package com.itfenghua01;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class reflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//根据全路径名获取Class
Class<?> c = Class.forName("com.itfenghua01.Student");
//获取一个构造方法
Constructor<?> con = c.getConstructor();
//根据构造方法创建对象
Object obj = con.newInstance();
//获取方法名数组
Method[] methods = c.getMethods();
//遍历方法名数组
for (Method mm:methods){
System.out.println(mm);
}
System.out.println("==========================");
Method[] sd = c.getDeclaredMethods();
for (Method me:sd){
System.out.println(me);
}
System.out.println("-------------------------");
//传入方法参数
Method method1 = c.getMethod("method1", String.class, int.class);
//调用方法
method1.invoke(obj, "ss", 12);
String name = method1.getName();
System.out.println(name);
System.out.println("__________________________");
Object o = c.newInstance();
Method method = c.getMethod("method1");
String name1 = method.getName();
//无返回值方法
method.invoke(o);
System.out.println(name1);
String name2 = c.getName();
System.out.println(name2);
System.out.println("^^^^^^^^^^^^^^^^^^");
Method method2 = c.getMethod("method2", String.class, int.class);
method2.invoke(o, "龙族", 5);
}
}
2.3.4获取全路径类名
String getName()
2.3.5注意事项
1.访问私有的属性和功能要先忽略安全检查
2.通过空参创建对象时,可以通过Class对象的newInstance方法,简化操作
2.4Class对象相关的类
2.4.1Field
获取值
Object get(Object obj)
设置值
void set(Object obj,Object value)
忽略安全检查
void setAccessible(boolean flag)
2.4.2Constructor
创建对象
T newInstance(Object…value)
2.4.3Method
执行方法
Object invoke(Object obj,Object…parameters)
获取方法名称
String getName()
2.5反射过程
1.获取Class对象(要反射哪个类中的内容)
2.获取要反射的具体内容的对象(Method,Field,Constructor)
3.执行具体的操作(获取值,设置值,执行方法)
2.6类加载器ClassLoader
获取
Class对象的getClassloder()方法
使用(结合Properties)
InputStream in = 加载器对象.getResourceAsStream(“src目录下的文件”)
Properties pro = new Properties()
pro.load(in)
3、模块化
3.1基本使用
1.在模块的src目录下新建一个名为module-info.java的描述性文件
2.模块导出格式:exports 包名;
3.模块依赖格式: requires 模块名;
写模块名报错,需要按下Alt+Enter提示,然后选择模块依赖
3.2模块服务
1.提供者模块添加:provides 接口名 with 实现类名;
2.使用者模块添加:uses 接口名;
3.测试类中使用
加载服务
ServiceLoader<接口名> myServices = ServiceLoader.load(接口名.class);
遍历服务
for(MyService my : myServices) {
//调用接口中的方法
my.service();
}