类加载器与反射
类加载器
类加载器:负责将.class文件(存储的物理文件)加载在内存中
加载器时机
1.创建类的实例(对象)
2.调用类的方法 (静态方法,类名直接调用)
3.访问类或者接口的类变量(静态变量,类名直接调用),或者为该类类变量赋值
4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
5.初始化某个类的子类(将类的父类字节码文件也加载到内存当中)
6.直接使用java.exe命令来运行某个主类
用到就加载,不用不加载
类加载的过程
类加载的过程的小结
当一个类被使用的时候,才会加载到内存
类加载的过程如下:加载、验证、准备、解析、初始化
类加载器的分类
public class ClassLoaderDemo{
psvm{
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//获取系统类加载器的父加载器 ---平台类加载器
ClassLoader classLoader1=systemClassLoader.getParent();
//获取平台类加载器的父加载器 ---启动类加载器
ClassLoader classLoader2=classLoader1.getParent();
sout("系统类加载器"+systemClassLoader );
.... }}
public class ClassLoaderDemo2{
psvm{
//获取系统类加载器
ClassLoader systemClassLoader=ClassLoader.getSystemClassLoader();
//利用加载器去加载一个指定的文件
//参数:文件的路径
//返回值:字节流
//prop.properties 创建在src路径下
InputStream resourceAsStream =systemClassLoader.getResourceAsstream("prop.properties");
Properties prop=new Properties();
prop.load(is);
sout(prop);
is.close(); }
}
反射
反射概述
java反射机制
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意属性和方法
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制
Java反射机制
利用反射可以无视修饰符获取类里面所有的属性和方法
先获取配置文件中的信息,动态获取信息并创建对象和调用方法
获取Class类的对象
//获取class对象的三种方法
public class ReflectDemo1{
psvm{
//1.Class类中的静态方法forName("全类名");
//全类名:包名+类名
Class clazz=Class.forName("com.itheima.myreflect.Student");
sout(clazz);
//2.通过class属性来获取
Class clazz2=Student.class;
sout(clazz2);
//3.利用对象的getClass方法来获取class对象
//getClass方法是定义在Object类中
Student s=new Student();
Class clazz3=s.getClass();
sout(clazz3);
}
}
获取Class类的对象
Class.forName{"全类名"};
类名.class
对象.getClass();
public class ReflectDemo1{
psvm{
//1.获取Class对象
Class clazz=Class.forName("com.itheima.myreflect3.Student");
//得到所有公共构造方法对象的数组
Constructor[] constructs=clazz.getConstructors();
for(Constructor constructor:constructors){
sout(constructor);}
//获得所有构造方法对象的数组
Constructor[] constructs1=clazz.getDeclaredConstructors();
for(Constructor constructor:constructors1){
sout(constructor);}
//获得单个公共构造方法对象
//小括号中,一定要跟构造方法的形参保持一致
Constructor constructor2=clazz.getConstructor();
sout(constructor2);
//获得有参构造,小括号中,一定要跟构造方法的形参保持一致
Constructor constructor3=clazz.getConstructor(String.class,int.class);
sout(constructor3);
//获得单个构造方法 小括号中,一定要跟构造方法的形参保持一致(获得私有的或共有构造方法)
Constructor constructor4=clazz.getDeclaredConstructor(String.class);
sout(constructor4);
}}}
Constructor类中用于创建对象的方法
T newInstance(Object...initargs):根据指定的构造方法创建对象
public class ReflectDemo2{
psvm{
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取构造方法对象
Constructor constructor=clazz.getConstructor(String.class,int.class);
//3.利用newInstance创建Student的对象
Student student=(Student)constructor.newInstance("zhangsan",23);
sout(student);
//创建一个空参的student对象
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取构造方法对象
Constructor constructor=clazz.getConstructor();
//3.利用空参来创建Student的对象
Student student=(Student)constructor.newInstance();
sout(student);
//创建空参的简写格式
Class clazz=Class.forName("com.itheima.myreflect.Student");
//在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象
Student student=(Student)clazz.newInstance();
sout(student);
//获取一个私有的构造方法并创建对象
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取一个私有化的构造方法
Constructor constructor=clazz.getDeclaredConstructor(String class);
//被private修饰的成员,不能直接使用的
//如果用反射强行获取并使用,需要临时取消访问检查
constructor.setAccessible(true);
//3.直接创建对象
Student student=(Student)constructor.newInstance("zhangsan");
sout(student);
}
}
反射小结
反射获取成员变量
public class ReflectDemo1{
psvm{
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取Field对象
Filed[] fields=clazz.getFields();//返回所有公共成员变量对象的数组
//3.遍历
for(Filed field:fields){
sout(field);
//获得所有成员变量对象的数组
//获取所有的Field对象
Field [] fields1=clazz.getDeclareFields();
//3.遍历
for(Field field:fields1){
sout(field);
//获取单个公共成员变量对象
//获取name这个成员变量
//想要获取的成员变量必须是真实存在的 //且是public修饰的
Field field=clazz.getField("name");
//打印
sout(field);
//获取单个成员变量对象
//包括private ,public
Filed field=clazz.getDeclaredField("money");
sout(field);
}
}}}
赋值或者获取值
void set(Object obj,Object value):赋值(给指定对象的成员变量赋值)
Object get(Object obj)获取值(返回指定对象的Field的值)
public class ReflectDemo2{
psvm{
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取name这个Field对象
Field field=clazz.getField("name");
//3.利用set方法进行赋值
//3.1先创建一个Student对象,无参构造
Student student=clazz.newInstance();
//3.2有了对象才可以给指定对象进行赋值
field.set(student,"zhangsan");
sout(student);
//Object get (Object obj)返回由该Field标示的字段在指定对象上的值
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取成员变量Field的对象
Field field=clazz.getDeclaredField("money");
//3.取消一下访问检查
field.setAccessible(true);
//4.调用get方法来获取值
//4.1创建一个对象
Student student1=(Student)clazz.newInstance();
//4.2获取指定对象的money的值
Object o=field.get(student1);
//5.打印一下
sout(o);
}
}
反射获取成员方法并运行
public class ReflectDemo{
psvm{
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取成员方法对象
Method[] methods=clazz.getMethods();
//3.遍历
for(Method method:methods){
sout(method);
//获取所有成员方法对象的数组,不包括继承的
Method[] methods=clazz.getDeclareMethods();
//遍历一下数组
for(Method method:methods){
sout(method);
//返回单个公共成员方法对象
//获取成员方法function1
Method method1=clazz.getMethod("function1");
//打印
sout(method1);
//获取一个有形参的方法
Method method2=clazz.getMethod("function2",String.class);
sout(method2);
//获取单个成员方法,包含私有的
Method method3=clazz.getDeclaredMethod("show");
//打印
sout(method3);
}}}}
反射获取成员方法并运行
Object invoke(Object obj,Object...args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
public class ReflectDemo{
psvm{
//1.获取class对象
Class clazz=Class.forName("com.itheima.myreflect.Student");
//2.获取里面的Method对象
Method method=clazz.getMethod("function4",String.class);
//3.运行function4方法就可以了
//3.1创建一个Student对象,当做方法的调用者
Student student=(Student)clazz.newInstance();
//3.2运行方法
Object result=method.invoke(student,"zhangsan");
//4.打印一下返回值
sout(result);
}
}