您的位置:首页 > 编程语言 > Java开发

正则表达式,Java反射相关

2015-06-30 22:28 549 查看

十二、正则表达式:

1、作用:

    用于操作字符串的规则。

2、好处:

    可以简化对字符串的复杂操作。

3、弊端:

    符号定义越多,正则表达式越长,阅读性越差。

4、示例:

见RegexDemo.java

<span style="font-family:Microsoft YaHei;font-size:12px;">/*
正则表达式
作用:用于操作字符串的规则
特点:用一些特定的符号来表示一些代码操作,简化书写
学习正则表达式就是学习一些特殊符号的使用
好处:可以简化对字符串的复杂操作

具体操作功能:
1、匹配:
String类中的matches(String regex)方法
用规则匹配整个字符串,只要有一处不符合规则就匹配结束,返回false
2、切割:
String类中的split(String regex)方法
3、替换:
String类中的replaceAll(String regex,String replacement)方法
*/
class RegexDemo{
public static void main(String[] args){
checkQQ();
}

//3、替换-------------------------------------------------------------------------------------------
public static void replaceAllDemo(){
String str = "seven12943907lin13777777777";//将字符串中的数字替换成"#"
String regex = "\\d{5,}";
String newstr = "#";

String str = "zhangsanXXlisiAAwangwu";//将叠词替换成"&"
String regex = "(.)\\1+";
String newstr = "&";

String str = "zhangsanXXlisiAAwangwu";//将重叠字符替换成单个字符
String regex = "(.)\\1+";
String newstr = "$1";//"$1"提取前一规则中的第一个组

str = str.replaceAll(regex,newstr);
System.out.println(str);
}

//2、切割-------------------------------------------------------------------------------------------
/*
切割字符串
*/
public static void splitDemo(){
//String str = "zhangsan   lisi  wangwu";
//String regex = " +";//按照多空格进行切割

//String str = "zhangsan.lisi.wangwu";
//String regex = "\\.";//"."是正则表达式中的特殊符号,"\."是正则表达式中的普通的点

//String str = "zhangsan\\lisi\\wangwu";
//String regex = "\\\\";

//为了可以让规则的结果被重用,将要重用的部分用小括号括起来,封装成一个组
//组的出现都有默认编号,组内的结果可以被重新使用
//从1开始,想要使用已有的组可以通过"\n(n就是组的编号)"的形式来获取
String str = "zhangsanXXlisiAAwangwu";
String regex = "(.)\\1+";//按照叠词切割,"+"表示出现一次或多次

String[] arr = str.split(regex);
for(String s:arr){
System.out.println(s);
}
}

//1、匹配-------------------------------------------------------------------------------------------
/*
匹配手机号
手机号段:13xxx 15xxx 18xxx
*/
public static void checkTel(){
String tel = "";
String regex = "1[358]\\d{9}";
System.out.println(tel.matches(regex));
}
/*
对QQ号码进行校验
要求:5~15位 0不能开头,只能是数字
*/
//方法二:使用正则表达式
public static void checkQQ(){
String qq = "";
String regex = "[1-9][0-9]{4,14}";
boolean flag = qq.matches(regex);
if(flag)
System.out.println("qq:"+qq);
else
System.out.println("格式错位");
}
/*
//方法一:使用了String类中的方法,进行组合完成了需求,但是代码过于复杂
public static void checkQQ(){
String qq = "1642313132";
int len = qq.length();
if(len>=5 && len<=15){
if(!qq.startWith("0")){
try{
long l = Long.parseLong(qq);
System.out.println("qq:"+l);
}
catch(NumberFormatException e){
System.out.println("出现非法字符");
}

//char[] arr = qq.toCharArray();
//boolean flag = true;
//for(int x=0;x<arr.length;x++){
//	if(!(arr[x]>='0' && arr[x]<='9')){
//		flag = false;
//	}
//}
//if(flag){
//	System.out.println("qq:"+qq);
//}else{
//	System.out.println("出现非法字符");
//}
}else{
System.out.println("不能以0开头");
}
}else{
System.out.println("号码5~15位");
}
}
*/
}</span>
<span style="font-family:Microsoft YaHei;font-size:12px;">/*
正则表达式

具体操作功能:
4、获取:
将字符串中符合规则的子串取出

操作步骤:
(1)将正则表达式封装成对象
(2)让正则对象和要操作的字符串相关联
(3)关联后,获取正则匹配引擎
(4)通过引擎对符合规则的子串进行操作,比如取出

注意:
同一个匹配器,使用同一个指针

*/
import java.util.regex.*;
class RegexDemo{
public static void main(String[] args){
getDemo();
}

public static void getDemo(){
String str = "baby now take me into your loving arms";
String regex = "\\b[a-zA-Z]{3}\\b";//取出三个字母组成的单词

//将规则封装成对象
Pattern p = Pattern.compile(regex);

//让正则对象和要作用的字符串相关联,获取匹配器子串
Matcher m = p.matcher(str);

//其实String类中的matches方法,就是用Pattern和Matcher对象来完成的
//只是被String的方法封装后使用比较简单,但是功能单一
//System.out.println(m.matches());

//find方法将规则作用到字符串上,并进行符合子串的查找,返回boolean
//System.out.println(m.find());
//group方法用于获取匹配后的结果
//System.out.println(m.group());
while(m.find()){
System.out.println(m.group());
System.out.println(m.start()+"..."+m.end());//获取子串的起始位置,含头不含尾
}
}
}</span>


