zoukankan      html  css  js  c++  java
  • 类加载和反射

    2、反射
    在我们使用类之前会有一个进入内存的步骤,其中分为三步,加载、连接、初始化三步。
    第一个加载过程是class文件读入内存,并且在栈里面创建一个class对象。(不论是什么类使用之前都会创建一个class对象)。
    连接:
    初始化:
    类初始化时机就是如何在栈里面建内存的步骤行为。类的加载。
    1、new person
    2、静态变量
    3、静态方法
    4、使用反射方式来强制创建某个类或接口对应的java.lang.class对象
    5、进内存的父类的子类
    6、main  java.exe命令
    类加载器:
    是将程序的.class文件加载到内存(程序的.class文件是由上面的6中方式产生的。),并且产生class对象,我们自定义的类都会出现一个class对象,因为他是对象,所以我们可以用对象.方法名()调取能够访问的所有方法。
    类加载器的组成。
    跟类加载器 核心
    jar包 拓展类加载器
    系统及在其 平时自定义的类。
    如何获取反射?
    反射的意义是java在运行状态时,对任意类都能知道所有的属性和方法,对于一个类,我们可以调用它的任意一个方法和属性。
    1、Class类
    通过类加载器,我们知道,class类不是自己创建出来的,而是系统让类加载进栈内存产生的,所以我们获取的class对象只能获取并不能new对象修改,因为它没有构造方法。
    开头第一步之获取Class类
    ①通过Object 的getObject()获取最高类Object 中的getClass
    person p=new person();
    Class c=p.getClass();
    ②通过类名.class获取字节码文件对象(任意数据类型都具备一个class静态属性)
    Class c1=person.class();
    ③通过class方法中调取静态方法.forName(JDBC工具类使用这个,每一个类中只能存在一个
    通过完整的包名+类名获取
    Class c2=class.forName("com.oracle.demo03.Person");传入要获取的类名。

    第二步之如何通过反射获取构造方法:
    如获取所有的public修饰的公共构造方法:
    1、首先获取class对象,同上面三条那一条都可以
    2、通过class对象调取所有public方法或者单个方法,[]或者单个

    Constructor[] cons=c.getConstructors();


    获取所有构造方法数组(包括私有)
    Constructor[] cons=c.getDeclaredConstructors();

    person类
    
    package com.oracle.demo02;
    
    public class Person {
        //私有
        private int age;
        //公共
        public String name;
        //公共空参构造
        public Person(){
            System.out.println("公共空参构造");
        }
        //公共有参构造
        public Person(int age,String name){
            this.name=name;
            this.age=age;
            System.out.println("公共有参构造");
        }
        //私有有参构造
        private Person(String name,int age){
            this.name=name;
            this.age=age;
            System.out.println("私有有参构造");
        }
        public void eat(){
            System.out.println("公共空参方法");
        }
        
        public void sleep(String name){
        
            System.out.println("公共有参方法");
        }
        private void plagname(int age){
            System.out.println("私有有参方法");
        }
        static{
            System.out.println("person静态代码块");
        }
        @Override
        public String toString() {
            return "Person [age=" + age + ", name=" + name + "]";
        }
    
    }
    获取所有的构造方法,因为默认调取的是toString,所以是以字符串显示的。
                  //获取person类的字节码文件对象
            Class c=Person.class;
        Constructor[] cons=c.getDeclaredConstructors();
            //遍历
            for(Constructor con:cons){//String获取出来是tostring类型,哪一个包下的
                System.out.println(con);
            }


    如果获取单个有参构造(需要在方法内传入类中的参数,顺序内容一样。

    Constructor con1=c.getConstructor(int.class,String.class);

    如果获取单个无参构造:
    Constructor con=c.getConstructor();
    3、【数组】需要通过超级for遍历。单个不需要(对获取的对象进行遍历)


    获取到构造并进行创建对象:
    Object obj=con.newInstance("小红",18);有参
    Object obj=c.newInstance();无参,快速创建对象。后面的操作基本用它。
    字节码文件对象:
    获取指定的成员变量并使用

    //获取指定的成员变量并使用
            //获取person的字节码文件对象
            Class c=Class.forName("com.oracle.demo02.Person");
            //获取公共成员变量
            Field f=c.getField("name");
            //给成员变量赋值
            //快速创建person对象
            Object obj=c.newInstance();
            //调取方法
            //给成员变量赋值
            f.set(obj, "哈哈哈哈哈");
            System.out.println(obj);

            //获取文件字节码对象,现在只是赋值没有输出
            Class c=Person.class;
            //调取公共有参成员方法对象
            Method m=c.getMethod("sleep", String.class);
            //快速创建person对象
            Person p =(Person)c.newInstance();
            //调用方法
            m.invoke(p, "智障障");


    top1:反射的两个使用案例,泛型擦除

    public class Demo05 {  //反射擦除泛型是因为泛型不进class文件
        public static void main(String[] args) throws NoSuchMethodException, SecurityException, 
    IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //泛型擦除 ArrayList<Integer> arr=new ArrayList<Integer>(); arr.add(1); //arr.add("aaa"); //获取ArrayList类的class对象 Class c=arr.getClass();//object 获取到没被限定泛型时的Object类对象 //获取add方法对象 Method m=c.getMethod("add", Object.class);//获取arr里的方法add,无泛型都可传入。 //调用add方法 m.invoke(arr, "aaa");//m获取到无泛型的add方法,就可以随意传入各种类型了。相当于时光回溯到没有泛型之前。 System.out.println(arr); }

     流程,通过先获取到并没有被泛型限制的arr集合对象,获得一个可以存取所有数据的Object对象,然后接着获取arr下方法add,通过成员变量的有参方法,传入,再调用invoke方法添加(无泛型类,想要存取的值)就可以了。

    top2:通过反射配置文件

    设置三个实体类:
    public class Person {
            public void eat(){
                System.out.println("人吃饭");
            }
    }
    public class Student {
        public void study(){
            System.out.println("学生学习");
        }
    
    public class Worker {
        public void work(){
            System.out.println("工作");
        }

    配置一个往里面存取键值对

    ClassName=com.oracle.demo03.Worker
    MethodName=work
    配置完成后,只需要改这里的信息,就可以再次执行其他对象
    public static void main(String[] args) throws IOException, ClassNotFoundException, 
    NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //明确数据源 FileReader fr=new FileReader("src/com/oracle/demo03/config.properties"); //创建Properties集合 Properties pro=new Properties(); //将文件中的键值对读到集合中 pro.load(fr); //从集合中获取类名 String classname=pro.getProperty("ClassName"); //从集合中获取方法名 String methodname=pro.getProperty("MethodName"); //通过类名获取该类的字节码文件对象,也就是获取到在文件里被书写的类地址。 Class c=Class.forName(classname); //通过字节码文件对象获取指定方法对象 通过对象.方法()获取到 Method m=c.getMethod(methodname); //快速创建空参对象 Object obj=c.newInstance(); //调用 m.invoke(obj); }

  • 相关阅读:
    MySQL5.7安装教程(压缩版)
    ASP.Net 添加 Interop for Word, excel 插件
    OpenLayers-加载地图数据(Google Map)
    OpenLayers学习方法
    OpenLayers 项目分析——(二)源代码总体结构分析{感谢原作者对于大家的贡献!}
    OpenLayers项目分析——(一)项目介绍{感谢原作者为大家的贡献!}
    OpenLayers 项目分析——(三)BaseTypes {感谢原文作者对于大家的贡献!!!}
    GeoServer安装及配置过程(配置shapefile)
    如何查询postgreSQL 里面某个数据库中所有用户定义的数据表的名字
    WebGIS(PostgreSQL+GeoServer+OpenLayers)之三 OpenLayers客户端数据显示
  • 原文地址:https://www.cnblogs.com/a199706/p/11479256.html
Copyright © 2011-2022 走看看