反射总结

一、Servlet3.0


概念:支持注解开发,由注解配置来代替web.xml配置

用法:在Servlet类上直接使用@WebServlet注解

  • 常用属性

    • name:String

      • 设置Servlet名称

    • urlPatterns:String[]

    • loadOnStartup:int

    • initParams: WebInitParam[]

      • initParams = {@WebInitParam(name = "username" ,value = "root"),
                   @WebInitParam( name = "password" ,value = "root123")}
      • 设置Servlet的初始化参数

二、类加载


  • 类的加载概述 :在class文件加载到jvm中时,会对应创建一个Class对象;分为三个步骤:加载、连接、初始化

    • 加载

      • 将class文件加载到内存区域,对应生成一个Class对象

    • 连接

      • 验证: 验证类的结构是否正确

      • 准备 :初始化静态成员

      • 解析 :将字节转换成jvm能够执行的引用(对象、变量、方法)

    • 初始化 就是对变量的初始化

 

三、类加载器


  • 类加载器的概述 :

    • 将class文件加载进内存,并生成对应的Class对象

  • 类加载器的分类

 

四、类反射机制


概念:通过类的Class对象,动态去调用类中的属性和方法

  • 获取Class对象的方式:

    • 全限定名:包名+类名

      • Class.forName("全限定名")

    • 编译期(在编译为.class的阶段)

      • 类名.class

    • 运行时

      • 对象名.getClass()

 

 

五、反射结合工厂模式


  • 使用继承

    • 解决Apple类、Banana类的代码复用性

    • Banana、Apple继承Fruit类

  • 使用工厂模式

    • 解决Banana、Apple和其他模块耦合较高

  • 使用反射机制

    • 解决工厂的getFruit方法中if...else代码过多

    • public static Fruit getFruit(String className) throws Exception {
              return (Fruit)Class.forName(className).newInstance();
          }

 

六、反射操作构造器(通过构造方法创建对象(构造方法的参数))


概念:使用反射机制操作public、protected、默认、private的构造器

  • 使用构造器创建无参对象

    • Class<?> c = Class.forName("com.qf.day52.bean.User");
      //获取构造器
      Constructor<?> constructor = c.getConstructor();
      //得到对象
      Object o = constructor.newInstance();
  • 使用构造器创建有参对象

    • Constructor<?> constructor1 = c.getConstructor(String.class,Integer.class,String.class);
      //构造器中传入数据类型
              Object o1 = constructor1.newInstance("阿杰", 20, "男");
      //传入参数
              System.out.println(o1);
  • 访问非public修饰的构造器

    • 注意:要用getDeclaredConstructor获得全部构造方法

    • //用getDeclaredConstructor获取全部构造方法
      Constructor<?> constructor2 = c.getDeclaredConstructor(String.class,Integer.class);
              constructor2.setAccessible(true);//暴力反射
              Object object = constructor2.newInstance("光芒", 20);

 

七、反射操作成员变量 (改变属性值)


概念:使用反射机制操作public、protected、默认、private的成员变量

public修饰的成员变量(属性):

  • 必须是public ,protected、default、private 不行

  •         Class<User> userClass = User.class; //获取类对象
            User user = userClass.newInstance(); //获取对象
            Field name = userClass.getField("name");//获取Field
            name.set(user,"阿杰");//赋值
            System.out.println(user);
    ​
            Object o1 = name.get(user);//通过Field获取赋的值
            System.out.println(o1);
  • 通过Field获取赋的值: field.get(对象)

非public修饰的成员变量(属性):

        Field declaredField = userClass.getDeclaredField("sex");
        declaredField.setAccessible(true);//暴力反射
        declaredField.set(user,"男");//设置成员变量
        System.out.println(user);
​
        Object o2 = declaredField.get(user);
        System.out.println(o2);

 

八、反射操作成员方法(对方法进行控制)


概念:使用反射机制操作public、protected、默认、private的成员方法

操作public修饰的成员方法

        Class<User> userClass = User.class;//获取类对象
        User user = userClass.newInstance();//获取对象
        Method setAge = userClass.getMethod("setAge", Integer.class);//获取方法
        setAge.invoke(user,20);//执行方法

注意:获取的方法要在参数中输入方法名 和参数类型,invoke()中要输入对象和参数

操作非public修饰的成员方法

        Method method = userClass.getDeclaredMethod("setName", String.class);//获取全部方法
        method.setAccessible(true);//暴力反射
        method.invoke(user,"阿杰");//执行方法

 

九、反射越过泛型检查


附:运行时对象是没有泛型,通过对象.getClass获得类对象,然后操作

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
​
        Class<? extends List> listClass = list.getClass();//获取类对象
        Method add = listClass.getDeclaredMethod("add",Object.class);//获取方法
        add.setAccessible(true);//暴力反射
        add.invoke(list,"str");//执行
        System.out.println(list);//打印

注意:参数的类型范围要大,所以写 Object.class

 

十、反射通用方法案例


需求:给指定对象的指定属性赋值

  • 步骤:

    • //获取方法名,通过属性名 :set+属性名第一个字母变大写+后面的属性名

    • //获得类对象

    • //获得属性

    • //获得属性的类型

    • //获得方法

    • //执行方法

public static void methods(Object obj, String fields , Object value) throws Exception{
        //获取方法名,通过属性名 :set+属性名第一个字母变大写+后面的属性名
        String result = "set"+ fields.substring(0,1).toUpperCase() + fields.substring(1);
        Class<?> c = obj.getClass();//获得类对象
        Field field1 = c.getField(fields);//获得属性
        Class<?> type = field1.getType();//获得属性的类型
​
        Method method = c.getMethod(result, type);//获得方法
        method.invoke(obj,value);//执行方法
    }

注意:通过field.type可以得到属性的类型

 

十一、反射结合配置文件


编写demo.properties,配置对象的唯一标识及对象的全类名,根据这段配置创建一个对象

代码实现

根据配置文件生成对象

        Properties properties = new Properties();//创建properties对象
        InputStream resourceAsStream =                                    Demo07.class.getClassLoader().getResourceAsStream("demo.properties");//获取流
        properties.load(resourceAsStream);//读取文件
​
        System.out.println(Class.forName(properties.getProperty("demo01")));//获得对象
        System.out.println(Class.forName(properties.getProperty("demo02")));

配置文件

demo01=com.qf.day52.bean.Fruit
demo02=com.qf.day52.bean.User

 

十二、静态代理设计模式

概念:增强被代理类的功能

代码实现:

public class UserDaoProxy implements UserDao {//实现接口
​
    private UserDao userDao = new UserDaoImpl();//创建对象
    @Override
    public void insert() {
        System.out.println("检测");
        userDao.insert();//调用方法
        System.out.println("记录日志");
    }
    @Override
    public void delete() {
    }
    @Override
    public void update() {
    }
    @Override
    public void select() {
    }
}
​

特点:

  • 缺点:必须要重写被代理类接口的所有的方法(包括不需要增强的方法,增高了耦合性)

  • 作用:增强被代理类的功能

  • 特点:可以控制被代理类对象

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值