DAY26反射,正則運算式

1.1類加載
當程式要使用某個類時,如果該類還未被加載到記憶體中,則系統會通過類的加載,類的連接,類的初始化這三個步驟來對類進行初始化,如果不出現意外情況,VM將會連續完成這三個步驟,所以有時也把這三個步驟統稱為類加載或者類初始化
類的加載:
將class檔案(源檔案)讀取記憶體,并創建對應的Class物件
任何類被使用時,系統都會創建一個java.lang.Class物件
類的連接
- 驗證階段:檢驗被加載的類和相關類(父類/介面)內部結構是否合法
- 準備階段:負責為類中的變數分配記憶體,并設定默認值
- 決議階段:將類的二進制資料中字符(方法)參考改為直接參考
類的初始化:
- 對類變數進行初始化(賦值)
類的初始化步驟
- 假如類還未被加載和連接,則程式先加載并連接該類
- 假如該類的直接父類還未被初始化,則先初始化其直接父類
- 假如類中有初始化陳述句,則系統依次執行這些初始化陳述句
注意:在執行第2個步驟的時候,系統對直接父類的初始化步驟也遵循初始化步驟1-3
類的初始化時機:
-
創建類的實體
-
呼叫類的類方法
-
訪問類或者介面的類變數,或者為該類變數賦值
-
使用反射方式來強制創建某個類或介面對應的java.lang.Class物件
-
初始化某個類的子類
-
直接使用java.exe命令來運行某個主類
1.2類加載器
Java加載類時,都是通過類加載器來進行加載
類加載器的作用:
- 負責將.class檔案加載到記憶體中,并為之生成對應的java.lang.Class物件
- 雖然我們不用過分關心類加載機制,但是了解這個機制我們就能更好的理解程式的運行
JVM的類加載機制
- 全盤負責:就是當一個類加載器負責加載某個Class時,該Class所依賴的和參考的其他Class也將由該類加載器負責載入,除非顯示使用另外一個類加載器來載入
- 父類委托:就是當一個類加載器負責加載某個Class時,先讓父類加載器試圖加載該Class,只有在父類加載器無法加載該類時才嘗試從自己的類路徑中加載該類
- 快取機制:保證所有加載過的Class都會被快取,當程式需要使用某個Class物件時,類加載器先從快取區中搜索該Class,只有當快取區中不存在該Class物件時,系統才會讀取該類對應的二進制資料,并將其轉換成Class物件,存盤到快取區
ClassLoader:是負責加載類的物件
Java運行時具有以下內置類加載器
-
Bootstrap class loader:它是虛擬機的內置類加載器,通常表示為null,并且沒有父null
-
Platform class loader:華臺類加載器可以看到所有平臺類,平臺類包括由平臺類加載器或其祖先定義的Java SE平臺API,其實作類和JDK特定的運行時類
-
System class loader:它也被稱為應用程式類加載器,與平臺類加載器不同,系統類加載器通常用于定義應用程式類路徑,模塊路徑和JDK特定工具上的類

-
類加載器的繼承關系:System的父加載器為Platform,而Platform的父加載器為Bootstrap
ClassLoader中的兩個方法
| 方法 | 說明 |
|---|---|
| static ClassLoader getSystemClassLoader() | 回傳用于委派的系統類加載器 |
| ClassLoader getParent() | 回傳父類加載器進行委派 |
package javaDemo.reflex.Demo1;
/*
ClassLoader中的兩個方法
static ClassLoader getSystemClassLoader()
回傳用于委派的系統類加載器
ClassLoader getParent()
回傳父類加載器進行委派
*/
public class ClassLoaderDemo {
public static void main(String[] args) {
//static ClassLoader getSystemClassLoader()回傳用于委派的系統類加載器
ClassLoader c = ClassLoader.getSystemClassLoader();
System.out.println(c);//AppClassLoader(系統類加載器)
//ClassLoader getParent()回傳父類加載器進行委派
ClassLoader c2 = c.getParent();
System.out.println(c2);//ExtClassLoader
ClassLoader c3 = c2.getParent();
System.out.println(c3);//null
}
}

2.1反射概述

