反射与正则表达式

一、类的加载:

原理理解:

当使用某个类的时候,如果该类还没有被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

a、加载:

就是指将class文件读入到内存,并创建一个Class对象

         任何类被使用时系统都会建立一个Class对象

b、连接:

         验证 : 是否有正确的内部结果,并和其他类协调一致。

         准备: 负责为类的静态成员分配内存,并配置默认初始化值。

        解析: 将类的二进制数据中的符号引用替换为直接的引用。

c、初始化 :

 

类初始化时机:

1.访问类的实例

2.访问类的静态变量,或者为静态变量赋值,

3.调用类的静态方法

4.调用反射方式来强制创建某个类或者接口对应的

5. Java.lang.Class对象。

6. 初始化某个类的子类

7. 直接使用java.exe命令来运行某个主类。

 

二、类加载器:

 

将.class文件加载到内存中,并生成对应的Class对象

分为三种:

1.BootstrapClassLoader 根类加载器:

(引导类加载器)负责java核心类加载,

如System,String等,在JDK中JRE的lib目录下rt.jar文件中

2.Extension ClassLoader扩展类加载器:

 负责JRE的扩展目录中Jar包的加载

在JDK中JRE的lib目录下ext目录

3.SystemClassLoader  系统类加载器:

负责在JVM启动时加载来自java命令的class文件

以及classpath环境变量所指定的jar包和类路径

 

三、反射 

1、原理理解:

能够知道任意一个类的所有属性和方法,且能调用它的任意一个方法和属性,

这种动态获取的信息以及动态调用对象的方法的功能称为java语音的反射机制。

 

要解剖一个类,首先要获取到类的每一个字节码文件对应的Class类型的对象,

其中用的是Class类中的方法:

 

成员变量 Field

构造方法 Constructor

成员方法  Method

 

2、获取class文件对象的方式:

三种方式:

1.

Person  p  =  new Person();

Class  c1  =  p.getClass();

 

2.

Class  c2  =  Person.class; 

 

3.

Class  c3  =  Class.forName(“myReflect.Person”);

PS:

c1  ==  c2   true

c2  ==  c3   true

1和2都运用于日常(2较方便),3常用于项目开发,

3中的全路径通常通过配置文件中存储的路径,因为容易出错。

 

 

 

    3、Constructor

    获取构造方法:

 

       1)得到这个类的所有构造方法:如得到上面示例中Person类的所有构造方法

            Constructor[] cons = Class.forName(“myReflect.Person”).getConstructors();

      2)获取某一个构造方法:

           Constructor con=Person.class.getConstructor(String.class,int.class);

括号中是参数的字节码文件对象。

 

4、Field

