zoukankan      html  css  js  c++  java
  • java反射学习

    java反射机制的核心是在程序运行时动态的加载类并获取类的详细信息,从而操作类或对象的属性和方法。
    java反射机制可以绕过java封装、直接调用私有属性的类或者方法

    反射类的三种方法:
    1、Class xxx = 类名.class,当表示类类型的时候Class需要大写
    2、使用getClass()方法、需要已知该类的对象
    3、使用forName(类的全称)方法、在使用forName方法时需要包含在try{}catch(){}异常处理中进行使用
    public class Phone {
        //属性
        String screen = "qwer";
        int cpu;
        //方法
        public void method01(){
            System.out.println("第一个公有方法");
        }
        private void method02(){
            System.out.println("第二个私有方法");
        }
    
        public static void main(String[] args) {
            //获取类类型(Class对象)
            //第一个表达式
            Class c1 = Phone.class;
            //第二个表达方式,已知该类的对象
            Phone phone = new Phone();
            Class c2 = phone.getClass();
            //第三个表达式
            //Class c3 = null;
            try {
               Class<?> c3 = Class.forName("Phone");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    如果直接使用forName()方法,会报一个未处理的错误、需要添加到try/catch异常处理中
    public class Phone {
        //属性
        String screen = "qwer";
        int cpu;
        //方法
        public void method01(){
            System.out.println("第一个公有方法");
        }
        private void method02(){
            System.out.println("第二个私有方法");
        }
    
        public static void main(String[] args) {
            //第三个表达式
            Class c3 = null;
            c3 = Class.forName("Phone");	//在这里forName()会报错,需要写到异常处理方法内、参数为类的全称
        }
    }
    在IDEA中我们可以选中forName()方法,然后使用Ctrl+Alt+T,选中try/catch
    添加一个异常处理方法,就可以正常使用了。

    实例化对象:
    newinstance()实例化对象,它生成的对象只能反射无参的构造函数
    Constructor.newinstance()可以反射所有构造函数,包括私有的
    //实例化类的对象
            //第一个表达式
            try {
                Phone.class.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            //第二个表达式
            try {
                Class.forName("Phone").newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            //第三个表达式
            try {
                Phone.class.getConstructor().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
    方法:
    Method类,方法的对象,一个成员方法就是一个Method对象
    getMethods()方法获取的是所有的public,包括父类继承的,不能获取私有方法
    getDeclaredMethods()获取的是所有该类自己声明的方法,无视访问权限
    invoke执行方法
    如果这个方法是普通方法,那么第一个参数时类对象
    如果这个方法是静态方法,那么第一个参数时类
    //调用方法
            try {
                //获取方法
                Method m1 = c2.getDeclaredMethod("method02");
                //执行方法
                try {
                    m1.invoke(c2.newInstance());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
    
            try {
                    Method m2 = c2.getMethod("method01");
                try {
                    m2.invoke(c2.newInstance());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            } catch (NoSuchMethodException e) {
                    e.printStackTrace();
            }
    属性(成员变量):
    getFields()方法获取的是所有的Public的成员变量的信息
    getDeclaredFields()获取的是该类所有声明的成员变量信息
    //获取类的属性(成员变量)的信息
            //getFields()方法获取的是所有的Public的成员变量的信息
            Field[] fs01 = c1.getFields();
            for (Field field : fs01){
                //成员变量的类型的类类型
                Class fieldType = field.getType();
                String typeName = fieldType.getName();
                //成员变量的名称
                String fieldName = field.getName();
                System.out.println(typeName+" "+fieldName);
            }
    
            //getDeclaredFields()获取的是该类所有声明的成员变量信息
            Field[] fs02 = c1.getDeclaredFields();
            for (Field field:fs02){
                //得到成员变量的类型的类类型
                Class fieldType = field.getType();
                String typeName = fieldType.getName();
                //得到成员变量的名称
                String fieldName = field.getName();
                System.out.println(typeName+" "+fieldName);
            }
    从结果可以看出,getFields()只能获取到类的公开的成员变量信息
    getDeclaredFields()可以获取该类所有声明的成员变量信息


    实例:
    通过反射调用java.lang.runtime类,并执行系统命令。
    一开始是这么写的,出现错误说是java.lang为私有属性、不可以访问。
    原因是Runtime类的构造器是私有修饰的,无法直接获取runtime类的实例,只能通过getRuntime()方法来间接获取一个Runtime类的实例
    运行一下,可以成功执行命令打开记事本
    但是当我们执行cmd命令时无法打开cmd窗口
    网上存在一些方法,可以解决这个问题。测试了一下发现只能执行dir命令,执行其他命令运行完成后cmd窗口会闪退,但是不影响程序的运行。
    我们可以直接使用echo函数写入一个文件
    当我们需要运行一个应用程序的时候,需要在写入这个程序的绝对路径
    如果该应用程序添加了环境变量或者在system32目录下,则不用写入绝对路径
    这样就可以直接打开远程桌面程序。
  • 相关阅读:
    Firefox OS 开发者预览版手机上线数小时即售罄
    7 款风格新颖的 jQuery/CSS3 导航
    大数据时代的 9 大KeyValue存储数据库
    jQuery 2.0发布,不支持IE 6/7/8
    全面理解面向对象的 JavaScript
    Hdoop入门
    Java Web 高性能开发,第 2 部分: 前端的高性能
    MySQL数据库存储引擎和分支现状
    11 个超棒的 jQuery 分步指引插件
    [扩展/新建swap]将文件或分区加载为swap
  • 原文地址:https://www.cnblogs.com/Excellent-person/p/14021917.html
Copyright © 2011-2022 走看看