zoukankan      html  css  js  c++  java
  • Java反射机制

     .反射的概述

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
    要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。
     反射是java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
     
     
    .反射强大之处:
     
     
    反射机制它没有局限性,可以知道任意一个类的所有属性以及方法,对于任意一个对象,都能够调用它的任意一个方法和属性。
    例:
     
         *  为什么jdbc连接要使用Class.forName("com.jdbc.mysql.Driver");
         *  不管是mysql的驱动 Driver还是Oracle的驱动或者其他驱动;
    * 它都需要去实现jdbc的一个驱动接口;
    * com.jdbc.mysql.Driver extends java.sql.Driver * java.sql.Driver d= Class.forName("com.jdbc.mysql.Driver") * * 例: * <servlet> * <servlet-name>xxx</servlet-name> * <servlet-class>com.xxx.xxxServlet</servlet-class> * </servlet> * ... * com.xxx.xxxServlet extends httpServlet * 通过建模我们就可以获取到com.xxx.xxxServlet这个路径 * Class<?> clz=Class.forName("com.xxx.xxxServlet"); * httpServlet httpservlet = clz.newInstanse();//获取到类对象就什么都可以干了
    一切反射相关的代码都从获得类(java.lang.Class)对象开始
      1 Class.forName(完整类名)              jdbc、自定义mvc框架用到
      2 类名.class                                     可用作通用的查询
      3 对象.getClass()                             通用增删改可用

      注1:ClassNotFoundException(类名错|少jar包)
      注2:同一类的、类对象只会创建一个
    测试类信息:
    package com.yuan.reflect;
    
    public class Student {
        private String sid;
    
        private String sname;
    
        public Integer age;
        
        static{
            System.out.println("加载进jvm中!");
        }
    
        public Student() {
            super();
            System.out.println("调用无参构造方法创建了一个学生对象");
        }
    
        public Student(String sid) {
            super();
            this.sid = sid;
            System.out.println("调用带一个参数的构造方法创建了一个学生对象");
        }
    
        public Student(String sid, String sname) {
            super();
            this.sid = sid;
            this.sname = sname;
            System.out.println("调用两个参数的构造方法创建了一个学生对象");
        }
    
        @SuppressWarnings("unused")
        private Student(Integer age) {
            System.out.println("调用Student类私有的构造方法创建了一个学生对象");
            this.age = age;
        }
    
        public String getSid() {
            return sid;
        }
    
        public void setSid(String sid) {
            this.sid = sid;
        }
    
        public String getSname() {
            return sname;
        }
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        public void hello() {
            System.out.println("你好!我是" + this.sname);
        }
    
        public void hello(String name) {
            System.out.println(name + "你好!我是" + this.sname);
        }
    
        @SuppressWarnings("unused")
        private Integer add(Integer a, Integer b) {
            return new Integer(a.intValue() + b.intValue());
        }
    
        @Override
        public String toString() {
            return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
        }
            
    }
    1、Class.forName("类的全路径名");    
        Class clz = Class.forName("com.yuan.reflect.Student");
        System.out.println(clz);

    结果:

    class com.yuan.reflect.Student

    2、类名.class

     Class clz=Student.class;
     System.out.println(clz);

    结果:

    class com.yuan.reflect.Student

    3、类(Class类类的类对象) 实例.getClass()      通用增删改可用

    Student stu=new Student();
      Class clz = stu.getClass();
      System.out.println(clz);

    结果:

    class com.yuan.reflect.Student

    .反射的三大作用

    1. 实例化对象          .newInstance();
    代码:
    package com.yuan.reflect;
    
    import java.lang.reflect.Constructor;
    
    /**
     * 反射实例化
     * 1.能够实例化未知的类
     * 2.能够通过私有的构造器创建实例
     * @author  ***
     *
     */
    public class Demo2 {
    
        public static void main(String[] args) throws Exception {
            Class clz= Student.class;
            //1、反射调用无参构造方法创建了一个学生对象
           // Student stu=(Student)clz.newInstance();
            
            //2、调用一个有参构造方法创建一个学生对象
            //拿到构造器类
    //        Constructor con = clz.getConstructor(String.class);//返回一个构造器
    //        //通过构造器实例化对象
    //        Student stu = (Student)con.newInstance("s007");
               // System.out.println(stu);
            
            //3、调用两个有参构造方法创建一个学生对象
                //拿到构造器类
    //            Constructor con = clz.getConstructor(String.class,String.class);//返回一个构造器
    //            //通过构造器实例化对象
    //            Student stu = (Student)con.newInstance("s007","zhangsna");
                //System.out.println(stu);
    
            //4、调用Student类私有的构造方法创建了一个学生对象
            //#java.lang.NoSuchMethodException: 未找到该方法(因为方法私有化所以不可被调用)
            //# getConstructor 这个方法只能寻找到public(公开的)修饰的构造器
    //        Constructor con = clz.getConstructor(Integer.class);
            //# getDeclaredConstructor 此方法可以寻找到任何修饰符修饰的构造器
    //        Constructor con = clz.getDeclaredConstructor(Integer.class);
            //# 设置私有方法可被访问
    //        con.setAccessible(true);
    //        //通过构造器实例化对象
    //          Student stu = (Student)con.newInstance(17);
               //System.out.println(stu);
        }
        
        
        
        
    }

    结果1:

    结果2:

    结果3:

    结果4:

    出现错误1:java.lang.NoSuchMethodException ,  说明你用的是getConstructor()方法,换成getDeclaredConstructor();

    出现错误2: java.lang.IllegalAccessException    没有设置私有可访问,加 .setAccessible(true);

    这两种都是针对于获取私有方法时找不到方法会出现的错误
     
     
    2. 动态调用方法      .invoke
    public static void main(String[] args) throws Exception {
            
            
            Student stu=new Student();
            //stu.hello();//普通调用方法
            
            Class clz=stu.getClass();
            //调用无参方法
    //        Method m = clz.getDeclaredMethod("hello");
    //        m.invoke(stu);
            
            //调用带参方法
            Method m = clz.getDeclaredMethod("add",Integer.class,Integer.class);
            m.setAccessible(true);
            //invoke 如果反射动态调用的方法是被void所修饰,他返回的就是null
                  // 如果反射动态调用的方法不是被void所修饰,那么返回的就是被调用的方法的返回值
            Object o=m.invoke(stu,20,5);
            System.out.println(o);
            
        }

    结果:

     
     
    3 .读写属性             set/get
    package com.yuan.reflect;
    
    import java.lang.reflect.Field;
    
    /**
     * 反射属性赋值取值
     * 
     * 反射能将jsp传递过来的参数直接封装到实体类中
     * 
     * @author  ***
     *
     */
    
    public class Demo4 {
    
        public static void main(String[] args) throws Exception{
            Student stu=new Student("s008","lili");
    //        stu.setSid("s004");
            stu.age=22;
    //        System.out.println(stu);
            
    // 赋值
    //反射处理的是一类的问题,在处理多个属性赋值或取值的时候,使用反射可以减省很多代码 //处理私有(private)属性时 需要设置它为可被访问: setAccessible(true); Class clz=stu.getClass(); Field field = clz.getDeclaredField("sid");//被赋值的属性 field.setAccessible(true);//设置私有可被访问 field.set(stu, "s02");//属性赋值 System.out.println(stu); System.out.println(field.get(stu));
    //取值
    // Field[] fields = clz.getDeclaredFields(); // for (Field field : fields) { // field.setAccessible(true); // System.out.println(field.getName()+"--"+field.get(stu)); // }
    } }

    赋值结果:

    加载进jvm中!
    调用两个参数的构造方法创建了一个学生对象
    Student [sid=s02, sname=lili, age=22]
    s02

    取值结果:

    加载进jvm中!
    调用两个参数的构造方法创建了一个学生对象
    sid--s008
    sname--lili
    age--22

    .访问修饰符    getModifiers()

    测试类信息:

    public class Student {
        private String sid;
    
        private String sname;
    
        public Integer age;
    }

    测试代码:

    public static void main(String[] args) {
            
            Class clz=Student.class;
            Field[] fields = clz.getDeclaredFields();
            for (Field field : fields) {
                System.out.println("-->");
                System.out.println(Modifier.toString(field.getModifiers()));
            }
        }

    输出结果:

    -->private

    -->private

    -->public

     
     
    谢谢观看!^-^
  • 相关阅读:
    【转载】SAP_ECC6.0_EHP4或SAP_ECC6.0_EHP5_基于Windows_Server_2008R2_和SQL_server_2008下的安装
    使用delphi 开发多层应用(二十四)KbmMW 的消息方式和创建WIB节点
    使用delphi 开发多层应用(二十三)KbmMW 的WIB
    实现KbmMw web server 支持https
    KbmMW 服务器架构简介
    Devexpress VCL Build v2014 vol 14.1.1 beta发布
    使用delphi 开发多层应用(二十二)使用kbmMW 的认证管理器
    KbmMW 4.50.00 测试版发布
    Basic4android v3.80 beta 发布
    KbmMW 认证管理器说明(转载)
  • 原文地址:https://www.cnblogs.com/ly-0919/p/11025290.html
Copyright © 2011-2022 走看看