今天不想跑,所以才去跑|

凉白茶

园龄:2年4个月粉丝:19关注:7

2023-07-21 15:56阅读: 36评论: 0推荐: 1

反射 p1 反射机制

反射机制

引出反射

  • 这样的需求在学习框架时特别多,即通过外部文件配置,在不修改源码的情况下,来控制程序,也符合设计模式的OCP原则(开闭原则:不修改源码,扩展功能)。

  • 代码演示:

    re.properties文件:

    classfullpath=com.hspedu.Cat
    method=cry

    Cat类:

    package com.hspedu;
    /**
    * @author: 86199
    * @date: 2023/5/18 10:09
    * @description:
    */
    public class Cat {
    private Strinag name = "招财猫";
    public int age = 10;
    public Cat() {
    }
    public Cat(String name) {
    this.name = name;
    }
    public void hi(){
    System.out.println("hi" + name);
    }
    public void cry(){
    System.out.println(name + "喵喵叫");
    }
    }

    ReflectionQuestion:

    package com.hspedu.reflection.question;
    import com.hspedu.Cat;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Properties;
    /**
    * @author: 86199
    * @date: 2023/5/18 10:14
    * @description:
    */
    public class ReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    //普通方式
    // Cat cat = new Cat();
    // cat.hi();
    //IO流,使用Preperties类读写配置文件
    Properties properties = new Properties();
    properties.load(
    new FileReader("src\\com\\hspedu\\re.properties"));
    String classfullpath = properties.get("classfullpath").toString();
    String methodName = properties.getProperty("method");
    System.out.println(classfullpath);
    System.out.println(methodName);
    //使用反射解决
    //(1)加载类,返回Class类型的对象 cls
    Class cls = Class.forName(classfullpath);
    //(2)通过cls 得到你的加载的类 com.hspedu.Cat 的对象实例
    Object o = cls.newInstance();
    System.out.println("o 的运行类型 = " + o.getClass());//运行类型
    //(3)通过 cls 得到你加载的类 com.hspedu.Cat 的 methodName"hi" 的方法对象
    // 即:在反射中,可以把方法视为对象(万物皆对象)
    Method method = cls.getMethod(methodName);
    //(4) 通过method调用方法:即通过方法对象类实现调用方法
    System.out.println("============================");
    method.invoke(o);
    //可以直接通过修改配置文件,而不是源码来改变调用的方法
    }
    }
    /*运行结果:
    com.hspedu.Cat
    cry
    o 的运行类型 = class com.hspedu.Cat
    ============================
    招财猫喵喵叫
    */

反射机制

  1. 反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到;
  2. 加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以形象的称之为:反射。
  3. 在启动时,包含main方法的类被加载。它会加载所有需要的类。这些被加载的类又要加载它们需要的类,以此类推。
  • 反射原理图

  • 弹幕摘要:

    • 加载的过程在方法区,加载结果(对象)在堆区,不知道对不对;
    • 类加载是将数据放入的内存的方法区中,然后在堆创建一个class对象,说白了就是堆中的class是用来封装方法区数据的类
  • 疑惑:

    • 那为什么需要这样一个Class对象呢?

      • Class类的对象的作用是运行时提供或获得某个对象的类型信息,这点对于反射技术很重要。
      • 是这样的,当我们new一个新对象或者引用静态成员变量时,Java虚拟机(JVM)中的类加载器子系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要实例对象或者提供静态变量的引用值。也就是说,Class对象对于类的实例化具有非常重要的意义。没它就没法new新对象和引用静态成员变量。

      ————————————————
      版权声明:本文为CSDN博主「一只野生饭卡丘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
      原文链接:https://blog.csdn.net/Searchin_R/article/details/84591735