获取类中一个成员变量

 

       FieldgetField(String s);//只能获取公有和父类中公有

     FieldgetDeclaredField(String s);//获取该类中任意成员变量,包括私有

     setAccessible(ture);

     //如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。

  set(Objectobj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。

     Object get(Objectobj);//返回指定对象上Field表示的字段的值。

 

5、Method

 

调用某个对象身上的方法,要先得到方法,再针对某个对象调用。

       Method[] getMethods();//只获取公共和父类中的方法。

        Method[] getDeclaredMethods();//获取本类中包含私有。

        Method  getMethod("方法名",参数.class(如果是空参可以写null));

        Object invoke(Objectobj ,参数);//调用方法

       如果方法是静态,invoke方法中的对象参数可以为null。

示例1:

import java.lang.reflect.Constructor;  
import java.lang.reflect.Field;  
  
public class ReflectField {  
    public static void main(String[] args) {  
        Class clazz = Human.class;// 获取字节码文件对象  
  
        // 获取所有的成员变量  
        // Field[] fields = c.getFields();  
        Field[] fields = clazz.getDeclaredFields();  
        for (Field field : fields) {  
            System.out.println(field);  
            /*输出:  
             * private java.lang.String Human.name  
             * private int Human.age 
             * private java.lang.String Human.address 
             */  
        }  
  
        // 获取单个的成员变量并赋值  
        try {  
            // 通过带参构造方法创建对象  
            Constructor con = clazz.getConstructor(String.class, int.class,  
                    String.class);// 这个是公共构造方法  
            Object obj = con.newInstance("天下第一", 22, "中国·武汉");  
  
            // 获取address并对其赋值  
            // Field addressField = clazz.getField("address");//NoSuchFieldException  
            Field addressField = clazz.getDeclaredField("address");  
            // public void set(Object obj,Object value)  
            // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。  
            addressField.setAccessible(true);// 因为IllegalAccessException,所有要暴力访问  
            addressField.set(obj, "武汉"); // 给obj对象的addressField字段设置值为"武汉"  
  
            // 获取name并对其赋值  
            Field nameField = clazz.getDeclaredField("name");  
            nameField.setAccessible(true);// 因为IllegalAccessException,所有要暴力访问  
            nameField.set(obj, "night");  
  
            // 获取age并对其赋值  
            Field ageField = clazz.getDeclaredField("age");  
            ageField.setAccessible(true);  
            ageField.set(obj, 22);  
  
            ((Human) obj).show();// :22——武汉 
  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
}  
class Human {  
    private String name;  
    private int age = 0;  
    private String address = "未填写";  
  
    private Human(String name) {  
        this.name = name;  
    }  
  
    public Human(String name, int age, String address) {  
        this.name = name;  
        this.age = age;  
        this.address = address;  
    }  
  
    public void show() {  
        System.out.println(name + ":" + age + "——" + address);  
    }  
}  

四、正则表达式

正则即是正确的规则。

正则表达式通过一些特殊的符号来操作字符串数据,可以简化书写,不过定义太多也不便于阅读。

 

字符
x 字符 x
\\ 反斜线字符
\0n 带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh 带有十六进制值 0x 的字符 hh
\uhhhh 带有十六进制值 0x 的字符 hhhh
\t 制表符 ('\u0009')
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')
\e 转义符 ('\u001B')
\cx 对应于 x 的控制符
 
字符类
[abc] ab 或 c(简单类)
[^abc] 任何字符,除了 ab 或c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a 到 d 或 m 到 p[a-dm-p](并集)
[a-z&&[def]] de 或 f(交集)
[a-z&&[^bc]] a 到 z,除了 b 和 c[ad-z](减去)
[a-z&&[^m-p]] a 到 z,而非 m 到 p[a-lq-z](减去)
 
预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
 
POSIX 字符类(仅 US-ASCII)
\p{Lower} 小写字母字符:[a-z]
\p{Upper} 大写字母字符:[A-Z]
\p{ASCII} 所有 ASCII:[\x00-\x7F]
\p{Alpha} 字母字符:[\p{Lower}\p{Upper}]
\p{Digit} 十进制数字:[0-9]
\p{Alnum} 字母数字字符:[\p{Alpha}\p{Digit}]
\p{Punct} 标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

 

五、正则表达式的常见操作:

 

1,匹配:其实用的就是String类中的matches方法。 
String reg = “[1-9][0-9]{4,14}”; 
boolean b = qq.matches(reg);//将正则和字符串关联对字符串进行匹配。 
2,切割:其实用的就是String类中的split方法。 
3,替换:其实用的就是String类中的replaceAll(); 
4,获取: 
1),先要将正则表达式编译成正则对象。使用的是Pattern中静态方法 compile(regex); 
2),通过Pattern对象获取Matcher对象。 
Pattern用于描述正则表达式,可以对正则表达式进行解析。 
而将规则操作字符串,需要从新封装到匹配器对象Matcher中。 
然后使用Matcher对象的方法来操作字符串。 
如何获取匹配器对象呢? 
通过Pattern对象中的matcher方法。该方法可以正则规则和字符串想关联。并返回匹配器对象。 
3),使用Matcher对象中的方法即可对字符串进行各种正则操作。

5、组和捕获

       捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组:

                    1     ((A)(B(C)))

                    2     \A

                    3     (B(C))

                    4     (C)

       组零始终代表整个表达式。在替换中常用$匹配组的内容。

示例:
import java.util.regex.*;  

public class Regex    
{  
    public static void sop(Object obj)  
    {  
        System.out.println(obj);  
    }  
    public static void main(String[] args)   
    {  
        functionDemo_1();  
        sop("---------------------------");  
        functionDemo_2();  
        sop("---------------------------");  
        functionDemo_3();  
        sop("---------------------------");  
        functionDemo_4();  
        sop("---------------------------");  
        functionDemo_5();  
        sop("---------------------------");  
        functionDemo_6();  
        sop("---------------------------");  
    }  
  
