Java语言基础-反射机制、正则表达式

反射机制

反射机制是在运行状态中,对于任意一个类,都能知道这个类(class文件)的所有属性和方法。
对于任意一个对象,都能调用它的任意一个方法和属性。
这种动态获取信息以及动态调用对象的方法的功能称为Java语言的反射机制。

简单来说,动态获取类中的信息,就是Java的反射机制。
可以理解为对类的解剖。

Tomcat
提供了处理请求和应答的方式。
因为具体的处理动作不同,所以对外提供了接口,由开发者来实现具体的请求和应答处理。

Class类可以获取字节码文件中的所有内容,反射就是依靠该类来完成的。
想要对一个类文件进行解剖,只要获取到该类的字节码文件即可。

获取类的字节码文件:

package cn.itcast.reflect.demo;

import cn.itcast.bean.Person;

/*
 * 要想对字节码文件进行解剖,必须要有字节码文件对象
 */
public class ReflectDemo {

    /**
     * @param args
     * @throws ClassNotFoundException 
     */
    public static void main(String[] args) throws ClassNotFoundException {
        
//        getClassObject_1();
//        getClassObject_2();
        getClassObject_3();
        
    }
    /*
     * 方式三:(重点)
     * 只要通过给定的类的字符串名称,就可以获取该类,更为扩展。
     * 可以用Class类中的方法完成。
     * 该方法就是forName。
     * 各种方式只要有名称即可,更为方便,扩展性更强。
     */
    public static void getClassObject_3() throws ClassNotFoundException {
        String className="cn.itcast.bean.Person";
        
        Class clazz=Class.forName(className);
        
        System.out.println(clazz);
    }
    
    /*
     * 方式二:
     * 任何数据类型都具有一个静态的属性.class来获取其对应的Class对象。
     * 不需要构造函数。
     * 相对简单,但是还是需要明确用到类中的静态成员。
     * 不够扩展
     */
    public static void getClassObject_2() {
        Class clazz=Person.class;
        
        Class clazz1=Person.class;
        System.out.println(clazz==clazz1);

    }

    /*
     * 获取字节码对象的方式:
     * 方式一:
     * Object类中的getClass方法
     * 想要用这种方式,必须要明确具体的类,并创建对象。
     */
    public static void getClassObject_1(){
        Person p=new Person();
        Class clazz=p.getClass();
        
        Person p1=new Person();
        Class clazz1=p1.getClass();
        
        System.out.println(clazz==clazz1);
    }

}

获取Class中的构造函数:

package cn.itcast.reflect.demo;

import java.lang.reflect.Constructor;

public class ReflectDemo2 {

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {

        // createNewObject();
        createNewObject_2();
    }

    public static void createNewObject_2() throws Exception {

        // cn.itcast.bean.Person p = new cn.itcast.bean.Person("小强",39);
        
        /*
         * 当要获取指定名称对应类中的所体现的对象时,
         * 而该对象初始化不使用空参数构造函数
         * 既然是通过指定的构造函数进行兑现的初始化,
         * 应先获取到该构造函数。
         * 通过字节码文件即可完成
         * 该方法是:getConstructor(parameterTypes)
         */
        String name = "cn.itcast.bean.Person";
        Class clazz = Class.forName(name);
        //获取到了指定的构造函数对象
        Constructor constructor=clazz.getConstructor(String.class,int.class);
        //通过该构造器对象的newInstance方法进行对象的初始化
        Object obj=constructor.newInstance("小明",38);
    }

    public static void createNewObject() throws ClassNotFoundException,
            InstantiationException, IllegalAccessException {

        // 早期:new的时候,先根据被new的类的名称查询该类的字节码文件,并加载进内存,并创建该字节码文件对象,然后创建该字节码文件对应的Person对象
        cn.itcast.bean.Person p = new cn.itcast.bean.Person();

        // 现在:
        String name = "cn.itcast.bean.Person";
        // 找寻该名称的类文件,并加载进内存,并产生Class对象
        Class clazz = Class.forName(name);
        // 如何产生该类的对象
        Object obj = clazz.newInstance();// 创建新实例
    }

}

获取Class中的字段示例:
public class AccessibleObjectextends Object implements AnnotatedElement
AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。

package cn.itcast.reflect.demo;

import java.lang.reflect.Field;

public class ReflectDemo3 {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        getFieldDemo();
    }

    /*
     * 获取字节码文件中的字段
     */
    public static void getFieldDemo() throws Exception {

        Class clazz = Class.forName("cn.itcast.bean.Person");

        // Field field=clazz.getField("age");//该方法只能获取到public的字段

        Field field=clazz.getDeclaredField("age");//只能获取本类中的所有字段(包含私有)
        //取消字段的访问权限检查,暴力访问
        field.setAccessible(true);
        
        Object obj=clazz.newInstance();
        
        field.set(obj, 90);
        Object o=field.get(obj);
        
        System.out.println(o);
    }

}

