黑马程序员之反射与正则

来源:互联网 发布:stm32f 输入端口写法 编辑:程序博客网 时间:2024/06/05 13:20

JAVA反射机制 


------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------


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


Java反射机制主要提供了以下功能: 

1,在运行时判断任意一个对象所属的类;

2,在运行时构造任意一个类的对象;

3,在运行时判断任意一个类所具有的成员变量和方法;

4,在运行时调用任意一个对象的方法;生成动态代理。 



Class类

反射的基石


如何得到各个字节码对应的实例对象(Class类型)


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


反射的概念

反射就是把java类中的各种成分映射成相应的java类


一个类中的每个成员都可以用想要的反射API类的一个实例对象来表示没通过调用
Class类的方法可以得到这些实例对象。
得到这些实例对象后有什么用呢,怎么用,这正是学习和引用反射的要点



比较字节码是否相同是尽量不要用equals,要用==

常用的方法:

String getName() 
          以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 

Package getPackage() 
          获取此类的包。 

Class<?>[] getInterfaces() //返回的是一个Class类型的数组
          确定此对象所表示的类或接口实现的接口。 



构造方法的反射

Constructor<T> getConstructor(Class<?>... parameterTypes) 
          返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 


Constructor<?>[] getConstructors() //返回的是一个Constructor类型的数组
          返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 


newInstance() 
          创建此 Class 对象所表示的类的一个新实例。 相当于new一个对象,返回的是对象是未知类型,都需要强制转换


Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
例子:Constructor[] Constructor =
Class.forName("java.lang.String").getConstructors();


得到某个类的一个构造方法:
例子:Constructor Constructor =
Class.forName("java.lang.String").getConstructor(StringBuffer.Class);//放入不一样的参数类,就获取不一样的构造方法
//获得方法时要用到类型


创建实例对象:

通常方法:String str = new String(new StringBuffer("abc"));
方式方法:String str = (String)constructor.newInstance(new StringBuffer("abc")); //用到constructor中的newInstance方法
//调用获得的方法时要用到上面相同类型的实例对象


Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用构造方法创建实例对象
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象

