一、类的加载:
原理理解:
当使用某个类的时候,如果该类还没有被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
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
三种方式:
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] | 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](减去) |
预定义字符类 | |
. | 任何字符(与行结束符可能匹配也可能不匹配) |
\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());
- }
- }
- }
- }