获取Class中的方法:

package cn.itcast.reflect.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import cn.itcast.bean.Person;

public class ReflectDemo4 {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        // getMethodDemo();
        // getMethodDemo_2();
        getMethodDemo_3();
    }

    public static void getMethodDemo_3() throws Exception {
        Class clazz = Class.forName("cn.itcast.bean.Person");

        Method method = clazz.getMethod("paramMethod", String.class, int.class);

        Object obj = clazz.newInstance();
        method.invoke(obj, "小强", 39);

    }

    public static void getMethodDemo_2() throws Exception {

        Class clazz = Class.forName("cn.itcast.bean.Person");

        Method method = clazz.getMethod("show", null);// 获取空参数一般方法
        // Person p=new Person();
        // p.show();

        // Object obj=clazz.newInstance();
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        Object obj = constructor.newInstance("小明", 37);
        method.invoke(obj, null);
    }

    /*
     * 获取指定Class中的公共函数
     */
    public static void getMethodDemo() throws Exception {

        Class clazz = Class.forName("cn.itcast.bean.Person");

        Method[] methods = clazz.getMethods();// 获取的都是公有的方法
        methods = clazz.getDeclaredMethods();// 只获取本类中所有方法(包括私有)

        for (Method method : methods) {
            System.out.println(method);
        }

    }

}

package cn.itcast.bean;

public class Person {

    private int age;
    private String name;

    public Person(String name, int age ) {
        super();
        this.age = age;
        this.name = name;
        System.out.println("person param run..."+this.name+":"+this.age);
    }
    public Person() {
        super();
        System.out.println("person run");
    }
    
    public void show(){
        System.out.println(name+"...show run..."+age);
    }
    
    private void privateMethod(){
        System.out.println("private method run");
    }
    
    public void paramMethod(String str,int num){
        System.out.println("paramMethod run......"+str+":"+num);
    }
    
    public static void staticMethod(){
        System.out.println("staticMethod run");
    }
}


反射练习:

package cn.itcast.reflect.test;

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

/*
 * 电脑运行
 */
public class ReflectTest {

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {

        MainBoard mb=new MainBoard();
        mb.run();
        
        //每次添加设备都需要修改代码,传递新创建的对象
//        mb.usePCI(new SoundCard());//新增SoundCard,需要修改程序
        
        
        //不修改代码,就能够完成以上动作
        //不使用new,而是直接获取class文件,在内部实现创建对象的动作
        File configFile=new File("pci.properties");
        
        Properties prop=new Properties();
        FileInputStream fis=new FileInputStream(configFile);
        
        prop.load(fis);
        
        for(int x=0;x<prop.size();x++){
            
            String pciName=prop.getProperty("pci"+(x+1));
            
            Class clazz=Class.forName(pciName);//用Class去加载这个pci子类
            
            PCI p=(PCI) clazz.newInstance();//创建的对象肯定是PCI的子类,可以直接将创建的对象类型强转为PCI
            
            mb.usePCI(p);
        }
        fis.close();
        
        
    }
}

package cn.itcast.reflect.test;

public class MainBoard {

    public void run() {
        System.out.println("main board run");
    }

    public void usePCI(PCI p) {//多态,提高扩展性
        if (p != null) {
            p.open();
            p.close();
        }
    }
}


package cn.itcast.reflect.test;

public interface PCI {
    
    public void open();
    public void close();
}
package cn.itcast.reflect.test;

public class SoundCard implements PCI{

    public void open(){
        System.out.println("sound open");
    }
    public void close(){
        System.out.println("sound close");
    }

}
package cn.itcast.reflect.test;

public class NetCard implements PCI{

    @Override
    public void open() {
        System.out.println("net open");
    }

    @Override
    public void close() {
        System.out.println("net close");
    }
}

pci.properties
pci1=cn.itcast.reflect.test.SoundCard
pci2=cn.itcast.reflect.test.NetCard


正则表达式
正则表达式用于操作字符串数据;
通过特定的符号来体现;
正则表达式虽然简化了书写,但是阅读性变差了。

package cn.itcast.regex.demo;

public class RegexDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {

        String qq = "123456789";
        // checkQQ(qq);

        String regex = "[1-9][0-9]{4,14}";// 正则表达式
        // String regex="[1-9]\\d{4,14}";//正则表达式

        // boolean b=qq.matches(regex);
        // System.out.println(qq+":"+b);

        String str = "aoob";
        String reg = "ao+b";// o有一次或多次
        boolean b = str.matches(reg);
        System.out.println(b);

    }

    /*
     * 需求:定义一个功能对QQ号进行校验
     * 要求:长度5-15位;只能是数字;0不能开头
     */
    public static void checkQQ(String qq) {
        int len = qq.length();
        if (len >= 5 && len <= 15) {
            if (!qq.startsWith("0")) {
                try {
                    long l = Long.parseLong(qq);
                    System.out.println(qq + "正确");
                } catch (NumberFormatException e) {
                    System.out.println(qq + "含有非法字符");
                }
            } else {
                System.out.println(qq + "不能0开头");
            }
        } else {
            System.out.println("长度错误");
        }
    }

}

正则表达式对字符串的常见操作
组和捕获
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

1     ((A)(B(C)))
2     \A
3     (B(C))
4     (C)

组零始终代表整个表达式。

之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用在表达式中使用,也可以在匹配操作完成后从匹配器获取。

与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组,则在第二次计算失败时将保留其以前捕获的值(如果有的话)例如,将字符串 "aba" 与表达式 (a(b)?)+ 相匹配,会将第二组设置为 "b"。在每个匹配的开头,所有捕获的输入都会被丢弃。

以 (?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。

public final class Patternextends Object implements Serializable
正则表达式的编译表示形式。
指定为字符串的正则表达式必须首先被编译为此类的实例(将正则表达式封装为对象)。然后,可将得到的模式用于创建 Matcher (匹配)对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。
因此,典型的调用顺序是
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();

package cn.itcast.regex.demo;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo2 {

    /**
     * @param args
     */
    public static void main(String[] args) {

        /*
         * 正则表达式对字符串的常见操作
         * 1.匹配
         * 使用的是String类中matchs方法;
         * 
         * 2.切割
         * 使用的是String类中的split方法;
         * 
         * 3.替换
         * 使用的是String类中的replaceAll方法;
         * 
         * 4.获取
         * 将正则规则进行对象的封装;
         * Pattern p = Pattern.compile("a*b");
         * 通过正则对象的matcher方法字符串相关联,获取要对字符串操作的匹配器对象Matcher
         * Matcher m = p.matcher("aaaaab");
         * 通过Matcher匹配器对象的方法对字符串进行操作
         * boolean b = m.matches();
         */
        // functionDemo1();
        // functionDemo2();
        // functionDemo3();
        functionDemo4();
    }

    /*
     * 获取示例
     */
    public static void functionDemo4() {
        String str = "da jia hao,ming tian bu fang jia!";

        String regex = "\\b[a-z]{3}\\b";// \\b-单词边界,否则会出现jia hao    min的情况

        // 1.将正则封装成对象
        Pattern p = Pattern.compile(regex);
        // 2.通过正则对象获取匹配器对象
        Matcher m = p.matcher(str);

        // 使用Matcher对象的方法对字符串进行操作
        // 既然要获取三个字母组成的单词
        // 进行查找 find()方法
        System.out.println(str);
        while (m.find()) {
            System.out.println(m.group());// 获取匹配器的子序列
            
            System.out.println(m.start()+":"+m.end());//输出开始和结束的位置
        }

    }

    /*
     * 替换示例
     */
    public static void functionDemo3() {

        String str = "zhangsantttxiaoqiangmmmmmzhaoliu";

        // str=str.replaceAll("(.)\\1+", "#");//将叠词替换为#

        str = str.replaceAll("(.)\\1+", "$1");// 将叠词替换为一个字母;$1,获取第一个参数中的第一组
        System.out.println(str);

        String tel = "15812345678";// 158****5678
        tel = tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
        System.out.println(tel);
    }

    /*
     * 切割示例
     */
    public static void functionDemo2() {
        // String str="zhangsan        xiaoqiang    zhaoliu";
        // String[] names=str.split(" +");//空格出现一次或多次

        // String str="zhangsan.xiaoqiang.zhaoliu";
        // String[] names=str.split("\\.");

        String str = "zhangsantttxiaoqiangmmmmmzhaoliu";// 按ttt,mmmmm切割
        // (X) X,作为捕获组 ;\n 任何匹配的 nth 捕获组
        // 组((A) (B(C)) 最外层括号为第一组,次外层为第二组,以此类推;无括号,则为第0组
        String[] names = str.split("(.)\\1+");// 第一位是任意字符,对任意字符进行复用
        for (String name : names) {
            System.out.println(name);
        }
    }

    /*
     * 匹配示例
     */
    public static void functionDemo1() {
        // 匹配手机号码是否正确
        String tel = "15800001111";
        // String regex="1[358][0-9]{9}";
        String regex = "1[358]\\d{9}";

        boolean b = tel.matches(regex);
        System.out.println(tel + ":" + b);
    }

}

正则表达式-练习:

package cn.itcast.regex.test;

import java.util.TreeSet;

public class RegexTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        /*
         * 1.治疗口吃:我...我我要要...要要..要学...学...编编编程...程程...程程
         * 2.对ip地址排序
         * 3.对邮件地址校验
         */
//        test_1();
//        test_2();
        test_3();
    }
    
    /*
     * 邮箱地址校验
     */
    public static void test_3() {
        
        String mail="abc1@sian.com.cn";
        
        String regex="[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]{2,3})+";//(\\.[a-zA-Z]{2,3})+,类似于.com,.cn的组,存在一次或者多次
        regex="\\w+@a\\w+(\\.\\w+)+";//笼统式匹配
        
        boolean b=mail.matches(regex);
        
        System.out.println(mail+":"+b);
        
    }

    /*
     * ip地址排序
     * 192.168.10.34    127.0.0.1    3.3.3.3    105.70.11.55
     */
    public static void test_2() {
        
        String ip_str="192.168.10.34  127.0.0.1 3.3.3.3    105.70.11.55";
        
        //1.为了让ip可以按字符串顺序比较,只要让ip的每一段位数相同,补零
        //按照每一位所需最多的0的个数进行补充;每一段都加2个0;
        
        ip_str=ip_str.replaceAll("(\\d+)", "00$1");
//        System.out.println(ip_str);//00192.00168.0010.0034  00127.000.000.001 003.003.003.003    00105.0070.0011.0055
        
        //2.每一段保留三位数字
        ip_str=ip_str.replaceAll("0*(\\d{3})", "$1");
//        System.out.println(ip_str);//192.168.010.034  127.000.000.001 003.003.003.003    105.070.011.055
        
        //切割ip地址
        String[] ips=ip_str.split(" +");
        TreeSet<String> ts=new TreeSet<String>();
        
        for(String ip:ips){
            ts.add(ip);
        }
        
        for(String ip:ts){
            System.out.println(ip.replaceAll("0*(\\d+)", "$1"));
        }
    }
    /*
     * 治口吃
     */
    public static void test_1(){
        
        String str="我...我我要要...要要..要学...学...编编编程...程程...程程";
        
        //1.将字符串中的 “.” 去掉,使用替换
        str=str.replaceAll("\\.+", "");
        //2.替换叠词
        str=str.replaceAll("(.)\\1+", "$1");
        System.out.println(str);
    }

}

正则表达式-练习-爬虫

package cn.itcast.regex.test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * 网页爬虫:其实是一个用于在互联网中获取符合指定规则数据的程序
 * 
 * 爬取邮箱地址
 */
public class RegexTest2 {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {

        // List<String> list=getMail();
        List<String> list = getMailByWeb();
        for (String mail : list) {
            System.out.println(mail);
        }

    }

    public static List<String> getMailByWeb() throws IOException {

        // 1.读取源文件
        URL url=new URL("http://iask.sina.com.cn/b/1005465.html");
        BufferedReader bufIn=new BufferedReader(new InputStreamReader(url.openStream()));

        // 2.对读取的数据进行规则的匹配,从中获取符合规则的数据
        String mail_regex = "\\w+@\\w+(\\.\\w+)+";

        List<String> list = new ArrayList<String>();

        Pattern p = Pattern.compile(mail_regex);

        String line = null;
        while ((line = bufIn.readLine()) != null) {
            Matcher m = p.matcher(line);
            while (m.find()) {
                // 3.将符合规则的数据存储到集合中
                list.add(m.group());
            }
        }
        bufIn.close();
        return list;
    }

    public static List<String> getMail() throws IOException {
        // 1.读取源文件
        BufferedReader bufr = new BufferedReader(
                new FileReader("c:\\mail.html"));

        // 2.对读取的数据进行规则的匹配,从中获取符合规则的数据
        String mail_regex = "\\w+@\\w+(\\.\\w+)+";

        List<String> list = new ArrayList<String>();

        Pattern p = Pattern.compile(mail_regex);

        String line = null;
        while ((line = bufr.readLine()) != null) {
            Matcher m = p.matcher(line);
            while (m.find()) {
                // 3.将符合规则的数据存储到集合中
                list.add(m.group());
            }
        }
        bufr.close();
        return list;
    }

}

posted on 2012-08-18 23:21  foolchen  阅读(307)  评论(0编辑  收藏  举报

导航