zoukankan      html  css  js  c++  java
  • Java 递归 反射 正则表达式

    递归

    1. 就是函数自身调用自身 (就是在栈内存中不断的加载同一个函数)

    2. 什么时候用递归呢?

    当一个功能被重复使用 而每一次使用该功能时的参数不确定 都由上次的功能元素结果来确定

    简单说: 功能内部又用到该功能 但是传递的参数值不确定(每次功能参与运算的未知内容不确定)

    3. 递归的注意事项

    1> 一定要定义递归的条件

    2> 递归的次数不要过多 容易出现 StackOverflowError 栈内存溢出错误

     

    反射

    其实就是动态加载一个指定的类 并获取该类中的所有的内容 而且将字节码文件封装成对象 并将字节码文件中的内容都封装成对象 这样便于操作这些成员 简单说: 反射技术可以对一个类进行解剖

    1. 反射的好处

    大大的增强了程序的扩展性

    2. 反射的基本步骤

    1> 获得Class对象 就是获取到指定的名称的字节码文件对象

    2> 实例化对象 获得类的属性, 方法或构造函数

    3> 访问属性, 调用方法, 调用构造函数创建对象

    3. 获取这个Class对象 有三种方式

    1> 通过每个对象都具备的方法getClass来获取 弊端: 必须要创建该类对象 才可以调用getClass方法(不利于程序的扩展 因为都需要在程序使用具体的类来完成)

    2> 每一个数据类型(基本数据类型和引用数据类型都有一个静态的属性class 弊端: 必须要先明确该类(不利于程序的扩展 因为都需要在程序使用具体的类来完成)

    3> 使用的Class类中的方法 (静态的forName方法) 指定什么类名 就获取什么类字节码文件对象 这种方式的扩展性最强 只要将类名的字符串传入即可

    // 根据给定的类名来获得 用于类加载

    String classname = "cn.itcast.reflect.Person"; // 来自配置文件

    Class clazz = Class.forName(classname); // 此对象代表Person.class

    // 如果拿到了对象 不知道是什么类型 用于获得对象的类型

    Object obj = new Person();

    Class clazz1 = obj.getClass(); // 获得对象具体的类型

    // 如果是明确地获得某个类的Class对象 主要用于传参

    Class clazz2 = Person.class;

    4. 反射的用法

    1> 需要获得java类的各个组成部分 首先需要获得类的Class对象 获得Class对象的三种方式

    Class.forName(classname) ---> 用于做类加载

    obj.getClass() ---> 用于获得对象的类型

    类名.class ---> 用于获得指定的类型 传参用

    2> 反射类的成员方法

    Class clazz = Person.class;

    Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2});

    method.invoke();

    3> 反射类的构造函数

    Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2, ...});

    con.newInstance(params...);

    4> 反射类的属性

    Field field = clazz.getField(fieldName);

    field.setAccessible(true);

    field.setObject(value);

    5. 获取了字节码文件对象后 最终都需要创建指定类的对象

    创建对象的两种方式(其实就是对象在进行实例化时的初始化方式)

    1> 调用空参数的构造函数: 使用了Class类中的newInstance()方法

    2> 调用带参数的构造函数: 先要获取指定参数列表的构造函数对象 然后通过该构造函数的对象的newInstance(实际参数) 进行对象的初始化

    综上所述 第二种方式 必须要先明确具体的构造函数的参数类型 不便于扩展 所以一般情况下 被反射的类 内部通常都会提供一个公有的空参数的构造函数

    // 如何生成获取到字节码文件对象的实例对象
    Class clazz = Class.forName("com.huangyi.domain.Person"); //类加载
    // 直接获得指定的类型
    clazz = Person.class;
    // 根据对象获得类型
    Object obj = new Person("zhangsan", 19);
    clazz = obj.getClass();
    Object obj = clazz.newInstance(); //该实例化对象的方法调用就是指定类中的空参数构造函数 给创建对象进行初始化 当指定类中没有空参数构造函数时 使用method_2();
    public static void method_2() throws Exception {
        Class clazz = Class.forName("com.huangyi.domain.Person");
        //既然类中没有空参数的构造函数 那么只有获取指定参数的构造函数 用该函数来进行实例化
        //获取一个带参数的构造器
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        //想要对对象进行初始化 使用构造器的方法newInstance();
        Object obj = constructor.newInstance("zhagnsan", 30);
        //获取所有构造器
        Constructor[] constructors = clazz.getConstructors(); //只包含公共的
        constructors = clazz.getDeclaredConstructors(); //包含私有的
        for(Constructor con : constructors) {
            System.out.println(con);
        }
    }

    6. 反射指定类中的方法

    //获取类中所有的方法
    public static void method_1() throws Exception {
        Class clazz = Class.forName("com.huangyi.domain.Person");
        Method[] methods = clazz.getMethods(); //获取的是该类中的公有方法和父类中的公有方法
        methods = clazz.getDeclaredMethods(); //获取本类中的方法 包含私有方法
        for(Method method : methods) {
            System.out.println(method);
        }
    }
    
    //获取指定方法
    public static void method_2() throws Exception {
        Class clazz = Class.forName("com.huangyi.domain.Person");
        //获取指定名称的方法
        Method method = clazz.getMethod("show", int.class, String.class);
        //想要运行指定方法 当然是方法对象最清楚 为了让方法运行 调用方法对象的invoke方法即可 但是方法运行必须要明确所属的对象和具体的实际参数
        Object obj = clazz.newInstance();
        method.invoke(obj, 39, "hehehe"); //执行一个方法
    }
    
    //想要运行私有方法
    public static void method_3() throws Exception {
        Class clazz = Class.forName("com.huangyi.domain.Person");
        //想要获取私有方法 必须用getDeclearMethod();
        Method method = clazz.getDeclaredMethod("method", null);
        // 私有方法不能直接访问 因为权限不够 非要访问 可以通过暴力的方式
        method.setAccessible(true); //一般很少用 因为私有就是隐藏起来 所以尽量不要访问
    }
    
    //反射静态方法
    public static void method_4() throws Exception {
        Class clazz = Class.forName("com.huangyi.domain.Person");
        Method method = clazz.getMethod("function", null);
        method.invoke(null, null);
    }

      

    正则表达式

    其实是用来操作字符串的一些规则 (其实更多是用正则解决字符串操作的问题)

    1. 好处: 正则的出现 对字符串的复杂操作变得更为简单

    2. 特点: 将对字符串操作的代码用一些符号来表示 只要使用了指定符号 就可以调用底层的代码对字符串进行操作 符号的出现 简化了代码的书写

    3. 弊端:符号的出现虽然简化了书写 但是却降低了阅读性

    4. 常见操作

    1> 匹配 其实用的就是String类中的matches方法

    String reg = "[1-9][0-9]{4,14}";

    boolean b = qq.matches(reg); //将正则和字符串关联对字符串进行匹配

    2> 切割 其实用的就是String类中的split方法

    3> 替换 其实用的就是String类中的replaceAll();

    4> 获取

    a. 先要将正则表达式编译成正则对象 使用的是Pattern中静态方法 compile(regex);

    b. 通过Pattern对象获取Matcher对象

    c. 使用Matcher对象中的方法即可对字符串进行各种正则操作

    5. 常用符号

     

  • 相关阅读:
    【十大思想实验之中的一个】电车难题
    XMLHTTP使用具体解释
    高速排序 解析
    RapeLay(电车之狼R)的结局介绍 (隐藏结局攻略)
    java设计模式演示样例
    [Network]Transport Layer
    【2012.1.24更新】不要再在网上搜索eclipse的汉化包了!
    WebService究竟是什么?
    epoll使用具体解释(精髓)
    贪心算法
  • 原文地址:https://www.cnblogs.com/huangyi-427/p/4717381.html
Copyright © 2011-2022 走看看