• java基础篇3之反射


    1、反射的基础
      反射的基石----》Class类
      java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class

      获取字节码对应的实例对象(Class类型)
      class cls1 = Person.class//字节码1;
      p1.getClass();
      Class.forName("java.lang.String"); 主要用这种进行反射

      8个基本类型,对应着8个Class对象
      void.class 对象

        String str1 = "abc";
        Class cls1 = str1.getClass();
        Class cls2 = String.class;
        Class cls3 = Class.forName("java.lang.String");
        cls1==cls2 //true
        cls1==cls3 //true
        int.class.isPrimitive //true
        int.class == Integer.class //flase
        int.class == Integer.TYPE //true
        数组类型的Class实例对象 Class.isArray()    

    2反射的概念
      反射就是把java类中的各种成分映射成对应的java类
      例如:
      成员变量---》Field对象
      方法----》Method对象
      构造方法---》Constructor对象
      ...

    3、 构造方法的反射应用

      Constructor类代表某一个构造方法

    //new String(new StringBuffer("abc"))
      Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
      String str2=(String)constructor1.newInstance(new StringBuffer("abc"))

      class -> constructor -> new object

      反射会导致程序性能下降

      Class.newInstance()方法
      例如:String obj = (Class)Class.forName("java.lang.String").newInstance();
      该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象
      用了缓存机制来保存默认构造方法的实例对象

     

    4、成员变量的反射

      Field类代表某各类中的一个成员变量
    
        public class ReflectPoint{
            private int x;
            public int y;
            ...构造方法 
        }
    
        ReflectPoint pt1 = new ReflectPoint(3,5);
        //fieldY不是对象身上的变量,而是类上的,要用它取对应对象上的属性值
        Field fieldY = pt1.getClass().getField("y"); //public
        fieldY.get(pt1); // 5 
        Field fieldX = pt1.getClass().getDeclaredField("x");//private
        filedX.setAccessible(true);//暴力反射
        fieldX.get(pt1);
    
    
        public class ReflectPoint{
            public String str1 ="ball";
            public String str2 ="basketball";
            public String str3 ="itcast";
        }
    
        private static void changeStringValue(Object obj){
            Field[] fields = obj.getClass.getFields();
            for(Field field:fields){
                //对字节码的比较用==号比 因为同一份字节码
                if(field.getType() == String.class){
                    String oldValue =(String)field.get(obj);
                    String newValue = oldValue.replace('b','a');
                    field.set(obj,newValue);
                }
            }
        }

    5 、成员方法的反射

      Method类代表某个类中的一个成员方法

     Method methodCharAt = String.class.getMethod("charAt",int.class);
      //调用方法一定是在一个对象上
      String str1="abc";
      methodCharAt.invoke(str1,1);

      如果传递给Method对象的invoke()方法的第一个参数为null,说明
      该Method对象对应的是一个静态方法

    6 、对接受数组参数的成员方法进行反射

      用反射方式执行某个类中的main方法

    public class TestArguments{
            public static void main(String[] args){
                for(String arg:args){
                    System.out.println(arg);
                }
            }
        }
    
        String clazz = "com.test.TestArguments";
        Method mainMethod = Class.forName(clazz).getMethod("main",String[].class);
        mainMethod.invoke(null,new Object[](new String[]{"111","222"}));
        mainMethod.invoke(null,(Object)new String[]{"111","222"});
        //编译器会做特殊处理,编译时不将参数作为数组看待,也就不会讲数组打算成若干参数了

    7、 数组与Object的反射

      相同的元素且相同的维度则是同一份字节码文件

       int[] a1 = new int[3];
        int[] a2 = new int[4];
        int[][] a3 = new int[2][3];
        String[] a4 = new String[3];
        a1.getClass() == a2.getClass();//true
        a1.getClass() == a3.getClass();//false
        a1.getClass() == a4.getClass();//false

    基本类型的数组是不能转为Object数组
    Object[] aobj = a1//error

    具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象

    代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class

    基本类型的一维数组可以被当做Object类型使用,不能当作Object[]类型使用,非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用

    Arrays.asList()方法处理int[]和String[]存在差异Arrays工具类用于完成对数组的反射操作

    private static void printObject(Object obj){
            Class clazz = obj.getClass();
            if(clazz.isArray()){
                int len = Array.getLength();
                for(int i=0;i<=len;i++){
                    System.out.println(Array.get(obj,i));
                }
            }else{
                System.out.println(obj);
            }
        }
  • 相关阅读:
    https://www.cnblogs.com/marost/p/4668664.html
    UEFI 坑 Ubuntu
    Spring《六》管理Bean
    Spring《五》集合的注入方式
    Spring《四-一》解决自动装配的问题
    spring《四》自动装配
    Spring《三》ref 引用其他bean
    Spring《二》 Bean的生命周期
    Spring《一》
    Fragment间相互调用并传值
  • 原文地址:https://www.cnblogs.com/atomicbomb/p/6624079.html
Copyright © 2020-2023  润新知