1 反射机制
Person类
package cn.itcast.bean;
public class Person {
private int age;
private String name;
public Person() {
super();
// TODO Auto-generated constructor stub
System.out.println("person run");
}
public Person(String name,int age) {
super();
this.age=age;
this.name=name;
System.out.println("person param run..."+this.name+":"+this.age);
}
public void show() {
System.out.println(name+"...show run..."+age);
}
private void method() {
System.out.println("method run");
}
public void paramMethod(String str,int num) {
System.out.println("paramMethod run......"+str+":"+num);
}
public static void staticMethod() {
System.out.println("static method run......");
}
}
package cn.itcast.reflect.demo;
import cn.itcast.bean.Person;
/*
* Java反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法
* 对于任意一个对象,都能够调用它的任意一个方法和属性
* 这种动态获取信息以及动态调用对象的方法的功能称为java预言的反射机制
*
* 动态获取类中信息,就是java反射
* 可以理解为对类的解剖
*
* 要想要对字节码文件进行解剖,必须要有字节码文件对象
* 如何获取字节码文件对象呢?
*
* */
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
// getClassObject_1();
// getClassObject_2();
getClassObject_3();
}
private static void getClassObject_3() throws ClassNotFoundException {
// TODO Auto-generated method stub
/*
*3、 只要通过给定的类的字符串名称就可以获取该类,更为扩展
* 是用Class类中的方法完成,该方法就是forName
*
* */
String className="cn.itcast.reflect.demo.Person";//它会到默认路径下找(bin目录或者path),所以这个路径名要写全
Class clazz=Class.forName(className);
System.out.println(clazz);
}
private static void getClassObject_2() {
// TODO Auto-generated method stub
/*
* 2、任何数据类型都具备一个静态的属性,class来获取其对应的class对象
* 相对简单,但是还是要明确用到类中的静态成员。还是不够扩展
*
*
* */
Class clazz=Person.class;
Class clazz1=Person.class;
System.out.println(clazz==clazz1);
}
/*
* 获取字节码对象的方式:
* 1、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);
}
}
package cn.itcast.reflect.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
// creatNewObject();
creatNewObject_2();
}
private static void creatNewObject_2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
// cn.itcast.bean.Person p=new cn.itcast.bean.Person("小强",39);
/*
* 当获取指定名称对应类中的所体现的对象时
* 而该对象初始化不使用空参数构造函数该怎么办?
* 既然是通过指定的构造函数进行对象的初始化,
* 所以应该先获取到该构造函数,通过字节码文件对象即可完成
* 该方法是:getConstructor(paramterTypes)
* */
String name="cn.itcast.bean.Person";
//找寻该类名称类文件,并加载进内存,并产生Class对象
Class clazz=Class.forName(name);
//获取到了指定的构造函数对象
Constructor constructor=clazz.getConstructor(String.class,int.class);
//通过该构造器对象的newInstance方法进行对象的初始化
Object obj=constructor.newInstance("小明",38);
}
private static void creatNewObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
// 早期: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();//调用空参构造函数
}
}
package cn.itcast.reflect.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
// getMethodDemo();
// getMethodDemo_2();
getMethodDemo_3();
}
private static void getMethodDemo_3() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
//获取指定函数(有参数),并运行
Class clazz=Class.forName("cn.itcast.bean.Person");
Method method=clazz.getMethod("paramMethod", String.class,int.class);
Object obj=clazz.newInstance();
method.invoke(obj, "小强",89);
}
private static void getMethodDemo_2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
//获取指定函数(函数没有参数),并运行
Class clazz=Class.forName("cn.itcast.bean.Person");
Method method=clazz.getMethod("show", null);//获取空参数函数一般方法
// Object obj=clazz.newInstance();//获取对象,空参数构造函数(对象初始化)
Constructor constructor=clazz.getConstructor(String.class,int.class);
Object obj=constructor.newInstance("小明",39);//获取对象,有参数构造函数(对象初始化)
method.invoke(obj, null);//运行指定函数
}
private static void getMethodDemo() throws ClassNotFoundException {
// TODO Auto-generated method stub
/*
* 获取指定Class中的公共函数
*
* */
Class clazz=Class.forName("cn.itcast.bean.Person");
// Method[]methods=clazz.getMethods();//获取的都是公有的方法(包括父类的方法)
Method[]methods=clazz.getDeclaredMethods();//只获取本类中所有方法,包括私有
for(Method method:methods) {
System.out.println(method);
}
}
}
package cn.itcast.reflect.demo;
import java.lang.reflect.Field;
public class getField {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
getFieldDemo();
}
private static void getFieldDemo() throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
/*
* 获取字节码文件中的字段
* */
Class clazz=Class.forName("cn.itcast.bean.Person");
// Field field=clazz.getField("age");//只能获取公有的
Field field=clazz.getDeclaredField("age");//只获取本类,但包含私有的
/*Object obj=clazz.newInstance();
Object o=field.get(obj);
System.out.println(o);*///不能访问,因为age是私有属性
//但可以通过下面这种方式,将私有字段的范文取消权限检查,暴力访问
field.setAccessible(true);
Object obj=clazz.newInstance();//初始化对象
// field.set(obj, 90);//修改age属性值
Object o=field.get(obj);
System.out.println(o);
System.out.println(field);//结果:private int cn.itcast.bean.Person.age
}
}
2 反射的应用(扩展性极强)
主程序
package cn.itcast.reflect.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
/*
* 电脑运行
*
* */
public class ReflectTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
Mainboard mb=new Mainboard();
mb.run();
//每次添加一个设备都需要修改代码传递一个新创建的对象
// mb.usePCI(new 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();//这一步其实就相当于new 一个p对象
mb.usePCI(p);
}
fis.close();
}
}
Mainboard类
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.close();
p.open();
}
}
}
NetCard类
package cn.itcast.reflect.test;
public class NetCard implements PCI {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("net run");
}
@Override
public void close() {
// TODO Auto-generated method stub
System.out.println("net close");
}
@Override
public void open() {
// TODO Auto-generated method stub
System.out.println("net open");
}
}
SoundCard类
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");
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("sound run");
}
}
接口类
package cn.itcast.reflect.test;
public interface PCI {
public void run();
public void close();
public void open();
}
2 正则表达式
package cn.itcast.regex.demo;
/*
* 正则表达式
*
* 正则表达式用于操作字符串数据
* 通过一些特定的符号来体现的。
* 所以为了掌握正则表达式,必须要学习一些符号
* 虽然简化了,但是阅读性差
*
* */
public class RegexDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String qq="1234567";
// checkQQ(qq);
String regex="[1-9][0-9]{4,14}";//正则表达式
// boolean b=qq.matches(regex);
// System.out.println(qq+":"+b);
String str="aooob";
String reg="ao+b";//o+表示一个或多个o {4}表示4个 {4,}表示4个及以上 {4,8}表示4到8个
boolean b=str.matches(reg);
System.out.println(str+":"+b);
}
/*
* 需求:定义一个功能对QQ号进行校验
* 要求:长度5~15,只能是数字,0不能开头
*
*
* */
private static void checkQQ(String qq) {
// TODO Auto-generated method stub
int len=qq.length();
if(len>=5&&len<=15) {
if(!qq.startsWith("0")) {
try {
long l=Long.parseLong(qq);
System.out.println(l+":正确");
}catch(NumberFormatException e) {
System.out.println(qq+":含有非法字符");
}
}else {
System.out.println(qq+":不能0开头");
}
}else {
System.out.println(qq+":长度错误");
}
}
}
package cn.itcast.regex.demo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 正则表达式对字符串的常见操作:
* 1、匹配
* 其实使用的就是String类中的matches方法
* 2、切割
* 其实使用的就是String类中的split方法
*
* 3、替换
* 其实使用的就是String类中的replaceAll()方法
*
* 4、获取
*
* */
// funcitonDemo_1();//匹配
// funcitonDemo_2();//切割
// funcitonDemo_3();//替换
funcitonDemo_4();//获取
}
private static void funcitonDemo_4() {
// TODO Auto-generated method stub
/*
* 获取
* 将正则规则进行对象的封装
* Pattern p=Pattern.compile("a*b");
*通过正则对象的matcher方法字符串相关联,获取要对字符串操作的匹配器对象matcher
*Matcher m=p.matcher("aaaaab");
*通过Matcher匹配器对象的方法对字符串进行操作
*boolean b=m.matches();
*
*
* */
String str="da jia hao,ming tian bu fang jia";
String regex="\\b[a-z]{3}\\b";//\\b是给中间匹配的对象加边界的
//将正则封装成对象
Pattern p=Pattern.compile(regex);
//通过正则对象获取匹配器对象
Matcher m=p.matcher(str);
//使用Matcher对象的方法对字符串进行操作
//既然要获取三个字母组成的单词
//查找.find();
while(m.find()) {
System.out.println(m.group());//获取匹配的子序列
System.out.println(m.start()+":"+m.end());//获取查找到对象的开始与结束位置
}
}
private static void funcitonDemo_3() {
// TODO Auto-generated method stub
/*String str="zhangsantttttxiaoqiangmmmmmmmzhaoliu";
str=str.replaceAll("(.)\\1+", "#");*/
String str="zhangsantttttxiaoqiangmmmmmmmzhaoliu";
str=str.replaceAll("(.)\\1+", "$1");//用$符号获取前面正则规则匹配后的内容
String tel="15800001111";//
tel=tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");//第一组用匹配的代替,中间四个用*代替,后面那组用匹配的代替
System.out.println(tel);//结果:158****1111
// System.out.println(str);
}
private static void funcitonDemo_2() {
// TODO Auto-generated method stub
/*String str="zhangsan xiaoqiang zhaoliu";
String[]names=str.split(" +");*/
/*String str="zhangsan.xiaoqiang.zhaoliu";
String[]names=str.split("\\.");//\.表示转义成普通字符".",但\在字符串中就表示时是就是普通字符“\”,要想它具有转义符的作用就必须转义,需要被转义下才能
*/
String str="zhangsantttttxiaoqiangmmmmmmmzhaoliu";
String[]names=str.split("(.)\\1+");//(.)将相同的字符串封装成一个组,而我们又不知道这个组中具体是什么,就用.代替,而这个字符不知道出现几次,就用\\1+转义后的代表这个组出现一次或多次
for(String name:names) {
System.out.println(name);
}
}
/*
* 演示匹配
* */
public static void funcitonDemo_1() {
// 匹配手机号码是否正确
String tel="15842563360";
// String regex="1[358][0-9]{9}";//[0-9]可以用"\\d"代替,因为\d表示数字,而在字符串中\表示转义(因此\d就是转义了的d),所以用转义过后的\d
String regex="1[358]\\d{9}";
boolean b=tel.matches(regex);
System.out.println(tel+":"+b);
}
}
package cn.itcast.regex.demo;
import java.util.TreeSet;
public class RegexTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 1、治疗口吃:我我...我我...我我我要...要要要要...要要要要...学学学学学
* 2、对ip地址排序
* 3、对邮件地址校验
*
* */
// test_1();
// test_2();
test_3();
}
//治疗口吃
private static void test_1() {
// TODO Auto-generated method stub
String str="我我...我我...我我我要...要要要要...要要要要...学学学学学";
// 将字符串中的.去掉,用替换
str=str.replaceAll("\\.", "");
// 替换叠词
str=str.replaceAll("(.)\\1+", "$1");
System.out.println(str);
}
/*
* ip地址排序
* 192.168.10.34 127.0.0.1 3.3.3.3 105.70.11.55
*
* */
private static void test_2() {
// TODO Auto-generated method stub
String ip_str="192.168.10.34 127.0.0.1 3.3.3.3 105.70.11.55";
//1、为了让ip可以按照字符串顺序比较,只要让ip的每一段的位数相同
//所以,补零,按照每一位所需做多0进行补充,每一段都加两个0
ip_str=ip_str.replaceAll("(\\d+)","00$1");
System.out.println(ip_str);
//然后每一段保留数字3位
ip_str=ip_str.replaceAll("0*(\\d{3})", "$1");
//1、将ip地址切出
String[]ips=ip_str.split(" +");
TreeSet<String>ts=new TreeSet<String>();
for(String ip:ips) {
// System.out.println(ip);
ts.add(ip);
}
for(String ip:ts) {
System.out.println(ip.replaceAll("0*(\\d+)", "$1"));
}
}
//对邮件地址校验
private static void test_3() {
// TODO Auto-generated method stub
String mail="abc1@sina.com";
String regex="[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]{1,3})+";
boolean b=mail.matches(regex);
System.out.println(mail+":"+b);
}
}
package cn.itcast.regex.demo;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
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 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
List<String>list=getMails();
for(String mail:list) {
System.out.println(mail);
}
}
private static List<String> getMails() throws IOException {
// TODO Auto-generated method stub
// 读取源文件
BufferedReader bufr=new BufferedReader(new FileReader("mail.html"));
// URL url=new URL("http://192.168.1.100:8080/myweb/mail.html");
// BufferedReader bufIn=new BufferedReader(new InputStreamReader(url.openStream()));
// 对读取的数据进行规则的匹配,从中获取符合规则的数据
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()) {
// 将符合规则的数据存储到集合中
list.add(m.group());
}
}
return list;
}
}