反射相关的主要类

  1. java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象;
  2. java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法;
  3. java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量;
  4. java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器;
  • 代码演示

    package com.hspedu.reflection;
    import java.io.FileReader;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.Properties;
    /**
    * @author: 86199
    * @date: 2023/5/20 10:52
    * @description:
    */
    public class Reflection01 {
    public static void main(String[] args) throws Exception{
    //1. IO流,使用Preperties类读写配置文件
    Properties properties = new Properties();
    properties.load(
    new FileReader("src\\com\\hspedu\\re.properties"));
    String classfullpath = properties.get("classfullpath").toString();
    String methodName = properties.getProperty("method");
    //2. 使用反射解决
    //(1)加载类,返回Class类型的对象 cls
    Class cls = Class.forName(classfullpath);
    //(2)通过cls 得到你的加载的类 com.hspedu.Cat 的对象实例
    Object o = cls.newInstance();
    System.out.println("o 的运行类型 = " + o.getClass());//运行类型
    //(3)通过 cls 得到你加载的类 com.hspedu.Cat 的 methodName"hi" 的方法对象
    // 即:在反射中,可以把方法视为对象(万物皆对象)
    Method method = cls.getMethod(methodName);
    //(4) 通过method调用方法:即通过方法对象类实现调用方法
    System.out.println("============================");
    method.invoke(o);
    //java.lang.reflect.Field:代表类的成员变量,Filed对象白哦是某个类的成员变量
    //得到age字段
    //getField不能得到私有属性
    Field ageFiled = cls.getField("age");
    System.out.println(ageFiled.get(o));
    //java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器
    Constructor constructor = cls.getConstructor();//()中可以指定构造器参数类型,不指定返回无参构造器
    System.out.println(constructor);//Cat()
    Constructor constructor1 = cls.getConstructor(String.class);//传入String类的Class对象
    System.out.println(constructor1);//Cat(java.lang.String)
    }
    }
  • 反射的优缺点:

    • 优点:可以动态的创建和使用对象(也是框架的底层核心),使用灵活,没有反射机制,框架技术就失去了底层支撑。

    • 缺点:使用反射基本是解释执行,对执行速度有影响。

反射调用优化——关闭访问检查

  1. Method和Field、Constructor对象都有setAccessible()方法;
  2. setAccessible()作用是启动和禁用访问安全检查的开关;
  3. 参数值为true表示反射的对象在使用时取消访问检查,可以提高反射的效率。参数值为false则表示反射的对象执行访问检查。

  • 代码演示:

    package com.hspedu.reflection;
    import com.hspedu.Cat;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    /**
    * @author: 86199
    * @date: 2023/5/20 11:20
    * @description: 测试反射调用的性能,和优化方案
    */
    public class Reflection02 {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
    m1();
    m2();
    m3();
    }
    //这里先把hi()方法中的打印注释了
    //传统方法调用方法hi
    public static void m1(){
    Cat cat = new Cat();
    long start = System.currentTimeMillis();
    for (int i = 0; i < 90000000; i++){
    cat.hi();
    }
    long end = System.currentTimeMillis();
    System.out.println("m1() 耗时 = " + (end - start));
    }
    //反射机制调用方法hi
    public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class cls = Class.forName("com.hspedu.Cat");
    Object o = cls.newInstance();
    Method method = cls.getMethod("hi");
    long start = System.currentTimeMillis();
    for (int i = 0; i < 90000000; i++){
    method.invoke(o);
    }
    long end = System.currentTimeMillis();
    System.out.println("m2() 耗时 = " + (end - start));
    }
    //反射优化:关闭访问检测
    public static void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class cls = Class.forName("com.hspedu.Cat");
    Object o = cls.newInstance();
    Method method = cls.getMethod("hi");
    method.setAccessible(true);//取消在访问调用方法时的访问检查
    long start = System.currentTimeMillis();
    for (int i = 0; i < 90000000; i++){
    method.invoke(o);
    }
    long end = System.currentTimeMillis();
    System.out.println("m3() 耗时 = " + (end - start));
    }
    }
    /*运行结果
    m1() 耗时 = 3
    m2() 耗时 = 197
    m3() 耗时 = 168
    */

本文作者:凉白茶

本文链接:https://www.cnblogs.com/zh-Note/p/17557508.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   凉白茶  阅读(36)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.

作曲 : Reol

作词 : Reol

fade away...do over again...

fade away...do over again...

歌い始めの一文字目 いつも迷ってる

歌い始めの一文字目 いつも迷ってる

どうせとりとめのないことだけど

伝わらなきゃもっと意味がない

どうしたってこんなに複雑なのに

どうしたってこんなに複雑なのに

噛み砕いてやらなきゃ伝わらない

ほら結局歌詞なんかどうだっていい

僕の音楽なんかこの世になくたっていいんだよ

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.

目の前 広がる現実世界がまた歪んだ

目の前 広がる現実世界がまた歪んだ

何度リセットしても

僕は僕以外の誰かには生まれ変われない

「そんなの知ってるよ」

気になるあの子の噂話も

シニカル標的は次の速報

麻痺しちゃってるこっからエスケープ

麻痺しちゃってるこっからエスケープ

遠く遠くまで行けるよ

安定なんてない 不安定な世界

安定なんてない 不安定な世界

安定なんてない きっと明日には忘れるよ

fade away...do over again...

fade away...do over again...

そうだ世界はどこかがいつも嘘くさい

そうだ世界はどこかがいつも嘘くさい

綺麗事だけじゃ大事な人たちすら守れない

くだらない 僕らみんなどこか狂ってるみたい

本当のことなんか全部神様も知らない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.