• Java 反射


    Java 反射

    示例类

    1. User 类:
    class User
    {
        String name;
        int id;
        
        public User()
        {
        
        }
        
        public User(String name, int id)
        {
            this.name = name;
            this.id = id;
        }
    
        public String getName()
        {
            return name;
        }
    
        public void setName(String name)
        {
            this.name = name;
        }
    
        public int getId()
        {
            return id;
        }
    
        public void setId(int id)
        {
            this.id = id;
        }
    }
    
    1. ReflectTest 类:
    public Class ReflectTest
    {
      pulic static void main(String[] args)
      {
        try
        {
          //测试
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    }
    

    类对象

    1. 不同的类区别在于有不同的方法,不同的属性。类对象,就是用于描述这种类,都有什么属性,什么方法的。
    2. 获取类对象的方法
      • Class.forName("mypackage.User")
      • User.class
      • new User().getClass()

    一个 ClassLoader 下,一种类,只会有一个类对象存在。通常一个 JVM 下,只会有一个 ClassLoader, 所以在一个 JVM 中,一种类,只会有一个类对象存在。以上三种方式取出来的类对象,都是一样的。

    反射创建对象

    1. 常规方法
    //使用反射的方式创建对象
    String className = "mypackage.User";
    //类对象
    Class uClass = Class.forName(className);
    //构造器
    Constructor con = uClass.getConstructor();
    //通过构造器实例化
    User u = (User) con.newInstance();
    
    1. Class.newInstance()Constructor.newInstance()
      Class 对象调用 newInstance() 方法只能用于不带参数的构造方法;
      Constructor 对象调用 newINstance() 方法可以指定参数;
    Constructor con =
          uClass.getConstructor(new Class[]{String.class, int.class});
    User u = (User) con.newInstance(new Object[]{"haha", 123});
    //也可以不传参数数组,直接写参数列表
    Constructor con = uClass.getConstructor(String.class, int.class);
    User u = (User) con.newInstance("haha", 123);
    

    反射访问属性

    1. 示例类名 User,有成员属性 name
    User u = new User();
    //获取类User的name字段
    Field f = u.getClass().getDeclaredField("name");
    //修改这个字段的值
    f.set(u, "haha");
    //获取被修改后的值
    System.out.println(f.get(u));
    

    2.getDeclaredField()getField()

    getField() 只能获取public的,包括从父类继承来的字段。
    getDeclaredField() 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。
    注:这里只能获取到private的字段,但并不能访问该private字段的值,除非加上f.setAccessible(true)

    反射调用方法

    1. 常规方法
    User u = new User();
    Method m = u.getClass().getMethod("setName", String.class);
    //等同于
    Method m = 
          u.getClass().getMethod("setName", new Class[]{String.class});
    
    //对u对象,调用这个方法
    m.invoke(u, "Jack");
    //等同于
    m.invoke(u, new Object[]{"Jack"});
    
    1. getMethod() getDeclaredMethod()

    getMethod():获得类的public类型的方法。
    getDeclaredMethod():获得类的所有方法。
    gtMethod(String name, Class[] parameterTypes):获得类的特定方法,name 参数指定方法的名字,parameterTypes 参数指定方法的参数类型。

    反射的作用

    反射可以访问私有属性,private 还有什么意义?

    private 的作用是在面向对象的封装上 ,并不是为了解决安全问题。

    1. 作用: 在运行时构造一个类的对象;判断一个类所具有的成员变量和方法;调用一个对象的方法;生成动态代理

    2. 应用场景:反射最大的应用就是框架

      • spring 的 ioc/di
      • javaBean 和 jsp 之间调用
      • struts 的 FormBean 和页面之间
      • JDBC 的 classForName()
      • hibernate 的 find(Class clazz)
    3. 示例:通过配置文件,切换业务类和业务方法, 不需要修改一行代码,也不需要重新编译,只需要修改配置文件,再运行即可

      • 业务类
      package reflection;
       
      public class Service1 
      {
          public void doService1()
          {
              System.out.println("业务方法1");
          }
      }
      
      package reflection;
       
      public class Service2 
      {
          public void doService2()
          {
              System.out.println("业务方法2");
          }
      }
      
      • 配置文件 config.txt
      class=reflection.Service1
      method=doService1
      
      • 测试类
      public class Test 
      {
          public static void main(String[] args) throws Exception 
          {
              //从config.txt中获取类名称和方法名称
              File configFile = new File("config.txt");
              Properties config= new Properties();
              config.load(new FileInputStream(configFile));
              String className = (String) config.get("class");
              String methodName = (String) config.get("method");
               
              //根据类名称获取类对象
              Class clazz = Class.forName(className);
              //根据方法名称,获取方法对象
              Method m = clazz.getMethod(methodName);
              //获取构造器
              Constructor c = clazz.getConstructor();
              //根据构造器,实例化出对象
              Object service = c.newInstance();
              //调用对象的指定方法
              m.invoke(service);
          }
      }
      
  • 相关阅读:
    js正则表达式
    js正则表达式校验非负浮点数:^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$
    js正则表达式校验非正整数:^((-d+)|(0+))$
    读书笔记--第三章
    phpmyadmin创建数据库无权限
    读书笔记--第二章
    读书笔记--第一章 信息收集
    CTF-1-web安全
    kali优化配置(4)---被动信息收集
    以太坊私有链搭建
  • 原文地址:https://www.cnblogs.com/pgjett/p/12344557.html
Copyright © 2020-2023  润新知