类加载器机反射简单了解
类加载器初步了解
类加载器:负责class文件(存储的物理文件)加载到内存中
Java文件--》(编译)class文件(字节码文件)--->(类加载器)虚拟机中线程的六种状态:
类加载时机
类在什么时候会被加载到内存中呢?
1.创建类得实例(对象)
2.调用类的方法
3.访问类或者接口的类变量,或者为该类变量赋值
4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
5.初始化某个类的子类
6.直接使用java.exe命令来运行某个主类
简单来说用到就加载,不用不加载
类加载的过程
加载->链接(验证+准备+解析)->初始化
加载:通过一个类的全限定名来获取此类的二进制字节流,将这个字节流所代表的静态存储结构准换为运行时数据结构,在内存中生一个代表这个类的java.lang.Class对象,任何类被使用时,系统都会为之建立一个java.lang.Class对象
简单来说通过包名+类名,获取这个类,准备用流进行传输
在这个类加载到内存中
加载完毕创建一个class对象
链接:链接阶段第一步加载,这一阶段为了确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全。
简单来说就是查看文件的信息是否符合虚拟机规范有没有安全隐患
准备:负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值,初始化静态变量
解析:将类的二进制数据流中的符号引用替换为直接引用
简单来说就是本类中如果用到了其他类,此时就需要找到对应的类
初始化:根据程序员通过程序指定的主观计划去初始化变量和其他资源
简单来说就是静态变量赋值以及初始化其他资源
类加载器的分类
三种:
启动类加载器:(BootstarpClassLoader) 虚拟机内置的类加载器
平台类加载器:(PlatformClassloader) 负责加载JDK中一些特殊的模块
系统加载器(SystemClassloader) 负责加载用户类路径上所指定的类库
双亲委派模型:
三种启动类加载器还可以有自定义类加载器 UserClassloader
级别分为自定义加载器的父类加载器----》系统类加载器----》平台类加载器----》启动类加载器(顶级)
并不是代码中的extens中的继承关系 而是逻辑上的继承
代码:
public class test {
public static void main(String[] args) {
//获得系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//获得系统加载器的父加载器 ----平台加载器
ClassLoader parent = systemClassLoader.getParent();
//获得平台类加载器的父加载器 ----启动类加载器
ClassLoader parent1 = parent.getParent();
System.out.println("系统加载器"+systemClassLoader);
System.out.println("平台加载器"+parent);
System.out.println("启动类加载器"+parent1);
// 系统加载器sun.misc.Launcher$AppClassLoader@14dad5dc
// 平台加载器sun.misc.Launcher$ExtClassLoader@1b6d3586
// 启动类加载器null
}
}
类加载器:
public static ClassLoader getSystemClassLoader() 获取系统类加载器
public InputStream getResourceAsStream(String name) 加载每一个资源文件
代码:
public class test2 {
public static void main(String[] args) throws IOException {
// public static ClassLoader getSystemClassLoader() 获取系统类加载器
// public InputStream getResourceAsStream(String name) 加载每一个资源文件
//获得系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//利用加载器去加载一个指定的文件
//参数文件的路径
//返回值:字节流
InputStream is = systemClassLoader.getResourceAsStream("prop.properties");
Properties prop=new Properties();
prop.load(is);
System.out.println(prop);
is.close();
}
}
除此之外在SRC目录下创建prop.properties文件
反射概述
Java反射机制
是在运行状态中,对于任何一个类,都能够知道这个类的所有属性和方法;
是对于任何一个对象,都能够调用它的任意属性和方法;
这种动态获取信息以及动态调用对象方法的功能称之为Java语言的反射机制
用反射去创建对象,调用成员变量,调用成员方法 不管是什么权限修饰符修饰的,都可以调用它类中的属性和方法
简单来说就是利用反射可以无视修饰符获取类里面所有的属性和方法
先获取配置文件中的信息,动态获取信息并创建对象和调用方法
获取Class对象
以前调用一个类中的方法
创建这个类的对象(new)
用对象调用方法
反射去调用一个类中的方法
反射方式:创建对象(利用class对象来创建的)
反射方式:调用方法
{Java文件--》编译Class文件(字节码文件)---》}类加载器----》内存(Class对象)
{内的文件称之为源代码阶段} 使用Class类中的静态方法 forName{String className}
内存中是类名.class 就可以获取到反射对象了
最后一个就是我们自己创建的对象 new Student() 这个阶段就称之为Runtime运行阶段 使用对象.getClass()
代码:
创建一个学生类
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void study(){
System.out.println("我正在学习");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
创建一个测试类:
/**
* 创建对象的三种方式
*/
public class test3 {
public static void main(String[] args) throws ClassNotFoundException {
//1.Class类中的静态方法forName(全类名) 全类名=包名+类名
Class classs = Class.forName("com.sx.first.reflect.Student");
System.out.println(classs);
//2.通过Class属性来获取
Class classs2=Student.class;
System.out.println(classs2);
//3.利用对象的getClass方法来获取class对象
//getClass方法是定义在Object类中
Student s=new Student();
Class classs3 = s.getClass();
System.out.println(classs3);
//获取的对象都是一样的
System.out.println(classs==classs2);
System.out.println(classs2==classs3);
}
}
//class com.sx.first.reflect.Student
//class com.sx.first.reflect.Student
//class com.sx.first.reflect.Student
//true
//true
反射获取Constructor对象
Constuctor<?>[] getConstructors();
返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors();
返回所有构造方法的数组
Constructor(T) getConstructor(Class<?>... parameterTypes):
返回单个公共构造方法对象
小括号一定要和构造方法的形参保持一致
Constructor<T> getDeclaredConstructor (Class<?>... parameterTypes):
返回单个构造方法对象
代码:
一个学生类:
public class Student {
private String name;
private int age;
//私有的有参构造方法
private Student(String name){
System.out.println("name的值为"+name);
System.out.println("private....Student...有参构造方法");
}
//公共的无参构造方法
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...有参构造方法");
}
}
一个测试类
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//Constuctor<?>[] getConstructors();
//返回所有公共构造方法对象的数组
//1.先获取Class对象
Class aClass = Class.forName("com.sx.first.reflect2.Student");
Constructor[] constructors = aClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
//public com.sx.first.reflect2.Student()
//public com.sx.first.reflect2.Student(java.lang.String,int)
}
//Constructor<?>[] getDeclaredConstructors();
//返回所有构造方法的数组
Constructor[] declaredConstructor = aClass.getDeclaredConstructors();
for (Constructor constructor : declaredConstructor) {
System.out.println(constructor);
//private com.sx.first.reflect2.Student(java.lang.String)
//public com.sx.first.reflect2.Student()
//public com.sx.first.reflect2.Student(java.lang.String,int)
}
//Constructor(T) getConstructor(Class<?>... parameterTypes):
//返回单个公共构造方法对象
//小括号一定要和构造方法的形参保持一致
Constructor constructor1 = aClass.getConstructor();
System.out.println(constructor1);
Constructor constructor2= aClass.getConstructor(String.class, int.class);
System.out.println(constructor2);
//因为Studnet类中,没有只有一个int的构造,所以这里会报错
Constructor constructor3= aClass.getConstructor( int.class);
System.out.println(constructor3);
//Constructor<T> getDeclaredConstructor (Class<?>... parameterTypes):
//返回单个构造方法对象
Constructor constructor = aClass.getDeclaredConstructor(String.class);
System.out.println(constructor);
}
}
利用Constructor创建对象
T newlnstance(Object...initargs):根据指定的构造方法创建对象
学生类:
public class Student {
private String name;
private int age;
//私有的有参构造方法
private Student(String name){
System.out.println("name的值为"+name);
System.out.println("private....Student...有参构造方法");
}
//公共的无参构造方法
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...有参构造方法");
}
}
测试类:
public class test2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//T newlnstance(Object...initargs):根据指定的构造方法创建对象
//1.获取class对象
Class aClass = Class.forName("com.sx.first.reflect2.Student");
//根据指定的构造方法创建对象
//method1(aClass);.
//空参方法创建对象
//method2(aClass);
//空参方法创建对象 简写格式
//method3(aClass);
//获得一个私有化的构造方法
Constructor constructor = aClass.getDeclaredConstructor(String.class);
//如果被private修饰的成员,不能直接使用的
//如果使用反射强行获取并使用,需要临时取消访问插件
constructor.setAccessible(true);
//直接创建对象
Student studnet = (Student) constructor.newInstance("zhangsan");
System.out.println(studnet);
}
private static void method3(Class aClass) throws InstantiationException, IllegalAccessException {
//2.在class类中,有一个newlnstance方法,可以利用空参直接创建一个对象
Student student = (Student) aClass.newInstance();
System.out.println(student);
//public...student...无参构造方法
//com.sx.first.reflect2.Student@1b6d3586
}
private static void method2(Class aClass) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//空参方法创建对象
//2.获取构造方法对象
Constructor constructor = aClass.getConstructor();
//利用空参来创建Studnet对象
Student student = (Student) constructor.newInstance();
System.out.println(student);
//public...student...无参构造方法
//com.sx.first.reflect2.Student@383534aa 创建的学生对象
}
private static void method1(Class aClass) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//2.获取构造方法对象
Constructor constructor = aClass.getConstructor(String.class, int.class);
//3.利用newlnstance创建对象
Student student = (Student) constructor.newInstance("zhangsan", 23);
System.out.println(student);
//name的值zhangsanage的值为23
//public。。。Student...有参构造方法
}
}
反射小结: 获取class对象
三种方式 最常用的 ----》Class.forName("全类名")
获取里面的构造方法对象
getConstructor(Class<?>...parameterTypes)
getDeclaredConstructor(Class<?>...parameterTypes)
如果是public 直接创建对象
newInstance(Object...initargs)
如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean) 暴力反射
反射获取成员变量
1.获取class对象
2.获得Field对象
Fileld[] getFields():返回所有公共成员变量对象的数组
Fileld[] getDeclaredFilelds():返回所有成员变量对象的数组
Field getField(String name): 返回单个公共成员变量对象
Field getDeclaredField(String name): 返回单个成员变量对象
代码实例:
学生类:
public class Student {
public String name;
public int age;
public String gender;
private int money=300;
}
测试类:
public class test3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
// Fileld[] getFields():返回所有公共成员变量对象的数组
//获得反射对象
Class aClass = Class.forName("com.sx.first.reflect3.Student");
//返回所有的公共变量
//method(aClass);
// Fileld[] getDeclaredFilelds():返回所有成员变量对象的数组
//返回所有的变量
// method2(aClass);
// Field getField(String name): 返回单个公共成员变量对象
//返回单个公共成员变量对象
// method3(aClass);
// Field getDeclaredField(String name): 返回单个成员变量对象
Field declaredField = aClass.getDeclaredField("money");
System.out.println(declaredField);
}
private static void method3(Class aClass) throws NoSuchFieldException {
//想要获取的成员变量必须是真实存在的
//且必须是public修饰的
Field field = aClass.getField("name");
System.out.println(field);
}
private static void method2(Class aClass) {
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
//public java.lang.String com.sx.first.reflect3.Student.name
//public int com.sx.first.reflect3.Student.age
//public java.lang.String com.sx.first.reflect3.Student.gender
//private int com.sx.first.reflect3.Student.money
}
}
private static void method(Class aClass) {
Field[] fields = aClass.getFields();
//进行遍历
for (Field field : fields) {
System.out.println(field);
//public java.lang.String com.sx.first.reflect3.Student.name
//public int com.sx.first.reflect3.Student.age
//public java.lang.String com.sx.first.reflect3.Student.gender
}
}
}
3.赋值或者获取值
void set(Object,Object value):赋值 给指定对象的成员变量赋值
Object get(Object obj)获取值 返回指定对象的Field的值
学生类:
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 +
'}';
}
}
测试类:
public class test4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
// void set(Object,Object value):赋值 给指定对象的成员变量赋值
Class aClass = Class.forName("com.sx.first.reflect3.Student");
method1(aClass);
// Object get(Object obj)获取值 返回指定对象的Field的值
//获取成员变量的值
Field declaredFields = aClass.getDeclaredField("money");
//取消访问检查
declaredFields.setAccessible(true);
//调用get方法来获取值
//创建对象
Student studnet = (Student) aClass.newInstance();
//获取指定对象money的值
Object o = declaredFields.get(studnet);
//打印o
}
private static void method1(Class aClass) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
//2.获取name这个Field对象
Field name = aClass.getField("name");
//利用set方法进行赋值
//3.1创建一个student对象
Student student = (Student) aClass.newInstance();
//3.2有了对象才可以给指定对象赋值
System.out.println(student);
}
}
反射获取成员方法并运行
1.获得class对象
2.获得Method对象
Method[] getMethods();返回所有公共成员对象的数组,包括继承
Method[] getDeclareMethods();返回所有从成员方法对象的数组,不包括继承
Method getMethod(String name,Class<?>...parameterTypes);
Method getDeclaredMethod(String name,Class<?>...parameterTypes) 返回单个成员方法对象
代码:
学生类:
public class Student {
//私有的 无参无返回值
private void show(){
System.out.println("私有的show方法。。。无参无返回值");
}
//公共的 无参无返回值
public void method(){
System.out.println("公共的method方法...无参无返回值");
}
//公共的 有参无返回值
public void method1(String name){
System.out.println("公共的无参无返回值"+name);
}
//公共的 无参有返回值
public String method2(){
System.out.println("method2方法,无参有返回值");
return "返回值参数";
}
//公共的 有参有返回值
public String method3(String name){
System.out.println("method3方法,有参数 有返回值"+name);
return "返回值参数";
}
}
测试类:
public class test5 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//1. 第一步始终是获得class对象
Class aClass = Class.forName("com.sx.first.reflect4.Student");
// Method[] getMethods();返回所有公共成员对象的数组,包括继承
//获取成员方法对象
//method(aClass);
// Method[] getDeclareMethods();返回所有从成员方法对象的数组,不包括继承
// method1(aClass);
// Method getMethod(String name,Class<?>...parameterTypes);
//获取method方法
//method3(aClass);
// Method getDeclaredMethod(String name,Class<?>...parameterTypes) 返回单个成员方法对象
//获得一个私有额成员方法show
Method show = aClass.getDeclaredMethod("show");
System.out.println(show);
//private void com.sx.first.reflect4.Student.show()
}
private static void method3(Class aClass) throws NoSuchMethodException {
//method2(aClass);
//获得有形参的方法
Method method1 = aClass.getMethod("method1", String.class);
System.out.println(method1);
//public void com.sx.first.reflect4.Student.method1(java.lang.String)
}
private static void method2(Class aClass) throws NoSuchMethodException {
//第一个参数 是方法名
Method method = aClass.getMethod("method");
//打印一下
System.out.println(method);
//public void com.sx.first.reflect4.Student.method()
}
private static void method1(Class aClass) {
//得到Method对象
Method[] declaredMethods = aClass.getDeclaredMethods();
//遍历
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
//获得所有方法 不包括继承
// public void com.sx.first.reflect4.Student.method1(java.lang.String)
// private void com.sx.first.reflect4.Student.show()
// public java.lang.String com.sx.first.reflect4.Student.method2()
// public java.lang.String com.sx.first.reflect4.Student.method3(java.lang.String)
// public void com.sx.first.reflect4.Student.method()
}
}
private static void method(Class aClass) {
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
//打印多余的方法就是继承来的方法
// public void com.sx.first.reflect4.Student.method()
// public void com.sx.first.reflect4.Student.method1(java.lang.String)
// public java.lang.String com.sx.first.reflect4.Student.method2()
// public java.lang.String com.sx.first.reflect4.Student.method3(java.lang.String)
// public final void java.lang.Object.wait() throws java.lang.InterruptedException
// public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
// public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
// public boolean java.lang.Object.equals(java.lang.Object)
// public java.lang.String java.lang.Object.toString()
// public native int java.lang.Object.hashCode()
// public final native java.lang.Class java.lang.Object.getClass()
// public final native void java.lang.Object.notify()
// public final native void java.lang.Object.notifyAll()
}
}
}
3.运行方法
反射获取成员方法并运行
Object inwoke(Object,Object..args) ;运行方法
参数一:用obj对象调用该方法 //相当于调用者
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值 (没有就不写)
代码:
学生类:
public class Student {
//私有的 无参无返回值
private void show(){
System.out.println("私有的show方法。。。无参无返回值");
}
//公共的 无参无返回值
public void method(){
System.out.println("公共的method方法...无参无返回值");
}
//公共的 有参无返回值
public void method1(String name){
System.out.println("公共的无参无返回值"+name);
}
//公共的 无参有返回值
public String method2(){
System.out.println("method2方法,无参有返回值");
return "返回值参数";
}
//公共的 有参有返回值
public String method3(String name){
System.out.println("method3方法,有参数 有返回值"+name);
return "返回值参数";
}
}
测试类:
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
// Object inwoke(Object,Object..args) ;运行方法
// 参数一:用obj对象调用该方法 //相当于调用者
// 参数二:调用方法的传递的参数(如果没有就不写)
// 返回值:方法的返回值 (没有就不写)
//1.获取calss对象
Class aClass = Class.forName("com.sx.first.reflect4.Student");
//2.获得里边的method3对象
Method method3 = aClass.getMethod("method3", String.class);
//运行method3方法就好了
//创建一个Student对象 当作方法调用者
Student student = (Student) aClass.newInstance();
//运行方法
Object stu = method3.invoke(student, "zhangsan");
//打印返回值
System.out.println(stu);
// method3方法,有参数 有返回值zhangsan
// 返回值参数
}
}