• 反射(一)


    Properties

    void load(InputStream inStream)
    void load(Reader reader)
    void store(OutputStream out,String comments)
    void store(Writer writer,String comments)
    
    • 1
    • 2
    • 3
    • 4

    读取文件内容

            Properties properties = new Properties();
            properties.load(new FileInputStream("idea_test\\src\\re.properties"));
            String classfullpath = properties.getProperty("classfullpath");		// 读取 导入进来的信息
            String methodName = properties.getProperty("method");
    
    • 1
    • 2
    • 3
    • 4

    写入文件内容

            Properties prop = new Properties();
            prop.setProperty("001","林青霞");
            prop.setProperty("002","张曼玉");
            prop.setProperty("003","王祖贤");
    
            prop.store(new FileWriter("idea_test\\src\\re.txt"),null);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    引入

            // 传统创建对象的方式
            Cat cat = new Cat();
            cat.hi();
    
    
            // 根据 配置文件指定的信息, 创建对象
            Properties properties = new Properties();
            properties.load(new FileInputStream("idea_test\\src\\re.properties"));
            String classfullpath = properties.getProperty("classfullpath");
            String methodName = properties.getProperty("method");
    
    //        加载类, 并得到 Class对象
            Class<?> cls = Class.forName(classfullpath);
    //        得到 被加载的类的 一个对象实例
            Object instance = cls.getDeclaredConstructor().newInstance();
            System.out.println("instance 的运行类型为: " + instance.getClass());
    //        得到 被加载的类的 方法methodName 的一个对象
    //        在反射中, 可以把方法视为对象
            Method method1 = cls.getMethod(methodName);
            System.out.println("================================");
    //        调用该方法
            method1.invoke(instance);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    反射的优点:可以通过不修改源代码,只修改配置文件,达到控制程序的效果。

    类加载器加载Cat.class字节码文件,然后在堆中就产生了一个Class对象(Class类的一个实例)(一个类只有一个Class对象),这个对象包含了Cat类的完整结构信息。(成员变量 Field[] fields,构造器 Constructor[] cons,成员方法 Method[] ms,等等)

    反射相关的类

    public class Cat {
        private String name;
        private Integer age;
        private Integer sex;
    
        public Cat(){}
        public Cat(String name){}
        public Cat(String name,Integer age,Integer sex){}
        
        public void hi(){
            System.out.println("hi...");
        }
        public void cry(){
            System.out.println("cry...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    //        加载类, 并得到 Class对象
            Class<?> cls = Class.forName("com.itheima.Cat");
            Field[] fields = cls.getDeclaredFields();
            Method[] methods = cls.getDeclaredMethods();
            Constructor<?>[] constructors = cls.getDeclaredConstructors();
    
            System.out.println();
            Stream.of(fields).forEach(System.out::println);
            System.out.println("========================");
            Stream.of(methods).forEach(System.out::println);
            System.out.println("========================");
            Stream.of(constructors).forEach(System.out::println);
    
            // 也可以指定要取哪一个
            Field age = cls.getDeclaredField("age");
            // 得到参数为一个 String 的构造方法对象
            Constructor<?> constructor1 = cls.getDeclaredConstructor(String.class);
            // 得到无参的构造方法对象
            Constructor<?> constructor2 = cls.getDeclaredConstructor();
    
    // Output
    private java.lang.String com.itheima.Cat.name
    private java.lang.Integer com.itheima.Cat.age
    private java.lang.Integer com.itheima.Cat.sex
    ========================
    public void com.itheima.Cat.hi()
    public void com.itheima.Cat.cry()
    ========================
    public com.itheima.Cat(java.lang.String,java.lang.Integer,java.lang.Integer)
    public com.itheima.Cat(java.lang.String)
    public com.itheima.Cat()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    反射调用优化

    使用反射,对执行速度有影响。

            // 传统调用方法
            m1();
            // 反射机制调用
            m2();
    
    // Output
    m1() 耗时:12
    m2() 耗时:2895
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
        public static void m1(){
            Cat c = new Cat();
            long start = System.currentTimeMillis();
            for(int i = 0; i < 900000000; i++){
                c.hi();
            }
            long end = System.currentTimeMillis();
            System.out.println("m1() 耗时:" + (end - start));
        }
        public static void m2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            Class<?> cls = Class.forName("com.itheima.Cat");
            Object newInstance = cls.getDeclaredConstructor().newInstance();
            Method hiMethod = cls.getMethod("hi");
    
            long start = System.currentTimeMillis();
            for(int i = 0; i < 900000000; i++){
                hiMethod.invoke(newInstance);
            }
            long end = System.currentTimeMillis();
            System.out.println("m2() 耗时:" + (end - start));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Method,Field,Constructor对象都有setAccessible方法。
    setAccessible作用是启动和禁用访问安全检查的开关。
    设置为true,关闭检查,可以加快一点点速度。

    Class类

    1.Class类实例不是new出来的,而是系统进行类加载的时候创建的。
    2.对于某个类的Class类实例,在内存中只有一份,因为类只加载一次。
    3.通过Class类实例可以完整的得到一个类的完整结构。
    4.Class类实例是存放在堆的。
    5.Cat类的字节码文件二进制数据,是存放在方法区的,有的地方称为类的元数据。
    一些其他的API

            Class<?> cls = Class.forName("com.itheima.Cat");
    
            System.out.println(cls.getName());  // 被加载的类的全限定名
            System.out.println(cls.getPackage().getName()); // 被加载的类的包名
            Field name = cls.getDeclaredField("name");
            System.out.println(name.get(instance));     // 得到属性对应的值
            name.set(instance,"xxx");                   // 设置属性的值
            System.out.println(name.get(instance));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如何得到Class类的实例?

            // 多用于配置文件, 读取类的全路径, 加载类。
            Class<?> cls1 = Class.forName("com.itheima.Cat");
            // 类名.class, 多用于参数传递。
            Class<Cat> cls2 = Cat.class;
            // 对象.getClass()
            Class<? extends Cat> cls3 = new Cat().getClass();
            // 通过类加载器[4种]
            ClassLoader classLoader = Cat.class.getClassLoader();
            Class<?> cls4 = classLoader.loadClass("com.itheima.Cat");
            // 基本数据类型(int,char,double,boolean,long,short), 按如下方式
            Class<Integer> integerClass = int.class;
            Class<Character> characterClass = char.class;
            Class<Boolean> booleanClass = boolean.class;
            // 包装类
            Class<Integer> type1 = Integer.TYPE;
            Class<Character> type2 = Character.TYPE;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    哪些类型有Class类的实例?

            Class<Cat> catClass = Cat.class;    // 类,(内部类也有)
            Class<Serializable> serializableClass = Serializable.class; // 接口
            Class<Integer[]> aClass = Integer[].class;  // 数组
            Class<float[][]> aClass1 = float[][].class; // 二维数组
            Class<Deprecated> deprecatedClass = Deprecated.class;   // 注解
            Class<Thread.State> stateClass = Thread.State.class;    // 枚举
            Class<Long> longClass = long.class;     // 基本数据类型
            Class<Void> voidClass = void.class;     // void
            Class<Class> classClass = Class.class;  // Class类自身也有
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    深入理解Java类加载器
    getDeclaredFields() 和 getFields() 区别
    Class对象是放在方法区还是堆中

  • 相关阅读:
    python利用matplotlib画实验图
    MySQL临时表创建出错(OS errno 13 - Permission denied)
    系统开发视角下的诊断 ———— 动力系统(P)诊断故障10
    Android studio初次运行项目报错
    Codeforces Round #835 (Div. 4) E. Binary Inversions
    推特API(Twitter API)V2 查询用户信息
    计算机毕业设计Java网上投稿管理系统(源码+系统+mysql数据库+Lw文档)
    JAVA代码审计-json web token 安全分析
    借道元宇宙 一汽-大众揽巡打造沉浸式上市体验
    查找子字符串s1在字符串s中最后出现的位置rindex()方法
  • 原文地址:https://blog.csdn.net/qq_53318060/article/details/125586893