程序例子如下:
import java.lang.reflect.*;public class constructorDemo {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubString str = "abc";//new String(new StringBuffer("abc"));Constructor con =String.class.getConstructor(StringBuffer.class);//注意class什么时候需要大写,什么时候需要小写String str2 = (String)con.newInstance(new StringBuffer("abc"));//需要强制转换System.out.println(str2.charAt(1));//注意是str2点.不是逗号,}}




成员变量的反射

Field类代表某个类中的一个成员变量

Field getField(String name) 
          返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 


Field[] getFields() //返回的是一个Field类型的数组
          返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 

程序实例如下:

import java.text.*;public class ReflectPoint {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubrePoint rp = new rePoint(3,5);Field fieldY =rp.getClass().getField("y");//fieldY的值是多少?5.错。fieldY不是对象身上的变量,而是类上的,要用它去取某个对象上对应的值System.out.println(fieldY.get(rp));Field fieldX =rp.getClass().getDeclaredField("x");//因为x是私有的,不能用getField,要不会出错fieldX.setAccessible(true);//也需要加上这个方法,表示可以访问,可以说是暴力访问System.out.println(fieldX.get(rp));}}class rePoint{private int x;public int y;public rePoint(int x, int y){this.x=x;this.y=y;}}


成员方法的方式:

Method类代表某一个成员方法

Method[] getMethods() //返回的是一个Method类型的数组
          返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口
(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 

Method getMethod(String name, Class<?>... parameterTypes) 
          返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 

得到类中的某一个方法:
例子:Method charAt = 
Class.forName("java.lang.String").getMethod("charAt",int class);

调用方法:

通常方法:System.ou.println(str.charAt(1));
反射方法: System.ou.println(charAt.invoke(str,1));
如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法



程序实例如下:

import java.lang.reflect.*;public class MethodDemo {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubString str = "hfwhgkhg";//调用str中的charAt方法Method method = String.class.getMethod("charAt", int.class);System.out.println(method.invoke(str, 1));}}

学习中的题目例子:

import java.lang.reflect.*;/* *通过反射来调用一个函数中的main方法 * */public class startMainDemo {public static void main(String[] args) throws Exception {// TODO Auto-generated method stub//不用反射的犯法格式//themain.main(new String[]{"423","4242","424"});Method method=themain.class.getMethod("main", String[].class);//记得main要用""//用null表示调用的是静态函数,把数组对象转换成Object对象是因为当数组带入时会被打开成三个参数//或者打包成new Object(new String[]{"423","4242","424"}),当被解开时,就还是一个数组参数带入method.invoke(null, (Object)new String[]{"423","4242","424"});}}class themain{public static void main(String[] args){for(String arg: args){System.out.println(arg);}}}






数组的反射



具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象


代表数组的Class实习对象的getSuperClass()方法返回的父类为Object类对应的Class


基本类型的一维数组可以被当作Object类型使用,不能当作Object类型使用
非基本类型的一维数组,既可以当作Object类型使用,有可以当作Object[]类型使用


Arrays.asList()方法处理int[]和String时的差异:
如果是int[],则把数组的所以元素打包变成一个对象,存入集合
如果是String[],这把数组中的每个元素逐一存入集合


Array工具类用于完成对数组的反射操作//在reflect包中
Array.getLength获取长度


程序如下:
import java.lang.reflect.Array;public class arrayDemo {public static void main(String[] args) {// TODO Auto-generated method stubint[] arr= {465,46,48,346,489,9};printObjcct(arr);String[] str = {"fd","fs","fs","ffs"};printObjcct(str);String str1="hohweohowvh";printObjcct(str1);}private static void printObjcct(Object obj) {// TODO Auto-generated method stubClass clazz = obj.getClass();if(clazz.isArray()){int len =Array.getLength(obj);for(int x=0;x<len;x++){System.out.println(Array.get(obj, x));}}else{System.out.println(obj);}}}



例子:通过配置文件加反射方式创建ArrayList和HashSet的实例对象


import java.io.*;import java.util.*;;public class reflectArrayDemo {public static void main(String[] args) throws  Exception {// TODO Auto-generated method stubInputStream is = new FileInputStream("e:\\luanlai\\1.txt");//Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。//属性列表中每个键及其对应值都是一个字符串Properties p = new Properties();p.load(is);is.close();//通过Properties中的键值关系来获取值,该值就是1.txt文件中设置的键值关系的值String classname = p.getProperty("thename2");//创建一个集合对象Collection coll = (Collection)Class.forName(classname).newInstance();coll.add("haha1");coll.add("haha2");coll.add("haha3");coll.add("haha1");System.out.println(coll);
}



正则表达式





正则表达式:符合一定规则的表达式
作用:用于专门操作字符串。
特点:用于一些特定的符号来表示一些代码操作,这样就简化了书写
所以学习正则表达式,就是在学习一些特殊符号的使用
好处:可以简化对字符串的复杂操作

弊端:符号定义越多,正则越长,阅读性越差

具体操作方法
1,匹配:String  matches(String regex),用规则匹配整个字符串,只要有一次不符合规则,就匹配结束,返回false


2, 切割: String Split(String regex);


3, 替换: String  replaceAll(String regex, String replacement)


常见规则


字符类 
[abc] a、b 或 c(简单类) 
[^abc] 任何字符,除了 a、b 或 c(否定) 
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围) 
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集) 
[a-z&&[def]] d、e 或 f(交集) 
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去) 
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去) 




Greedy 数量词 
X? X,一次或一次也没有 
X* X,零次或多次 
X+ X,一次或多次 
X{n} X,恰好 n 次 
X{n,} X,至少 n 次 
X{n,m} X,至少 n 次,但是不超过 m 次 




匹配


public class RegexDemo {public static void main(String[] args) {// TODO Auto-generated method stub//Demo();checkTel();}public static void Demo(){String str = "b4";//表示第一位出现的字符必须是abc中的一个,第2为出现的必须是d,而且只能有两个字符串String regex = "[abc][1-9]";String regex1 = "[^bcd]";//第一个字符只要不是bcd即可boolean b = str.matches(regex);System.out.println(b);}/*匹配手机号码手机号码端只有13xxx   15xxx  18xxx*/public static void checkTel(){String str = "13566665555";String telReg ="1[358]\\d{9}";boolean b = str.matches(telReg);System.out.println(b);}}




切割 


public class splitDemo {public static void main(String[] args) {//点在正则表达式中表示是任意字符,但是需要切割的是点,不是任意字符,所以用\.表示,//但是\具有解析的作用,所以\.解析后还是.任意字符,所需要\\.,用第一个\来解析\,所以变成\.method("zhangsan.lisi.wangwu","\\.");//用第一个\解析第二个\,变成\,然后再解析一个\,所以变成\\method("c:\\abc\\a.txt","\\\\");//按照叠词进行切割:为了可以让规则的结果被重用,可以将规则封成一个组,用()完成//组的出现都有编号,从1开始,想要使用已有的组,可以偷挪\n(n就是组的编号)的形式来获取method("ewdddkjhfffhissssfe","(.)\\1+");}public static void method(String str,String reg){String[] arr=str.split(reg);for(String s : arr){System.out.println(s);}}}





替换


public class replaceAllDemo {public static void main(String[] args) {String str="fwefwe1412313gw456446ww13216543greg313";method(str,"\\d+","#");//将字符串中的数组替换成#String str1="ffsfccccfhthhhhhhtttgfdgfppoeefew";method(str1,"(.)\\1+","&");//将重复出现的字符替换成&String str2="abcdefccccabcdefhhhhhhtttgfdgfppoeefew";method(str2,"(.)\\1+","$1");//将重叠的字符替换成单个字母;如zzzz-->z}public static void method(String str,String reg,String newStr){str=str.replaceAll(reg, newStr);System.out.println(str);}}




正则表达式的第四个功能


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


import java.util.regex.*;public class getDemo {public static void main(String[] args) {// TODO Auto-generated method stubString str = "zhe shi zui hou yi tian de nei rong le ,jia you !";String reg = "\\b[a-z]\\b";////将规则封装成对象Pattern p = Pattern.compile(reg);//然正则对象和要作用的字符串相关联,获取匹配器对象Matcher m =p.matcher(str); while(m.find()){System.out.println(m.group());//group方法必须先查找,才能输出结果,用于获取匹配后的结果}}}



实例如下:

需求:
对邮件地址进行校验

public class checkMail {public static void main(String[] args) {// TODO Auto-generated method stubString mail="faf3fwew2_fffsffwe@sine.com";String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";System.out.println(mail.matches(regex));}}/*192.68.1.254  102.49.23.13  10.10.10.10  8.109.90.30将IP地址进行地址段顺序排序*/public class IPArrange {public static void main(String[] args) {String ip = "192.68.1.254   102.49.23.13    10.10.10.10  8.109.90.30";ip=ip.replaceAll("(\\d+)", "00$1");ip=ip.replaceAll("0*(\\d{3})", "$1");String[] arr=ip.split(" +");Arrays.sort(arr);for(String s:arr){s=s.replaceAll("0*(\\d+)", "$1");System.out.println(s);}}}





0 0
原创粉丝点击