zoukankan      html  css  js  c++  java
  • 第8章 反射

    反射是动态语言的关键.

    为什么需要反射呢?

    一个已经开发完全的程序,如果需要对功能进行升级、更新,虽然可以通过修改源代码进行编写,从而升级java程序的功能.但实际开发的时候这并不是一个好的办法.

    实际开发中,不会去修改原先的程序代码,而是创建一个新类,将升级的功能封装在新类的方法中,通过反射来解刨这个心累的class文件,然后去调用新类的成员和方法.

    获取Class类对象

    例子:

    public class Person {//创建一个Person类
        public String name;
        public    int id;
        public  Person()//无参构造方法
        {
        }
        public Person(String name, int id) {
            super();
            this.name = name;
            this.id = id;
        }
    
    
        public void display() {
            System.out.println("姓名为:"+name+"id为:"+id);
        }
    }
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Demo {
    
        public static void main(String args[]) throws Exception {
        //获取Class类的对象的三种方法 通过类名.class、对象名.getClass()、forName方法来获取类的对象
        Class class1=Person.class;
    Person p1
    =new Person("小张",1); Class class2=p1.getClass(); Class class3=Class.forName("反射练习.Person"); //每一个类都存在一个类对象,用于描述该类有什么方法、成员 System.out.println(class1); }
    }

    Class类对象创建常用类对象:

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Demo {
    
        public static void main(String args[]) throws Exception {
        //获取Class类的对象的三种方法 通过类名、对象名、forName方法来获取类的对象
        Class class1=Person.class;
        Person p1=new Person("小张",1);
        Class class2=p1.getClass();
        Class class3=Class.forName("反射练习.Person");
        //每一个类都存在一个类对象,用于描述该类有什么方法、成员
        
        System.out.println(class1);
        
        
        //用Class对象来创建新的对象
        //第一步:首先先获取Constructor对象,这是该类的公共构造函数
        Constructor con1=class1.getConstructor(); //获取该类的无参构造函数.
        Constructor con2=class2.getConstructor(String.class,int.class);//这是获取该类的有参构造函数在getConstructor方法括号中加上构造方法参数类型.class;
        //使用con1获取的无参构造函数来创建对象 使用Constructor类的newInstance方法.
        Person p2=(Person) con1.newInstance();//想获得无参构造函数的时候,如果想获取的无参构造函数是隐式的会发生错误,需要将无参构造函数添加进类
        p2.id=20;
        p2.name="小张";
        p2.display();
        //newInstance方法返回的是Object对象,所以需要强制类型转换
        //Constructor是用于存储构造方法的类型.
        //使用 con2获取的有参构造函数来创建对象 
        Person p3=(Person) con2.newInstance("小李",30);
        p3.display();
        System.out.println(p2+""+p3);
    }
    }

    获取和设置成员变量

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Demo {
    
        public static void main(String args[]) throws Exception {
        //获取Class类的对象的三种方法 通过类名、对象名、forName方法来获取类的对象
        Class class1=Person.class;
        Person p1=new Person("小张",1);
        Class class2=p1.getClass();
        Class class3=Class.forName("反射练习.Person");
        //每一个类都存在一个类对象,用于描述该类有什么方法、成员
        
        System.out.println(class1);
        
        
        //用Class对象来创建新的对象
        //第一步:首先先获取Constructor对象,这是该类的公共构造函数
        Constructor con1=class1.getConstructor(); //获取该类的无参构造函数.
        Constructor con2=class2.getConstructor(String.class,int.class);//这是获取该类的有参构造函数在getConstructor方法括号中加上构造方法参数类型.class;
        //使用con1获取的无参构造函数来创建对象 使用Constructor类的newInstance方法.
        Person p2=(Person) con1.newInstance();//想获得无参构造函数的时候,如果想获取的无参构造函数是隐式的会发生错误,需要将无参构造函数添加进类
        p2.id=20;
        p2.name="小张";
        p2.display();
        //newInstance方法返回的是Object对象,所以需要强制类型转换
        //Constructor是用于存储构造方法的类型.
        //使用 con2获取的有参构造函数来创建对象 
        Person p3=(Person) con2.newInstance("小李",30);
        p3.display();
        System.out.println(p2+""+p3);
        
        //获取和设置成员变量
        //Field用于存储成员变量信息   Class的getFields方法能够获取公有成员变量信息(如果想要获得私有字段的名称 得使用getDeclared-Fields()方法)
        Field[] filed1=class1.getFields();
        for(Field filed:filed1)//加强型for循环,即for-each循环 for(数据类型 变量名:数组、集合名){ \执行语句  }
        {
            System.out.println(filed.getName()); //Field的getName方法获得字段的名称
        }
        //那如何设置某个字段的值呢?
        Constructor con3=class1.getConstructor();//获取无参构造函数
        
        
        Object obj=con3.newInstance();//新建一个Object类型的变量来指向con3所存储的构造函数所新建的对象
        
        Field name=class1.getField("name");//获得name的Field类的对象
        name.set(obj, "张三");//这个时候name获取    //值为想要设置的字段的Field类型的对象.set(想要设置成员属性所属的对象,属性值);
        
        Field id=class1.getField("id");
        id.set(obj, 02);
        
        System.out.println(name.get(obj)+" "+id.get(obj));
        
      }
    }
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Demo {
    
        public static void main(String args[]) throws Exception {
        //获取Class类的对象的三种方法 通过类名、对象名、forName方法来获取类的对象
        Class class1=Person.class;
        Person p1=new Person("小张",1);
        Class class2=p1.getClass();
        Class class3=Class.forName("反射练习.Person");
        //每一个类都存在一个类对象,用于描述该类有什么方法、成员
        
        System.out.println(class1);
        
        
        //用Class对象来创建新的对象
        //第一步:首先先获取Constructor对象,这是该类的公共构造函数
        Constructor con1=class1.getConstructor(); //获取该类的无参构造函数.
        Constructor con2=class2.getConstructor(String.class,int.class);//这是获取该类的有参构造函数在getConstructor方法括号中加上构造方法参数类型.class;
        //使用con1获取的无参构造函数来创建对象 使用Constructor类的newInstance方法.
        Person p2=(Person) con1.newInstance();//想获得无参构造函数的时候,如果想获取的无参构造函数是隐式的会发生错误,需要将无参构造函数添加进类
        p2.id=20;
        p2.name="小张";
        p2.display();
        //newInstance方法返回的是Object对象,所以需要强制类型转换
        //Constructor是用于存储构造方法的类型.
        //使用 con2获取的有参构造函数来创建对象 
        Person p3=(Person) con2.newInstance("小李",30);
        p3.display();
        System.out.println(p2+""+p3);
        
        //获取和设置成员变量
        //Field用于存储成员变量信息   Class的getFields方法能够获取公有成员变量信息(如果想要获得私有字段的名称 得使用getDeclared-Fields()方法)
        Field[] filed1=class1.getFields();
        for(Field filed:filed1)//加强型for循环,即for-each循环 for(数据类型 变量名:数组、集合名){ \执行语句  }
        {
            System.out.println(filed.getName()); //Field的getName方法获得字段的名称
        }
        //那如何设置某个字段的值呢?
        Constructor con3=class1.getConstructor();//获取无参构造函数
        
        
        Object obj=con3.newInstance();//新建一个Object类型的变量来指向con3所存储的构造函数所新建的对象
        
        Field name=class1.getField("name");//获得name的Field类的对象
        name.set(obj, "张三");//这个时候name获取    //值为想要设置的字段的Field类型的对象.set(想要设置成员属性所属的对象,属性值);
        
        Field id=class1.getField("id");
        id.set(obj, 02);
        
        System.out.println(name.get(obj)+" "+id.get(obj));
        
        
        //Class类如何获取和调用方法?
        Method method1=class1.getMethod("display");//1、获取指定字符串的方法,//如果想获取的方法需要参数,方法名后面就跟上 参数类型.class 用逗号分隔
        Object object1= con2.newInstance("小张",03);//2、使用con2存储的有参构造函数来创建一个Object对象
        method1.invoke(object1);//执行无参的方法,如果该方法需要参数,直接按照顺序将参数用逗号分隔加上即可.
            
        }
        }

    课后习题:

    1、获取Class类的常用方法是什么?

    有三种,1、通过类名.class来获得Class类对象

       2、通过该类型的对象.getClass()方法来获取该类型的Class类对象

          3、使用Class.forName("包名.类名")方法来获取字符串中描述的类Class类对象

    2、如何获取Class类的构造方法?

    使用getConstructor()方法,如果想获取无参构造函数,则不需要填写参数,如果想获取有参数的构造函数,括号中需要class.参数类型 多个参数类型之间使用逗号分隔.

  • 相关阅读:
    Spring_AOP动态代理详解(转)
    Java中spring读取配置文件的几种方法
    SpringMVC工作原理2(代码详解)
    SpringMVC工作原理1(基础机制)
    Web服务器和应用服务器简介
    WEB服务器与应用服务器解疑
    WebService基本概念及原理
    HTTP协议
    TCP、UDP协议间的区别(转)
    HTTP、TCP、UDP以及SOCKET之间的区别/联系
  • 原文地址:https://www.cnblogs.com/youjunhui/p/14905323.html
Copyright © 2011-2022 走看看