十三、Java反射:

1、定义:

    Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class
    对象是由字节码创建的

2、获取字节码对应的实例对象的方法:

    (1)类名.class,例如:System.class
    (2)对象.getClass(),例如:new Date().getClass();
    (3)Class.forName("类名"),例如:Class.forName("java.util.Date");

3、九个预定义的Class实例对象:

    八个基本数据类型加上void
    只要是源程序中出现的类型,都有各自的Class实例对象,例如:void、int[]...

4、反射:

    反射就是把Java类中的各种成分映射成相应的Java类。
    一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。
    (1)Constructor类:代表某个类中的一个构造方法
        a、得到某个类所有的构造方法:Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
        b、得到一个构造方法:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);//具体哪一个构造方法,区别在于参数不同
        c、创建实例对象:
            通常方式:String
str = new String(new StringBuffer("abc"));
            反射方式:String
str = (String)Class.forName("java.lang.String").getConstructor(StringBuffer.class).newInstance(new StringBuffer("abc"));
       d、使用不带参数的构造方法,可以直接使用:
           Class.newInstance();
            该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象,该方法用到了缓存机制
    (2)Field类:成员变量
        a、获取公有成员:Field fY = pt.getClass().getField("y");
            System.out.println(fY.get(pt));
        b、获取私有成员:Filed fX = pt.getClass().getDeclaredField("x");
            fX.setAccessible(true);//暴力反射,否则不可用
            System.out.println(fX.get(pt));
        c、Field[] fields = obj.getClass().getFields();
            for(Field
f : fields){
             
      if(field.getType()==String.class){
             
             f.set(obj,(String)f.get(obj).replace('b','a'));
             
      }
            }
    (3)Method类:代表某个类中的成员方法
        a、得到类中的某一个方法:Method charAt = Class.forName(java.util.String).getMethod("charAt",int.class);
        b、调用方式:
            通常方式:System.out.println(str.charAt(1));
            反射方式:System.out.println(charAt.invoke(str,1));
            当invoke的第一个参数是"null"时,说明这是一个静态方法,静态方法的调用不需要对象
    (4)Array类:数组的反射
        a、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
        b、代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class
        c、基本类型的一维数组可以看作是Object的子类对象使用,但不可以当作Object[]类型使用;
 
        非基本类型的一维数组,可以当作Object类型使用,也可以当作Object[]类型使用

5、框架等具体示例,详见ReflectDemo.java

<span style="font-family:Microsoft YaHei;font-size:12px;">/*
反射(Reflect)示例

*/
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

