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

     
     
    谢谢观看!^-^
  • 相关阅读:
    vue路由对象($route)参数简介
    原生js写ajax请求(复习)
    js,jq.事件代理(事件委托)复习。
    CSS 设置table下tbody滚动条
    H5 调用手机摄像机、相册功能
    css实现六边形图片(最简单易懂方法实现高逼格图片展示)
    input表单的type属性详解,不同type不同属性之间区别
    js对象,set和get方法 的三种实现形式
    day03 变量
    day01 js三种导入html的方法、js书写规范、变量的基本使用、变量提升
  • 原文地址:https://www.cnblogs.com/ly-0919/p/11025290.html
Copyright © 2011-2022 走看看