反射--

类加载--

       当程序需要使用某个类的时候,如果该类还未被加载到内存中,则系统会通过类的加载、类的连接、类的初始化

这三个步骤对类进行初始化,如果不出现意外,JVM将会连续完成这三个步骤,所有这三个步骤类加载或者类初始化。

类的加载:就是指将class文件读入内存,并为之创建一个java.lang.class对象;

类的连接:

验证阶段:用于检验被加载的类是否有正确的内部结构

准备阶段:负责为类的类变量分配内存,并设置默认初始化值

解析阶段:将类的二进制数据中的符号引用替换为直接引用

类的初始化:

这一阶段主要对类的变量进行初始化

初始化步骤:

     如果类还未被加载和连接,则程序先加载并连接该类;

     假如该类的直接父类还未被初始化,则先初始化其直接父类;

    加入类中有初始化语句,则系统依次执行这些初始化语句;

类加载器:负责将   .class   文件加载到内存中,

ClassLoader:  负责加载类的对象

  主要方法:

      getSystemclassLoad()    返回用于委派的系统类加载器

     getParent()  放回父类加载器用于委派

public class ClassLoadDemo {
    public static void main(String[] args) {
        //获得系统类加载器
        ClassLoader c = ClassLoader.getSystemClassLoader();
         //  获取父类加载器
        ClassLoader p = c.getParent();
        System.out.println(p);
    }
}

反射:

 

对某个类:

1、反射获取class对象的方法由三种: 

Class<Employee> c = Employee.class;  //返回Employee类的class对象
Employee e = new Employee;
Class c2 = e.getclass();
Class cl = Class.forName("col.student.Student"); //括号里面的类必须是包含包名的全路径

 

2、反射获取构造方法并使用:

import col.student.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ClassLoadDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取类的class对象
        Class c = Class.forName("col.student.Student");

        //获取类中的构造方法
        Constructor<?>[] cons = c.getConstructors(); // 只能获取公有public的构造方法

        Constructor<?>[] cons1 = c.getDeclaredConstructors();  //返回所有构造方法的数组

        Constructor<?> cons2 = c.getConstructor();//返回一个Constructor对象,该对象
        //反映由该Class对象表示的类的指定公共构造函数;,括号里面不给参数返回无参构造方法
        Object obj = cons2.newInstance();  //返回这个无参构造方法对应的学生类信息
                                           //  根据指定的构造方法创建对象
        /*得到的obj 与通过  Student s =  new  Student()  得到的结果是一样的  即  s==obj
        只是obj是通过反射获取的,s是直接通过类构造得到的
         */
        
        //  通过反射实现Student s = new Student("a",12,"123456")
        //传入参数则获取带参构造方法,传入的参数是 带参构造方法中   数据类型.class;
        Constructor<?> ss = c.getConstructor(String.class,int.class,String.class);
        //这一步需要传入具体的参数
        Object o1 = ss.newInstance("zhejiang",12,"12345");

        // Constructor<?> cons3 = c.getDeclaredConstructors(); //返回一个指定的构造函数
    }
}

3、反射获取成员变量并使用;

        c.getField()

 Field name = c.getField("name"); // 获取公有的成员变量name,不指定参数的话获取所有
 Object obj1 = c.getConstructor().newInstance();
 name.set(obj1,"zhejiang"); // 给name成员变量 赋值为   zhejiang  ;
给对象obj1 的成员变量name赋值
package reflect;
import col.student.Student;

import java.lang.reflect.InvocationTargetException;

public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<?>  c = Class.forName("col.student.Student");

        var obj = c.getConstructor().newInstance();
        
        var name = c.getDeclaredField("name");
        
        name.setAccessible(true);  // 私有成员变量设置暴力访问
        name.set(obj,"zhejiang");

        var age = c.getDeclaredField("age");
        age.setAccessible(true);
        age.set(obj,10);
        
    }
}

4、反射获取成员方法并使用

getMethod()

public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<?>  c = Class.forName("col.student.Student");

        var me = c.getMethod("method1"); //获取方法,传入的参数是方法名;
        Object obj = c.getConstructor().newInstance();
       
        me.invoke(obj);//表示obj实例对象调用me方法,如果me方法需要传入参数,将具体参数值写入括号
        
         // 调用带参方法
        var me1 = c.getMethod("method2",String.class,int.class); //获取方法,传入的参数是方法名;
        Object obj1 = c.getConstructor().newInstance();
        me1.invoke(obj1,"a",12);  //如果方法带返回值,需要接收返回值 
        object o = me1.invoke(obj1,"a",12);

       /* 等价于  Student s = new Student();
        s.method1();*/

    }
}

练习:给定一个集合ArrayList<Integer> 集合,在集合中添加字符串数据;

public class reflecttest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<Integer> array = new ArrayList<>();

        array.add(10);

        Class<? extends ArrayList>  c= array.getClass();
        Method m = c.getMethod("add", Object.class); //add方法的参数是object类型的
        //通过反射获取原始的参数类型,然后加入
        Object hello = m.invoke(array, "hello"); // 因为add的参数是object类型,所以可以添加字符串
    }
}

练习2:通过配置文件运行类中的方法

class.txt 文件的内容

classname=col.student.Student
methodname =study
package reflect;

import col.student.Student;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Properties;

public class reflecttest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException {
        Student s = new Student();
        s.study();
        /* 在class.txt 文件中配置
               classname = xxx
               methodname =xxx
         */
        //1、加载数据
        Properties prop =new Properties();
        FileReader fr = new FileReader("class.txt");
        prop.load(fr);
        fr.close();

        String classname = prop.getProperty("classname");//返回等号右边
        String methodname = prop.getProperty("methodname");

        //通过反射使用  反射调用指定类中的指定方法,如果需要修改类,只需要该配置文件
        Class<?> c = Class.forName(classname);
        Constructor<?> con= c.getConstructor();
        Object o = con.newInstance();
        Method me = c.getMethod(methodname);
        me.invoke(o);



    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zero _s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值