class ReflectDemo{
public static void main(String[] args) throws Exception{
/*
Constructor构造方法类
示例参数为StringBuffer
*/
Constructor cons = String.class.getConstructor(StringBuffer.class);//1、获取方法时指定类型
//编译器,只看代码的编译,不管运行,所以需要指定类型
String str1 = (String)cons.newInstance(new StringBuffer("abc"));//2、调用方法时需要传入上面同样类型的对象
System.out.println(str1.charAt(2));

/*
Field成员变量类
*/
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fY = pt1.getClass().getField("y");
//fY不是对象身上的变量,而是类(字节码文件)上的,要用它去取某个对象上的值
System.out.println(fY.get(pt1));
Field fX = pt1.getClass().getDeclaredField("x");//获取私有变量
fX.setAccessible(true);//暴力反射,否则不可用
System.out.println(fX.get(pt1));

System.out.println(pt1.toString());
changeStringValue(pt1);
System.out.println(pt1.toString());

/*
Method方法类
*/
Method methodCharAt = Class.forName("java.lang.String").getMethod("charAt",int.class);//"..."可变参数,有几个参数写几个
System.out.println(methodCharAt.invoke(str1,1));//获取字节码文件中的方法,包装成一个对象,再调用该对象中的方法invoke;第一个参数是作用的对象,后面是参数列表

//调用main方法
//普通方式
//TestArguments.main(new String[]{"seven","da","lin"});
//反射方式
String startingClassName = args[0];//运行时需要传入一个参数"TestArguments",这是要启动的类名,开发过程中我们一般不知道,直接从配置文件中加载
Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
mainMethod.invoke(null,new Object[]{new String[]{"seven","da","lin"}});//如果不用Object封装一下,java会将发来的String数组解包一次,认为是三个String参数;封装之后,解包一次,就是一个String数组
//mainMethod.invoke(null,(Object)new String[]{"seven","da","lin"});//这样亦可

/*
Array数组类
*/
int[] a1 = new int[]{1,2,3};
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[]{"a","b","c"};
System.out.println(a1.getClass().getName() == a2.getClass().getName());//true
System.out.println(a1.getClass().getName() == a3.getClass().getName());//false
System.out.println(a1.getClass().getName() == a4.getClass().getName());//false
System.out.println(a1.getClass().getName());//获取类名,"[I"整型数组
System.out.println(a1.getClass().getSuperclass().getName());//结果"java.lang.Object",获取父类名称
System.out.println(a4.getClass().getSuperclass().getName());//结果"java.lang.Object"

//数组类型是Object的子类,把数组看成Object对象,Object类型数组可以存放Object对象
Object obj1 = a1;//可以,a1是一个数组对象
Object obj2 = a4;//可以,a4是一个数组对象
//Object[] obj3 = a1;//不可以,obj3是一个对象数组,a1只是一个数组对象
Object[] obj4 = a3;//可以,a3可以看成一个数组,其中存的是数组对象
Object[] obj5 = a4;//可以,String本就是对象,String[]就是一个对象数组

System.out.println(a1);//"[I@______"下划线为hashCode值
System.out.println(a4);//"[Ljava.lang.String;@______"
System.out.println(Arrays.asList(a1));//"[[I@______]",a1是一个int[],整体是一个对象
System.out.println(Arrays.asList(a4));//"[a,b,c]",a4是一个String[],其中的每个String可以看成一个对象

//使用反射的方式打印数组
printObject(a1);
printObject(a4);//"a\n b\n c\n"
printObject("xyz");//"xyz"

Object[] a = new Object[]{"seven",1};//Object数组中可以存放各种类型
System.out.println(a[0].getClass().getName());
System.out.println(a[1].getClass().getName());
}
/*
Array练习:
*/
private static void printObject(Object obj){
Class c = obj.getClass();
if(c.isArray()){
int len = Array.getLength(obj);
for(int i=0;i<len;i++){
System.out.println(Array.get(obj,i));//obj[i]
}
}else{
System.out.println(obj);
}
}
/*
Field练习:
将任意一个对象中的所有String类型的成员对应的字符串内容中的“b”改成“a”
*/
private static void changeStringValue(Object obj) throws Exception{
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
//if(field.getType().equals(String.class)){
if(field.getType()==String.class){//字节码使用"=="比较
String oldstr = (String)field.get(obj);
String newstr = oldstr.replace('b','a');
field.set(obj,newstr);
}
}
}
}

public class ReflectPoint{
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "soccer";
public ReflectPoint(int x,int y){
this.x = x;
this.y = y;
}
public String toString(){
return str1+","+str2+","+str3;
}
}

public class TestArguments{
public static void main(String[] args){
for(String arr : args){
System.out.println(arr);
}
}
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: