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="[email protected]";

        

        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;

    }



}

你可能感兴趣的:(java语言)