Java反射機制:是指在運行時去獲取一個類的變數和方法資訊,然后通過獲取到的資訊來創建物件,呼叫方法的一種機制,由于這種動態性,可以極大的增強程式的靈活性,程式不用在編譯期就完成確定,在運行期仍然可以擴展
2.2獲取Class類的物件
我們要想通過反射去使用一個類,首先我們要獲取到該類的位元組碼檔案物件,也就是型別為Class型別的物件這里我們提供三種方式獲取Class型別的物件
-
使用類的class屬性來獲取該類對應的Class物件,舉例: Student.class將會回傳Student類對應的Class物件
-
呼叫物件的getClass(方法,回傳該物件所屬類對應的Class物件
-
該方法是Object類中的方法,所有的Java物件都可以呼叫該方法
-
使用Class類中的靜態方法forName(String className),該方法需要傳入字串引數,該字串引數的值是某個類的全路徑,也就是完整包名的路徑
設定一個類:
Student類
package javaDemo.reflex.Demo2;
public class Student {
//成員變數:一個私有,一個默認,一個公共
private String name;
int age;
public String address;
//構造方法,一個私有,一個默認,兩個公共
public Student() {
}
private Student(String name) {
this.name = name;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//成員方法,一個私有,四個公共
private void function(){
System.out.println("function");
}
public void method1(){
System.out.println("method1");
}
public void method2(String s){
System.out.println("method:"+s);
}
public String method3(String s,int i){
return s+","+i;
}
@Override
public String toString() {
return "Student{"+
"name='"+name+'\''+
",age="+age+
",address='"+address+'\''+
'}';
}
}
ReflectDemo
public class ReflectDemo {
public static void main(String[] args) {
//使用類的class屬性來獲取該類對應的Class物件,
Class<Student> c1 = Student.class;//泛型類
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1==c2);//位元組碼檔案物件唯一,所以為true
}
}


三種方法詳情:
package javaDemo.reflex.Demo2;
/*
三種方式獲取Class物件:
1.使用類的class屬性來獲取該類對應的Class物件,舉例: Student.class將會回傳Student類對應的Class物件
2.呼叫物件的getClass(方法,回傳該物件所屬類對應的Class物件
該方法是Object類中的方法,所有的Java物件都可以呼叫該方法
3.使用Class類中的靜態方法forName(String className),該方法需要傳入字串引數,該字串引數的值是某個類的全路徑,也就是完整包名的路徑
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//使用類的class屬性來獲取該類對應的Class物件,(該方法最簡單)
Class<Student> c1 = Student.class;//泛型類
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1==c2);
System.out.println("----------------------");
//呼叫物件的getClass(方法,回傳該物件所屬類對應的Class物件
Student s=new Student();
Class<? extends Student> c3= s.getClass();
System.out.println(c1==c3);//為true,所以方法二也能得到位元組碼檔案物件
System.out.println("----------------------");
//使用Class類中的靜態方法forName(String className)(該方法最靈活)
Class<?> c4 = Class.forName("javaDemo.reflex.Demo2.Student");
System.out.println(c1==c4);//結果也為true,所以方法三也是能得到位元組碼檔案物件
}
}

2.3反射獲取構造方法
Class類中用于獲取構造方法的方法
| 方法 | 說明 |
|---|---|
| Constructor<?>[]getConstructors() | 回傳所有公共構造方法物件的陣列 |
| Constructor<?>[]getDeclaredConstructors() | 回傳所有構造方法物件的陣列 |
| Constructor getConstructor(Class<?>… parameterTypes) | 回傳單個公共構造方法物件 |
| Constructor getDeclaredConstructor(Class<?>…parameterTypes) | 回傳單個構造方法物件 |
Constructor類中用于創建物件的方法
| 方法 | 說明 |
|---|---|
| T newInstance(Object… initargs): | 根據指定的構造方法創建物件 |
package javaDemo.reflex.Demo3;
import java.lang.reflect.Constructor;
/*
反射獲取構造方法并使用
*/
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException{
//獲取Class物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
//construotor<?>[] gatconstruators()
//回傳一個包含 construator物件的陣列,constructoz物件反映了由該class物件表示的類的所有公共建構式
Constructor<?>[] cons = c.getConstructors();
for (Constructor<?> con : cons) {
System.out.println(con);
}
}
}
construotor<?>[] gatconstruators() 回傳一個包含 construator物件的陣列,constructoz物件反映了由該class物件表示的類的所有公共建構式


construator<?>[] getDeclaredconstruoters{) 回傳反映由該 class物件表示的類宣告的所有建構式的 constructoz物件的陣列,
//construator<?>[]getDeclaredconstruoters{)
//回傳反映由該 class物件表示的類宣告的所有建構式的 constructoz物件的陣列,
Constructor<?>[] cons2 = c.getDeclaredConstructors();
for (Constructor<?> con : cons) {
System.out.println(con);
}
System.out.println("------");
for (Constructor<?> con2 : cons2) {
System.out.println(con2);
}
所有的方法都被回傳了