    public static void functionDemo_1()  
    {  
        //匹配手机号码  
        String tel = "15072472927";  
        String regex = "1[358]\\d{9}";  
  
        Boolean b = tel.matches(regex);  
        sop(tel+":"+b);  
    }  
    public static void functionDemo_2()  
    {  
        //演示切割   
        String tel = "zhangsan   lisi             wangwu";  
        String[] gex = tel.split("\\s+");  
  
        for(String str : gex)  
        {  
            sop(str);  
        }  
    }  
    public static void functionDemo_3()  
    {  
        //演示切割   
        //(.)表示一组,\\1+表示与第1组相同的出现1次以上  
        String tel = "zhangsanttttttlisimmmmmmmmmmmwangwu";  
        String[] gex = tel.split("(.)\\1+");  
  
        for(String str : gex)  
        {  
            sop(str);  
        }  
          
    }  
    /* 
     * 演示替换 
     */  
    public static void functionDemo_4()  
    {  
        //$表示前一个参数的第一组  
        String tel = "zhangsanttttttlisimmmmmmmmmmmwangwu";  
        String gex = tel.replaceAll("(.)\\1+","$1");  
  
            sop(gex);  
          
          
    }  
    public static void functionDemo_5()  
    {  
           
        String tel = "15072472927";  
        tel = tel.replaceAll("(\\d{3})(\\d{4})(\\d{4})","$1****$3");  
  
            sop(tel);  
          
          
    }  
     /* 
     * 演示获取 
     * 将正则规则进行对象的封装。 
     * Pattern p = Pattern.compile("a*b"); 
     * 通过正则对象的matcher方法字符串相关联。获取要对字符串操作的匹配器对象Matcher。 
     * boolean b = m.matches(); 
     */  
    public static void functionDemo_6()  
    {  
         //打印三个字符的单词  
         // \\b表示单词边界  
        String tel = "da jia hao,ming tian bu fang jia";  
          
        //1. 将正则封装成对象  
        String regex = "\\b[a-z]{3}\\b";  
        Pattern p = Pattern.compile(regex);  
          
        //2. 通过正则对象获取匹配器对象  
        Matcher m = p.matcher(tel);  
  
        //使用Matcher对象的方法对字符串进行操作。  
        //既然要获取三个字母组成的单词。  
        //查找:find();  
        while (m.find())  
        {  
            sop(m.group());//获取匹配的子序列  
            sop(m.start()+":"+m.end());//字符在字符串中的索引位置  
        }  
          
          
    }  
}
程序运行结果为:
 
 
*另一个示例:网络爬虫
/** 
 * @author LinP 
 *  网络爬虫 
 * 网页爬虫:其实就是一个程序用于在互联网中获取符合指定规则的数据。 
 * 爬取需要获取的信息。 
 */  
public class RegexDemo {  
  
    /** 
     * @param args 
     * @throws IOException  
     */  
    public static void main(String[] args) throws IOException {  
        // TODO 自动生成的方法存根  
        //getMailAddress();  
        getMailAddressByWeb();  
    }  
      
    private static void getMailAddressByWeb() throws IOException {  
        // TODO 自动生成的方法存根  
        URL url = new URL("http://bbs.itheima.com/thread-200600-1-1.html");  
          
        BufferedReader bufr = new BufferedReader(new InputStreamReader  
                (url.openStream()));  
        Pattern p = Pattern.compile("\\w+(\\.\\w+)+");  
          
        String line = null;  
        while((line = bufr.readLine())!=null){  
            Matcher m = p.matcher(line);  
            while(m.find()){  
  
                System.out.println(m.group());  
            }  
        }  
  
    }  
  
    private static void getMailAddress() throws IOException {  
        //1. 读取源文件。  
        BufferedReader bufr = new BufferedReader(new FileReader  
                ("C:/Users/LinP/Desktop/gaoxin/3-反射/3-反射.html"));  
          
        //2. 对读取的数据进行规则的匹配。从中获取符合规则的数据。  
        Pattern p = Pattern.compile("\\b\\.[a-zA-Z]{6}\\b");  
          
        ArrayList<String> list = new ArrayList<String>();  
          
        String line = null;  
        while((line = bufr.readLine())!=null){  
            Matcher m = p.matcher(line);  
            while(m.find()){  
                System.out.println(m.group());  
            }  
        }         
    }  
}  
程序运行结果为:

 

posted @ 2015-10-06 23:29  yuer629  阅读(306)  评论(0编辑  收藏  举报