基础加强--类加载器&反射
类加载器--初步了解
类加载器--类加载时机
类加载的过程
字节码文件对象中存储类中的成员信息
类的加载过程-链接
- 验证
- 准备
- 解析
类加载过程--初始化和小结
- 总结
案例说明加载过程
- 验证安全隐患
类加载器的分类
类加载器--双亲委派模型
package com.loader;
//测试类加载器的使用
public class LoaderTest {
public static void main(String[] args) {
//获取系统类加载器
final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//获取系统类加载器的父加载器-----平台类加载器
final ClassLoader parentClassLoader = systemClassLoader.getParent();
//获取平台类加载器的父加载器-=--启动类加载器
final ClassLoader loader = parentClassLoader.getParent();
System.out.println("系统类加载器"+systemClassLoader);
System.out.println("父类加载器"+parentClassLoader);
System.out.println("启动类加载器"+loader);
}
}
类加载器--常用方法
需要注意的是:需要加载的文件要写在src文件夹下面
package com.loader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class LoaderTest1 {
public static void main(String[] args) throws IOException {
/*
static ClassLoader getSystemClassLoader();获取系统类加载器
InputStream getResourceAsStream(String name);加载某一个资源文件
*/
//1.获取系统类加载器
final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//2.利用类加载器去加载一个指定的文件
final InputStream is = systemClassLoader.getResourceAsStream("prop.properties");
Properties properties = new Properties();
properties.load(is);
System.out.println(properties);
is.close();
}
}
反射
反射--概括
在过去的方式创建对象并调用方法的这种方式是死的,当改变了要调用的方法,大部分代码要重写。而反射创建对象并调用方法则更灵活
- 总结
获取calss对象
关于字节码文件对象见上面的类加载器的内容*
- 获取字节码文件对象的方式
package com.reflect;
//反射的三种创建对象的方式
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
//1.仅仅编译还没有被加载(源代码阶段)
final Class<?> clazz = Class.forName("com.reflect.Student");
System.out.println(clazz);//class com.reflect.Student
//2.该类被加载,创建了字节码文件的对象
final Class<Student> clazz1 = Student.class;
System.out.println(clazz1);//class com.reflect.Student
//3.该类的对象被创建
final Student student = new Student();
System.out.println(student.getClass());//class com.reflect.Student
}
}
- 总结
获取Constructor对象
-
演示见以前的
注意:被private修饰的构造方法不能直接使用(如果用反射直接使用将会报错),如果用反射强行使用需要临时取消访问检查 -
举例:临时取消访问检查
package com.reflect;
public class Student {
private String name;
private int age;
public Student() {
}
private Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
}
package com.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//使用反射创建对象()
public class ConstructorTest1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
method1();
}
private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//1.获取字节码文件对象
final Class<?> clazz = Class.forName("com.reflect.Student");
//2.获取构造方法的对象
final Constructor<?> con = clazz.getDeclaredConstructor(String.class, int.class);
con.setAccessible(true);//临时取消该构造方法的权限检查
//3.利用构造方法创建对象
final Student s1 = (Student) con.newInstance("张三", 17);
System.out.println(s1);
}
}
- 如果不取消将会:
反射-小结
反射获取Field对象
利用Filed赋值和获取值
- 为什么这2个方法都需要传递对象
- get方法的使用