类加载器&&反射

类加载器:负责将.class文件(存储的物理文件)加载到内存中

类加载时机:用到就加载,不用不加载
1、当new一个类时,即新建一个类;
2、调用类的静态方法、读取静态变量、或设置静态变量时;
3、当使用反射调用一个类时;
4、初始化一个子类时,如果其父类未初始化,则需要先初始化其父类;
5、程序运行时需要指定一个主类,即main方法所在的类,虚拟机会优先初始化这个类;
6、jdk7动态语言所支持的一些情况;

//通过ClassLoader.getSystemClassLoader()获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

//再通过系统类加载器调用getParent(),获取平台类加载器
ClassLoader classloader1 = systemClassLoader.getParent();

//再通过平台类加载器调用getParent(),获取启动类加载器
ClassLoader classloader2 = classloader1.getParent();

 //利用类加载器去加载指定的资源文件,参数:文件路径,返回值:字节流
        InputStream is = systemClassLoader.getResourceAsStream("prop.properties");

        Properties prop = new Properties();
        prop.load(is);

        System.out.println(prop);

        is.close();

反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

获取class对象

//获取class对象的三种方式

//1、Class类中的静态方法forName("全类名")
//全类名:包名+类名
Class clazz1 = Class.forName("com.lcl.reflect.Student");
System.out.println(clazz1);

//2、通过class属性获取
Class clazz2 = Student.class;
System.out.println(clazz2);

//3、利用对象的getClass()方法获取class对象
Student student = new Student();
Class clazz3 = student.getClass();
System.out.println(clazz3);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RoyeESa7-1656653021895)(C:\Users\StarrySea\Desktop\MarkDown学习\图片\类加载器&&反射12.jpg)]

获取Constructor对象

Class clazz = Class.forName("com.lcl.reflect.StudentReflectTest3");

//获取Constructor对象
getConstructors()、getDeclaredConstructors():这两者不用传参,不是指定构造,返回的是一个构造对象的数组,前者是所有公有构造,后者是所有构造
 getConstructor、getDeclaredConstructor:这两者需要传参,指定哪一个构造对象返回,前者是单个公有,后者单个所有

//Constructor<?>[] getConstructors()
//返回包含一个数组 Constructor对象反射由此表示的类的所有【公共】构造类对象。
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
    System.out.println(constructor);
}

System.out.println("--------------------------------------------");

//Constructor<?>[] getDeclaredConstructors()
//返回一个反映 Constructor对象表示的类声明的【所有】 Constructor对象的数组类。
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
    System.out.println(declaredConstructor);
}

System.out.println("--------------------------------------------");

//Constructor<T> getConstructor(类<?>... parameterTypes)
//返回一个 Constructor对象,该对象反映 Constructor对象表示的类的【指定】的【公共】类函数。
//小括号中,一定要跟构造方法的形参保持一致
Constructor constructor1 = clazz.getConstructor();//公有空参
System.out.println(constructor1);

Constructor constructor2 = clazz.getConstructor(String.class, int.class);//公有有参
System.out.println(constructor2);

System.out.println("---------------------------------------------");

//Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
//返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的【所有】【指定】类函数。
Constructor declaredConstructor1 = clazz.getDeclaredConstructor();//公有空参
System.out.println(declaredConstructor1);

Constructor declaredConstructor2 = clazz.getDeclaredConstructor(String.class, int.class);//公有有参
System.out.println(declaredConstructor2);

Constructor declaredConstructor3 = clazz.getDeclaredConstructor(String.class);//私有有参
System.out.println(declaredConstructor3);

使用Constructor对象创建对象

//T newInstance(object... initargs):根据指定的构造方法创建对象,参数是构造方法参数

//1、获取class对象
Class clazz2 = Class.forName("com.lcl.reflect.StudentReflectTest3");

//2、获取构造方法对象
Constructor constructor2 = clazz2.getDeclaredConstructor(String.class);

//被private修饰的成员,不能直接使用,如果用反射强行使用,需要临时取消访问检查,public修饰的成员不需要这一步
constructor2.setAccessible(true);