當使用Constructor[] getDeclaredConstructor(Class<?>… parameterTypes)
T newInstance(object…initargs)創建和初始化建構式的宣告英的新實體
//Constructor<T>[] getConstructors(Class<?>... parameterTypes):
// 回傳單個公共構造方法物件
//Constructor<T>[] getDeclaredConstructor(Class<?>... parameterTypes):
// 回傳單個構造方法物件
//引數:你要獲取的構造方法的引數的個數和資料型別對應的位元組碼檔案物件
Constructor<?> con3 = c.getConstructor();
//Constructor提供了一個類的單個建構式的資訊和訪問權限
//T newInstance(object..initargs)
//使用由此constructoz物件表示的建構式,使用指定的初始化引數來創建和初始化建構式的宣告英的新實體,
Object obj = con3.newInstance();
System.out.println(obj);
結果:

代碼完整詳情
package javaDemo.reflex.Demo3;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/*
反射獲取構造方法并使用
*/
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//獲取Class物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
//construotor<?>[] gatconstruators()
//回傳一個包含 construator物件的陣列,constructoz物件反映了由該class物件表示的類的所有公共建構式
Constructor<?>[] cons = c.getConstructors();
//construator<?>[]getDeclaredconstruoters{)
//回傳反映由該 class物件表示的類宣告的所有建構式的 constructoz物件的陣列,
Constructor<?>[] cons2 = c.getDeclaredConstructors();
for (Constructor<?> con : cons) {
System.out.println(con);
}
System.out.println("------");
for (Constructor<?> con2 : cons2) {
System.out.println(con2);
}
//Constructor<T>[] getConstructors(Class<?>... parameterTypes):
// 回傳單個公共構造方法物件
//Constructor<T>[] getDeclaredConstructor(Class<?>... parameterTypes):
// 回傳單個構造方法物件
//引數:你要獲取的構造方法的引數的個數和資料型別對應的位元組碼檔案物件
System.out.println("---------");
Constructor<?> con3 = c.getConstructor();
//Constructor提供了一個類的單個建構式的資訊和訪問權限
//T newInstance(object..initargs)
//使用由此constructoz物件表示的建構式,使用指定的初始化引數來創建和初始化建構式的宣告英的新實體,
Object obj = con3.newInstance();
System.out.println(obj);
}
}

2.4 反射獲取構造方法并使用練習
練習1:通過反射實作如下操作
- Student s=new Student(“林青霞”,30,“西安”);
- System.out.println(s);
- 基本資料型別也可以通過.class得到對的class型別
package javaDemo.reflex.Exerice01;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/*
練習1:通過反射實作如下操作
Student s=new Student("林青霞",30,"西安");
System.out.println(s);
*/
public class ReflectDEMO {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//獲取class物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
// public Student(String name, int age, String address)
//基本資料型別也可以通過.class得到對的class型別
Constructor<?> con = c.getConstructor(String.class, int.class, String.class);
//T newInstance(Object... initargs)
Object o = con.newInstance("林青霞", 30, "西安");
System.out.println(o);
}
}

練習2:通過反射實作如下操作
-
Student s = new Student(“林青霞”);
-
System.out.println(s);
-
public void setAccessible (boolean flag):值為true,取消訪問檢查(俗稱暴力反射)
package javaDemo.reflex.Exerice02;
import java.lang.reflect.Constructor;
/* 練習2:通過反射實作如下操作
Student s = new Student("林青霞");
System.out.println(s);
*/
public class ReflectDemo {
public static void main(String[] args)throws Exception {
//獲取class物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
//private Student(String name)
//Constructor<T>[] getDeclaredConstructor(Class<?>... parameterTypes):
Constructor<?> con = c.getDeclaredConstructor(String.class);
Object obj = con.newInstance("林青霞");
System.out.println(obj);
}
}
按上述代碼會出現如下情況:
原因:私有屬性修飾的不能創建物件

解決:增加一行代碼:
//暴力反射
//方法:public void setAccessible (boolean flag):值為true,取消訪問檢查
con.setAccessible(true);

結果:

