• java 类加载器、反射


    字节码对象,当我们保存后程序产生的.class文件是编译后的文件,当我们运行程序的时候,程序去读取.class文件,这个文件会存到内存中,在堆中创建一个.class文件对象

    当程序要使用某个类的时候,该类还没有到内存中去,会通过加载,连接,初始化3步对这个类进行初始化

    加载,将class文件对象加载到内存中去,创建一个class对象,任何类在被使用时都会创一个class对象

    连接,1.检验,检查语法是否有问题,跟其他类是否协调

      2.准备,给静态成员变量初始化值

      3.解析,将符号引用改成直接引用

    例如:int a = 1;解析就是把a直接改成1了

    类什么时候初始化

    1.创建类的时候

    2.类的静态方法

    3.类的静态成员变量赋值的时候

    4.反射创建某个类的时候

    5.调用某个类的子类的时候

    6.直接运行程序的时候

    类的加载器组成

    反射

     对于java中任意一个类,我们可以知道他的方法和属性,对于任意一个对象,我们可以调用他的方法和属性,解剖出来,这叫做java的反射机制

     首先我们要获取这个类的字节码对象,对他进行操作

    有3种方式

    我们先创建一个类person

     1 package com.orcale.damo01;
     2 
     3 public class Person {
     4     public String name;
     5     private int age;
     6     static{
     7         System.out.println("静态代码块");
     8     }
     9     public Person(){
    10         System.out.println("空参构造");
    11     }
    12     public Person(String name,int age){
    13         this.name= name;
    14         this.age= age;
    15         System.out.println("有参构造");
    16     }
    17     private Person(int age,String name){
    18         this.age = age;
    19         this.name= name;
    20         System.out.println("有参构造");
    21     }
    22     public void eat(){
    23         System.out.println("吃饭");
    24     }
    25     public void work(String name){
    26         System.out.println(name+"走路");
    27     }
    28     private void run(String name){
    29         System.out.println(name+"跑步");
    30     }
    31     @Override
    32     public String toString() {
    33         return "Person [name=" + name + ", age=" + age + "]";
    34     }
    35 }

    通过对象获取字节码对象

    1 Person p = new Person();
    2 Class c = p.getClass();
      System.out.println(c);

    通过类名获取

    1 Class c1 = Person.class;

    通过class的静态方法获取forName(完成的类名,包名)

    1 Class c2 = Class.forName("com.orcale.damo01.Person");
    2 System.out.println(c2);

    获取公共的构造方法

    1 Class c = Person.class;
    2 Constructor con =c.getConstructor(这里如果是有参构造就写参数);
    就表示为
     Constructor con =c.getConstructor(Sting.calss,int.class)数据类型在前,class在后面,具体看构造参数
    3 System.out.println(con);

    获取所有的公共的构造方法

    1     Class c = Person.class;
    2         Constructor[] con = c.getConstructors();   一个对象数组,把所有的构造方法都放进去
    3         for(Constructor co:con){
    4             System.out.println(co);
    5         }

    获取公共的方法

    1 Class c = Person.class;
    2         Constructor con =c.getConstructor(String.class,int.class);
    3         //因为Person类中没有单独String name的构造方法,所以写了2个,
    4         Object obj = c.newInstance();
    5         //创建一个对象祖宗类,然后用字节码对象获取方法
    6         //getMethod("第一个写需要调用的方法名字",写需要传入的参数);
    7         Method me = c.getMethod("work", String.class);
    8         //调用方法用invoke方法(第一个写对象,第二个写需要传入的实参)
    9         me.invoke(obj, "小明");

    获取所有的公共方法和获取所有的公共构造方法差不多,整个数组遍历就可以了

    获取所有的公共成员变量

    1 Class c= Person.class;
    2         Field[] f= c.getFields();  //通过Field【】方法数组
    3         for(Field ff:f){
    4             System.out.println(ff);
    5         }

    获取指定的公共成员变量

    1 Class c= Person.class;
    2         Field f= c.getField("name");
    3         System.out.println(f);

    修改公共的成员变量赋值

    1 Class c= Person.class;
    2         Field f= c.getField("name");
    3         Object obj = c.newInstance();
    4         //调用set方法对name赋值,然后输出对象的属性
    5         f.set(obj, "小明");
    6         System.out.println(obj)

    获取私有的构造方法

    原理是通过setAccessible方法,避开了对类的加载器对类的检查,不建议对私有的构造方法和属性操作,不然还私有干啥没有意义了

    1     Class c =Person.class;
    2         Constructor con = c.getDeclaredConstructor(int.class,String.class);
    3         con.setAccessible(true);//暴力反射开关
    4         Object obj =  con.newInstance(12,"dd");   
    5         System.out.println(obj);

    获取私有的成员变量

    Class c= Person.class;
            Field field = c.getDeclaredField("age");  //获取私有的的成员变量
            Object obj = c.newInstance();
            field.setAccessible(true);  //暴力开关
            field.set(obj, 11);   
            System.out.println(obj);

     练习:有一个AarrayList<String> list,然后往里面添加int类型数据,泛型擦除(字节码文件中没有泛型)

    1 ArrayList<String> arr = new ArrayList<String>();
    2         arr.add("abc");
    3         Class c= arr.getClass();
    4         Method addd = c.getMethod("add", Object.class);
    5         addd.invoke(arr, 1);
    6         for(Object obj:arr){
    7             System.out.println(obj);
    8         }
  • 相关阅读:
    DataTablez转List对象效率慢的问题.
    Oracle 删除重复数据
    1.layui 添加旋转等待, 2.div里面加载HTML页面
    layui-table JSON.stringify()序列化出来的不同行数据类型错误.导致后台转成表格的时候出错.(常用)
    0基础学MVC课程
    构造函数的执行顺序
    html控件自动点 “加号”添加 多个附件
    C#委托之个人理解 转自 loose_went
    一步一步学Linq to sql系列文章 转lovecherry
    使用AOP 使C#代码更清晰 转yanghua_kobe
  • 原文地址:https://www.cnblogs.com/wangrongchen/p/9242789.html
Copyright © 2020-2023  润新知