//3、利用newInstance()方法创建Student对象,要与对应的构造对象创建对象(参数不同)
StudentReflectTest3 student2 = (StudentReflectTest3)constructor2.newInstance("lisi");
System.out.println(student2);

获取成员变量并使用

//获取成员变量并使用

//1、获取class对象
Class clazz = Class.forName("com.lcl.reflect.StudentReflectTest5");

//2、获取Field对象
//1)Field[] getFields():返回【所有公共】的成员变量对象
Field[] fields = clazz.getFields();
for (Field field : fields) {
    System.out.println(field);
}

System.out.println("------------------------------");

//2)Field[] getDeclaredFields():返回【所有的】成员变量对象
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
    System.out.println(declaredField);
}

System.out.println("------------------------------");

//3)Field getField(String name):返回【单个公共】的成员变量对象。成员变量必须真实存在的
Field fied = clazz.getField("name");
System.out.println(fied);

System.out.println("------------------------------");

//2)Field getDeclaredField(String name):返回【单个】的成员变量
Field field1 = clazz.getDeclaredField("money");
System.out.println(field1);
Field field2 = clazz.getDeclaredField("age");
System.out.println(field2);

System.out.println("-------------------------------");

//3 赋值:set(对象,值),给【指定对象】的成员变量赋值

Field fied2 = clazz.getField("gender");
StudentReflectTest5 student = (StudentReflectTest5)clazz.newInstance();//用空参构造创建StudentReflectTest5对象
fied.set(student,"man");
System.out.println(student);

System.out.println("-------------------------------");

// 获取值:get(对象),返回【指定对象】的Field的值

Field field3 = clazz.getDeclaredField("toufa");
//被private修饰的成员,不能直接使用,如果用反射强行使用,需要临时取消访问检查,public修饰的成员不需要这一步
field3.setAccessible(true);
StudentReflectTest5 student2 = (StudentReflectTest5)clazz.newInstance();
Object o = field3.get(student2);
System.out.println(o);

获取方法并运行

//获取成员方法并运行

//1、获取class对象
Class clazz = Class.forName("com.lcl.reflect.StudentReflectTest6");

//2、获得Method对象
//Method[] getMethods():返回【所有公共】成员方法对象数组,【包括继承】的
Method[] methods = clazz.getMethods();
for (Method method : methods) {
    System.out.println(method);
}
System.out.println("-------------------------------------");

//Method[] getDeclaredMethods():返回【所有】成员方法对象数组,不包括继承的
Method[] methods1 = clazz.getDeclaredMethods();
for (Method method : methods1) {
    System.out.println(method);
}
System.out.println("-------------------------------------");

//Method getMethod(Sring 方法名,方法形参类型.class):返回【单个公共】成员方法对象
Method show2 = clazz.getMethod("show2");
System.out.println(show2);

Method show3 = clazz.getMethod("show3",String.class);
System.out.println(show3);
System.out.println("--------------------------------------");

//Method getDeclaredMethod(Sring 方法名,方法形参类型.class):返回【单个】成员方法对象
Method show1 = clazz.getDeclaredMethod("show1");
System.out.println(show1);
System.out.println("--------------------------------------");

//3、运行方法
//invoke(对象,实参):指定对象调用方法,看有无返回值
StudentReflectTest6 student1 = (StudentReflectTest6)clazz.newInstance();
Method show5 = clazz.getMethod("show5", String.class);
Object result = show5.invoke(student1,"lisi");
System.out.println(result);

//临时取消访问检查
show1.setAccessible(true);
show1.invoke(student1);


public class StudentReflectTest6 {
    private void show1(){
        System.out.println("私有,无参无返回值");
    }

    public void show2(){
        System.out.println("公有,无参无返回值");
    }

    public void show3(String name){
        System.out.println("公有,有参无返回值,参数:"+name);
    }

    public String show4(){
        System.out.println("公有,无参有返回值");
        return "aaa";
    }

    public String show5(String name){
        System.out.println("公有,有参有返回值,参数:"+name);
        return "aaa";
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值