2.5反射獲取成員變數并使用
Class類中用于獲取成員變數的方法
- Field[] getFields0:回傳所有公共成員變數物件的陣列
- Field[] getDeclaredFields0:回傳所有成員變數物件的陣列
- Field getField(String name):回傳單個公共成員變數物件
- Field getDeclaredField(String name):回傳單個成員變數物件
Field類中用于給成員變數賦值的方法
- void set(Object obj, Objectvalue):給obj物件的成員變數賦值為value
package javaDemo.reflex.reflexDemo4;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
反射獲取成員變數并使用
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception{
//獲取Class物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
Field[ ] getFields ()回傳一個包含 Field物件的陣列, Field物件反映由該cLass物件表示的類或介面的所有可訪問的公共欄位
// Field[] getDecLaredFields ()回傳一個Field物件的陣列,反映了由該―cLass物件表示的類或介面宣告的所有欄位
// Field[] fields = c.getFields();
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("----------");
//Field getField (String name)回傳一個 Field物件,該物件反映由該CLass物件表示的類或介面的指定公共成員欄位
// Field getDeclaredField (String name)回傳一個Field物件,該物件反映由該Class物件表示的類或介面的指定宣告欄位
Field addressfield = c.getField("address");
//獲取無參構造方法創建物件
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//FieLd提供有關類或介面的單個欄位的資訊.和動態訪問
// void set (object obi,0bject value)將指定的物件引數中由此 Field物件表示的欄位設定為指定的新值
addressfield.set(obj,"西安");//給obj的成員變數addressfield賦值為西安
System.out.println(obj);
}
}
2.6反射獲取成員變數并使用練習
練習:通過反射實作如下操作
- Student s = new Student0;
- s.name =“林青霞”;·
- s.age = 30;·
- s.address =“西安”;
- System.out.println(s);
package javaDemo.reflex.T_Exercise01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/* 練習:通過反射實作如下操作
Student s = new Student0;
s.name ="林青霞";
s.age = 30;
s.address ="西安";
System.out.println(s);
*/
public class ReflectDemo {
public static void main(String[] args)throws Exception {
//獲取Class物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
//通過無參構造創建物件
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
// s.name ="林青霞";
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);//私有類,爆力反射
nameField.set(obj,"林青霞");
//s.age = 30;
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj,30);
//s.address ="西安";
Field addressfield = c.getField("address");
addressfield.set(obj,"西安");
System.out.println(obj);
}
}
2.7反射獲取成員方法并使用
Class類中用于獲取成員方法的方法
- Method[]getMethods0:回傳所有公共成員方法物件的陣列,包括繼承的
-Method[] getDeclaredMetl;ods():回傳所有成員方法物件的陣列,不包括繼承的 - Method getMethod(String name, Class<?>… parameterTypes):回傳單個公共成員方法物件
- Method getDeclaredMethod(String name,Class<?>… parameterTypes):回傳單個成員方法物件
Method類中用于呼叫成員方法的方法
- Object invoke(Object obj, Objec…args):呼叫obj物件的成員方法,引數是args,回傳值是Object型別
package javaDemo.reflex.T_Exercise01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/*
反射獲取成員方法并使用
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception{
//獲取class物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
// c.getMethod()Method[] getMethods();獲取所有公共成員方法(包括繼承)的陣列,方法物件反映由該CLass物件表示的類或介面的所有公共方法,包括由類唉介面宣告的物件以及從超類和超級介面繼承的類
// Method[] getDeclaredMethods();獲取所有成員方法(不包括繼承)的陣列,方法物件反映由CLass物件表示的類或介面的所有宣告方法,包括public,protected,default (package)訪問和私有方法
// Method[] methods = c.getMethods();
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("---------分割線-------------");
// Method getMethod(String name,class<?>.. paramneterTypes)回傳一個方法物件,該物件反映由該class物件表示的類或介面的指定公共成員方法,
// Method getDeelarecMethod(String name, Class<?>... parameterTypes)回傳一個方法物件,它反映此表示的類或介面的指定宣告的方法class對家,
Method m = c.getMethod("method1");
Method m2= c.getDeclaredMethod("method2", String.class);
//獲取無參構造方法創建物件
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//在類或介面上提供有關單一方法的資訊和訪問權限
//Object invoke (0bject obj,Object... args)在具有指定引數的指定物件上呼叫此方法物件表示的基礎方法
//object回傳值型別
//obj:呼叫物件
//args:方法需要的引數
m.invoke(obj);
m2.invoke(obj,"2");
}
}
2.8反射獲取成員方法并使用練習
練習:通過反射實作如下操作
- Student s = new Student();
- s.method1();
- s.method2(林青霞");
- String ss = s.method3(“林青霞”,30);
- System.out.println(ss);
- s.function();
package javaDemo.reflex.T_Exercise01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/* 練習:通過反射實作如下操作
①Student s = new Student();
②s.method1();
③s.method2(林青霞");
④String ss = s.method3("林青霞",30);
⑤System.out.println(ss);
⑥s.function();
*/
public class ReflectDemo_exercise {
public static void main(String[] args)throws Exception {
//獲取物件
Class<?> c = Class.forName("javaDemo.reflex.Demo2.Student");
//獲取無參構造方法創建物件①Student s = new Student();
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//②s.method1();
Method method = c.getMethod("method1");
method.invoke(obj);
//③s.method2(林青霞");
Method method2 = c.getMethod("method2", String.class);
method2.invoke(obj,"林青霞");
//④String ss = s.method3("林青霞",30);
Method method3 = c.getMethod("method3", String.class, int.class);
Object o = method3.invoke(obj,"林青霞", 30);
//⑤System.out.println(ss);
System.out.println(o);
//⑥s.function();
Method function = c.getDeclaredMethod("function");
function.setAccessible(true);
function.invoke(obj);
}
}
3.正則運算式
3.1為什么需要正則運算式
簡潔的代碼
嚴謹的驗證文本框中的內容
一個簡單的運算式即可驗證郵箱
var reg= /^\w+@\w+(\.[a-zA-Z]{2,3}){1,2}$/;
if(reg.test(email) ==false){
$email_prompt.html("電子郵件格式不正確,請重新輸入");
return false;
}
3.2正則運算式的模式
簡單模式
只能表示具體的匹配
String reg=“china”;
String reg=“abc8”;
復合模式
可以使用通配符表達更為抽象的規則模式
String reg="^[0-9]+$";
String reg="^\\w+@\\w+\\.[a-zA-Z]{2,3}$";
3.3正則運算式符號
| 符號 | 描述 |
|---|---|
| /…/ | 代表一個模式的開始和結束 |
| ^ | 匹配字串的開始$匹配字串的結束 |
| \s | 任何空白字符\S任何非空白字符 |
| \d | 匹配一個數字字符,等價于[0-9] |
| \D | 除了數字之外的任何字符,等價于[^0-9] |
| \w | 匹配一個數字、下劃線或字母字符,等價于[A-Za-z0-9_] |
| \W | 任何非單字字符,等價于[^a-zA-z0-9_] |
| . | 除了換行符之外的任意字符 |
| 符號 | 描述 |
|---|---|
| {n} | 匹配前一項n次 |
| {n,} | 匹配前一項n次,或者多次 |
| {n,m} | 匹配前一項至少n次,但是不能超過m次 |
| * | 匹配前一項0次或多次,等價于{0,} |
| + | 匹配前一項1次或多次,等價于{1,} |
| ? | 匹配前一項0次或1次,也就是說前一項是可選的,等價于{0,1} |
3.4方法
| 方法 | 描述 |
|---|---|
| static Pattern compile(String regex, int flags) | 將給定的正則運算式編譯為帶有給定標志的模式, |
| Matcher matcher(CharSequence input) | 創建一個匹配器,匹配給定的輸入與此模式, |
| boolean find() | 嘗試找到匹配模式的輸入序列的下一個子序列, |
3.5驗證郵政編碼和手機號碼
①手機號碼都是11位,并且第1位都是1,第二位沒有0,1,2
②1219446210@qq.com和chen1219446210@163.com
package javaDemo.reflex.LASTDemo;
//①手機號碼都是11位,并且第1位都是1,第二位沒有0,1,2
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PhoneCheck {
public static void main(String[] args) {
String phone="123456789111";//案例(12位)
Pattern pattern=Pattern.compile("^[1]{1}[3-9]{2}[0-9]{9}$");//條件
Matcher matcher = pattern.matcher(phone);//比較
boolean b = matcher.find();//判斷
System.out.println(b);
}
}

package javaDemo.reflex.LASTDemo;
//②1219446210@qq.com和chen1219446210@163.com
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EmailCheck {
public static void main(String[] args) {
String email="1219446210@qq.com";
String email2="chen1219446210@163.com";
Pattern pattern=Pattern.compile("^(([1-9][0-9]{6,11}@qq)|(\\w{1,14}@163)).com$");
Matcher matcher1 = pattern.matcher(email);
Matcher matcher2 = pattern.matcher(email2);
boolean b1 = matcher1.find();
boolean b2 = matcher2.find();
System.out.println(b1);
System.out.println(b2);
}
}

上一章節-DAY25-TCP協議
下一章-隨緣更新
|
|
|
|
|
|

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291302.html
標籤:其他
上一篇:被大廠拒絕后,沉淀兩年,終于拿下(騰訊、阿里、百度等offer)
下一篇:shell第三天作業
