zoukankan      html  css  js  c++  java
  • 漫谈反射

    反射

    理解反射的概念

    反射就是把Java类中的各种成分映射相成Java类。

    比如:众多的人用一个Person类来表示,那么众多的Java类就用一个Class类来表示。


    反射也称为对类的解剖。把类的各个组成部分映射成一个个对应的Java类。

    比如:一个类有:成员变量,方法,构造方法,包等等信息。

    利用反射技术能够对一个类进行解剖。

    事实上仅仅要拿到Java类的字节码相应的Class对象,就等于拿到了Java类中的各个成分。

    反射的基石就是Class。

    Class类

    Class类用于表示.class文件,是全部载入进内存的字节码对象的父类。所以能够通过Class得到执行时的类。


    怎样得到某个class文件相应的class对象呢?

    方法有3种:

    1)类名.class 比如,Person.class。

    2)对象.getClass() 比如。new Data().getClass()。

    3)Class.forName("包名.类名"); 比如,Class.forName("java.lang.String");

    代码演示样例:

    public class ClassTest{

    public static void main(String...args)throws Exception{

    String str = "abc";

    Class cls1 =String.class;

    Class cls2 = str.getClass();

    Class cls3 = Class.forName("java.lang.String");

    System.out.println(cls1 == cls2);//true

    System.out.println(cls2 == cls3);//true

    }

    }


    注意:字节码文件是唯一的,所以不管怎么获取。都是同一份字节码文件。



    九个提前定义Class实例对象(八大原始类型+void)

    Class 类的实例表示正在执行的 Java 应用程序中的类和接口。

    枚举是一种类,凝视是一种接口。

    每一个数组属于被映射为 Class 对象的一个类,全部具有同样元素类型和维数的数组都共享该Class 对象。

    主要的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和keyword void也表示为 Class 对象。

    注意:

    1、int.class == Integer.TYPE。

    2、数组类型的Class实例对象Class.isArray()为true。

    3、反射并非Java 5.0的新特性。

    Java 5.0 代码演示样例:

    package com.itheima.day01;

    public class ReflectTest {

    public static void main(String[] args) {

    System.out.println("推断int基本数据类型和Integer的基本数据类型"

    + "是不是同一个Class对象 结果为:"+(int.class == Integer.TYPE));

    System.out.println("推断int.class是不是基本数据类型 结果为:"+int.class.isPrimitive());

    System.out.println("推断是不是数组类型 结果为:"+int[].class.isArray());

    }

    }

    总之,仅仅要是在源程序中出现的类型,都有各自的Class实例对象,比如。int.classint[].class。


    一个类中的每一个成员都能够用对应的反射API类的一个实例对象来表示。通过调用Class类的方法能够得到这些实例对象后。得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。



    构造方法的反射应用(Coustructor类)


    Constructor类的实例对象代表类的一个构造方法。

    反射公共。私有和保护的构造方法:

    反射公共的须要的方法是:getConstructor();

    反射私有的须要的方法是:getDeclaredConstructor();

    Constructor对象代表一个构造方法。Constructor对象有的方法:得到构造方法名字。得到所属于的类,产生实例对象。


    得到某个类空參数构造方法。例:

    Constructor constructor = Class.forName("java.lang.String").getConstructor();

    得到某个类全部的构造方法,例:

    Constructor [] constructors= Class.forName("java.lang.String").getConstructors();

    得到某一个带參数的构造方法,例:

    Constructor constructor =Class.forName("java.lang.String").getConstructor(StringBuffer.class);


    注意:一个类有多个构造方法,用什么方式能够区分清楚想得到当中的哪个方法呢?依据參数的个数和类型,比如,Class.getMethod(name,Class... args)中的args參数就代表所要获取的那个方法的各个參数的类型的列表。重点:參数类型用什么方式表示?用Class实例对象。


    利用构造方法创建实例对象:

    通常方式:String instance = new String(new StringBuffer("黑马程序猿"));

    反射方式:String instance = (String)constructor.newInstance("黑马程序猿");

    //调用获得的方法时要用到上面同样类型的实例对象

    通过Class类中的newInstance()方法也可创建类的实例,其内部工作原理是先得无參的构造方法,再用构造方法创建实例对象。

    代码演示样例:

    package com.itheima.day01;

    import java.lang.reflect.Constructor;

    public class ReflectTest {

    public static void main(String[] args) throws Exception {

    Class clszz = Class.forName("java.lang.String");

    Constructor constructor = clszz.getConstructor(StringBuffer.class);

    String str = (String) constructor.newInstance(new StringBuffer("黑马程序猿"));

    char [] chs = str.toCharArray();

    for(int x = 0; x<chs.length;x++){

    System.out.println(chs[x]);

    }

    }
    }

    成员变量的反射(Field类)

    Field类代表反射某个类中的一个成员变量。


    问题:得到的Field对象是相应到类上面的成员变量。还是相应到对象上的成员变量?类仅仅有一个。而该类的实例对象有多个,假设是与对象关联,那关联的是哪个对象呢?所以字段fieldAge 代表的是Age的定义,而不是详细的Age变量。

    (注意訪问权限的问题)也就是说,定义的是类对象,而非对象的对象。

    当我们须要对其操作的时候。须要确定是那个详细的对象。

    代码演示样例:

    package com.itheima.study;

    public class Person {

    public int age;

    private int height;

    public Person(int age,int height){

    this.age=age;

    this.height=height;

    }

    }


    package com.itheima.study;

    import java.lang.reflect.Field;

    public class ReflectTest{

    public static void main(String...args) throws Exception{

    Person p = new Person(20,30);

    Field fieldAge = p.getClass().getField("age");

    System.out.println(fieldAge.get(p));

    }

    }

    练习:将随意一个对象中的全部String类型的成员变量所相应的字符串内容中的“b"改为"a"。

    public class ReflectPoint  
    {  
       private int x;  
       public int y;  
       public String str1="blue";  
       private String str2="bubble";  
       public String str3="soso";  
        public ReflectPoint(int x, int y)  
        {  
            super();  
            this.x = x;  
            this.y = y;  
        }  
          
        public String toString()  
        {  
            return str1+" "+str2+" "+str3;  
        }  
        
    }  

    public class Reflect {


    /**
    * 练习:将随意一个对象中的全部String类型的成员变量所相应的字符串内容中的“b"改为"a"。



    */
    public static void main(String[] args) throws Exception {
    Constructor[]  constructors=String.class.getConstructors();//得到String类的全部公共构造方法  
            Constructor constructor=String.class.getConstructor(StringBuffer.class);//得到指定參数的构造方法  
            //用构造方法创建实例  
            String s=(String)constructor.newInstance(new StringBuffer("黑马"));  
            System.out.println(s);           
            //Class类里面的无參构造方法                                                        
            Date date=(Date)Class.forName("java.util.Date").newInstance();  
            System.out.println(date);  
              
            ReflectPoint rp=new ReflectPoint(3,3);  
            Field fieldY=rp.getClass().getField("y");//注意fieldY不是对象的变量,是所在类的变量  
            int rpY=(Integer) fieldY.get(rp);//依据对象取得变量的值  
            System.out.println(rpY);  
              
            Field fieldX=rp.getClass().getDeclaredField("x");//由于x被private修饰  
            fieldX.setAccessible(true);//把私有的变量设置成能够訪问  
            System.out.println(fieldX.get(rp));  
              
            value(rp);  
            System.out.println(rp);
           
    }

    private static void value(Object  obj) throws Exception {
    Field[]  fields=obj.getClass().getFields();
    for (Field field : fields) {
    if (field.getType()==String.class) {//getType()返回一个 Class 对象。它标识了此 Field 对象所表示字段的声明类型
    String  oldvalue=(String) field.get(obj);// 返回指定对象上此 Field 表示的字段的值
    String  newvalue=oldvalue.replace('b','a');//把b变成a
    field.set(obj, newvalue);//将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

    }
    }
    }


    }


  • 相关阅读:
    数据结构与算法-基础(七)完全二叉树
    数据结构与算法-基础(六)二叉树基础
    数据结构与算法-基础(五)队列(Qeque)
    数据结构与算法-基础(四)栈(Stack)
    数据结构与算法-基础(三)- 循环链表(补充)
    数据结构与算法-基础(二)单向链表
    数据结构与算法-基础(一)动态数组
    Swift-Button 的 highlighted(高亮)
    Android现有工程使用Compose
    Android Jetpack Compose 引入示例工程
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6821361.html
Copyright © 2011-2022 走看看