
🧡💛💚💙💜🤎💗感謝各位一直以來的支持和鼓勵🧡💛💚💙💜🤎💗
制作不易🙏🙏🙏求點贊👍 👍 👍 ? 收藏 ? ? ? ?關注???
???????????????????????????????????
👉👉👉👉👉👉🧡💛💚💙💜🤎💗 一鍵三連走起 🧡💛💚💙💜🤎💗
一、 了解類加載
(1 )概述:
當程式要使用某個類時,如果該類還沒有加載到記憶體中,系統會通過類的加載,類的連接,類的初始化三個步驟來對類進行初始化
(2)類的加載
- 將class檔案(源檔案)讀取記憶體,并創建對應的Class物件
- 任何類被使用時,系統都會創建一個java.lang.Class物件
(3) 類的連接
- 驗證階段:檢驗被加載的類和相關類(父類/介面)內部結構是否合法
- 準備階段:負責為類中的變數分配記憶體,并設定默認值
- 決議階段:將類的二進制資料中字符(方法)參考改為直接參考
(4)類的初始化:
對類變數進行初始化(賦值)
- 1.當類還未被加載和連接時,程式要先加載并連接該類
- 2.該類的直接父類未被初始化,要先初始化直接父類
- 3.假如類中有初始化陳述句(非static修飾),那么依次執行初始化陳述句
執行步驟2時,同樣遵循1-3
(5)類加載的使用
- 創建類的實體
- 操作類或相關的類變數
- 呼叫類方法
- 初始化子類
- 直接使用java.exe運行某個主類
- 使用反射方式強制創建類或介面對應的Class物件
二、類加載器
Java加載類時,都是通過類加載器來進行加載
(1)類加載器的作用:
負責將class檔案加載到記憶體中,生成對應的Class物件
(2)類加載器的機制
- 全盤負責:當類加載器負責加載某一個class檔案時,與之相關的class檔案也由該類加載器負責,除非顯示由另一個加載器負責
- 父類委托:加載某一個class檔案時,先讓父類的加載器試圖加載該class檔案,只有在父類無法加載該class檔案時,才嘗試從自己的類路徑加載
- 快取機制:會把所有加載的class檔案生成的Class物件進行快取,當程式需要使用某一個Class物件時,類加載器首先去快取中搜索,快取中不存在時,才會將class檔案加載到記憶體中,并生成對應的Class物件
三、反射
反射就是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個物件,都能夠呼叫它的任意方法和屬性;并且能改變它的屬性,這也就是Java被視為動態(或準動態)原因,為什么說是準動態,是因為一般而言的動態語言定義是程式運行時,允許改變程式結構或變數型別,這種語言稱為動態語言,
(1) 反射獲取Class物件
通過反射使用一個類,需要獲取該類位元組碼檔案,也就是型別為Class的物件
獲取方式
- 1.使用該類的class屬性來獲取對應的Class物件,
- 2.呼叫該類的getClass()方法,回傳該物件所屬類對用的Class物件
該方法是Object中的方法,所有類都可以調動 - 3.使用Class中的靜態方法forName(String className),該方法需要傳入String引數,引數是某個類完整的包名
示例代碼:
//1.使用該類的class屬性來獲取對應的Class物件,
// 獲取User類編譯后的位元組碼檔案 User.class
Class<User> userClass = User.class;
System.out.println(userClass);
//class com.xiaobei.lambda.demo_class.User 回傳該類的路徑(位置)
//2.呼叫getClass()方法,回傳該物件所屬類對用的Class物件
// getClass()方法是Object中的方法,所有類都可以調動,
User user = new User();//創建物件
Class<? extends User> userClass1 = user.getClass();
System.out.println(userClass1);
//class com.xiaobei.lambda.demo_class.User 回傳該類的路徑(位置)
// 3.使用Class中的靜態方法forName(String className),
// 該方法需要傳入String型別的引數,引數是某個類完整的包名
Class<?> aClass = Class.forName("com.xiaobei.lambda.demo_class.User");
System.out.println(aClass);
測驗結果:

(2)反射獲取構造方法
Class類中用于獲取構造方法的方法:
Constructor<?>[] getConstructors():
獲取所有公共構造物件的陣列
Constructor<?>[] getDeclaredConstructors():
獲取所有構造物件的陣列
Constructor<T>[] getConstructors(Class<?>... parameterTypes):
回傳單個公共構造方法物件
Constructor<T>[] getDeclaredConstructor(Class<?>... parameterTypes):
回傳單個構造方法物件
Class類中用于使用構造方法的方法:
T newInstance(Object... initargs);
根據指定的構造方法創建物件
注意:
通過反射私有化構造不能直接創建物件需要通過setAccessible方法
示例代碼;
public class User {
//無參構造
public User() {
System.out.println("我是無參構造");
}
//有參構造
public User(String name) {
System.out.println("我是有參構造\t"+name);
}
//私有構造
private User(String name,int age){
System.out.println("我是私有有參構造\t"+name+"--"+age);
}
}
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
// 獲取User類編譯后的位元組碼檔案 User.class
Class<User> userClass = User.class;
//1. Constructor<?>[] getConstructors():獲取所有公共構造物件的陣列
System.out.println("獲取所有公共構造物件的陣列");
Constructor<?>[] userClassConstructors = userClass.getConstructors();
for (Constructor<?> userClassConstructor : userClassConstructors) {
System.out.println(userClassConstructor);
}
System.out.println("--------------------------------");
//2.Constructor<?>[] getDeclaredConstructors():獲取所有構造物件的陣列
System.out.println("獲取所有構造物件的陣列");
Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("--------------------------------");
//3. Constructor<T>[] getConstructors(Class<?>... parameterTypes):回傳單個公共構造方法物件
System.out.println("回傳單個公共構造方法物件");
Constructor<User> constructor = userClass.getConstructor(String.class);
System.out.println(constructor);
System.out.println("--------------------------------");
//4. Constructor<T>[] getDeclaredConstructor(Class<?>... parameterTypes):回傳單個構造方法物件
System.out.println("回傳單個構造方法物件");
Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class,int.class);
System.out.println(declaredConstructor);
Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor1);
System.out.println("--------------------------------");
//5. T newInstance(Object... initargs);根據指定的構造方法創建物件
//每個類都有一個默認的構造方法,所以不需要指定,可以直接使用
User user = userClass.newInstance();
System.out.println(user);
//使用指定構造方法創建物件
Constructor<User> declaredConstructor2 = userClass.getDeclaredConstructor(String.class);
User user1 = declaredConstructor2.newInstance("張三");
System.out.println(user1);
//使用指定私有方法創建物件
//注意:會報錯private 修飾的無妨創建
//解決辦法:因為編譯程序中會檢測是否符合Java語法格式,那么我們可以繞過編譯安全檢測機制(又稱“暴力反射”/“暴射”)
Constructor<User> declaredConstructor3 = userClass.getDeclaredConstructor(String.class, int.class);
//設定為可通行的語法格式,可以讓Class物件認為private修飾的構造符合
declaredConstructor3.setAccessible(true);
User user2 = declaredConstructor3.newInstance("李四", 20);
System.out.println(user2);
}
}
測驗結果:

(3)反射獲取成員變數方法
Class類中用與獲取成員變數的方法
Field[] getFields();獲取所有公共成員變數的陣列
Field[] getDeclaredFields();獲取所有成員變數的陣列
Field[] getFields(String name);回傳單個公共成員變數的物件
Field[] getDeclaredFields(String name);回傳單個成員變數的物件
Class類中用與成員變數賦值的方法
void set(Object obj,Object value): 給obj物件的成員賦值value
注意:
通過反射私有化成員不能直接賦值,需要通過setAccessible()方法
示例代碼:
public class User {
public String name;
public int uid;
private int age;
private double weight;
}
public class Test {
public static void main(String[] args) throws Exception {
// 獲取User類編譯后的位元組碼檔案 User.class
Class<User> userClass = User.class;
//Class類中用與獲取成員變數的方法
//Field[] getFields();獲取所有公共成員變數的陣列
System.out.println("獲取所有公共成員變數的陣列");
Field[] fields = userClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-----------------------------");
//Field[] getDeclaredFields();獲取所有成員變數的陣列
System.out.println("獲取所有成員變數的陣列");
Field[] declaredFields = userClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("-----------------------------");
//Field[] getFields(String name);回傳單個公共成員變數的物件
System.out.println("回傳單個公共成員變數的物件");
Field field = userClass.getField("name");
System.out.println(field);
System.out.println("-----------------------------");
//Field[] getDeclaredFields(String name);回傳單個成員變數的物件
System.out.println("回傳單個成員變數的物件");
Field name = userClass.getDeclaredField("name");
System.out.println(name);
Field age = userClass.getDeclaredField("age");
System.out.println(age);
System.out.println("-----------------------------");
//Class類中用與成員變數賦值的方法
//void set(Object obj,Object value):給obj物件的成員賦值value
//給公有的成員變數賦值
System.out.println("給公有的成員變數賦值");
Field name1 = userClass.getDeclaredField("name");
User user = userClass.newInstance();
name1.set(user,"張三");
System.out.println(user.name);
//給私有的成員變數賦值
System.out.println("給私有的成員變數賦值");
Field age1 = userClass.getDeclaredField("age");
//繞過安全檢測機制
age1.setAccessible(true);
User user1 = userClass.newInstance();
age1.set(user1,20);
//System.out.println(user1.age);//不符合java語法
Object o = age1.get(user1);
System.out.println(o);
}
}
測驗結果:

(4)反射獲取成員方法方法
Class類中用與獲取成員變數的方法
Method[] getMethods();
獲取所有公共成員方法(包括繼承)的陣列
Method[] getDeclaredMethods();
獲取所有成員方法(不包括繼承)的陣列
Method[] getMethod(String name,Class<?>... parameterTypes);
回傳單個公共成員方法的物件
Method[] getDeclaredMethod(String name,Class<?>... parameterTypes);
回傳單個成員方法的物件
Method類中用與呼叫成員方法的方法
Object invoke(Object obj,Object...args):
呼叫obj物件的成員方法引數為args,回傳值為Object
注意:
通過反射私有化成員方法不能直接呼叫,需要通過setAccessible方法
測驗代碼:
public class User {
public void fun(){
System.out.println("我是公有無參成員方法");
}
public void show(int sum){
System.out.println("我是公有有參成員方法"+ sum);
}
private void fun1(){
System.out.println("我是私有無參成員方法");
}
private void show1(int sum){
System.out.println("我是私有有參成員方法"+ sum);
}
}
public class Test {
public static void main(String[] args) throws Exception {
// 獲取User類編譯后的位元組碼檔案 User.class
Class<User> userClass = User.class;
//Class類中用與獲取成員變數的方法
//Method[] getMethods();獲取所有公共成員方法(包括繼承)的陣列
System.out.println("獲取所有公共成員方法(包括繼承)的陣列");
Method[] methods = userClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("----------------------------------");
//Method[] getDeclaredMethods();獲取所有成員方法(不包括繼承)的陣列
System.out.println("獲取所有成員方法(不包括繼承)的陣列");
Method[] declaredMethods = userClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("----------------------------------");
//Method[] getMethod(String name,Class<?>... parameterTypes);回傳單個公共成員方法的物件
System.out.println("回傳單個公共成員方法的物件");
Method show = userClass.getMethod("fun");
System.out.println(show);
System.out.println("----------------------------------");
//Method[] getDeclaredMethods(String name,Class<?>... parameterTypes);回傳單個成員方法的物件
System.out.println("回傳單個成員方法的物件");
//公有
Method show1 = userClass.getDeclaredMethod("show", int.class);
System.out.println(show1);
//私有
Method show11 = userClass.getDeclaredMethod("show1", int.class);
System.out.println(show11);
System.out.println("----------------------------------");
//Method類中用與呼叫成員方法的方法
//Object invoke(Object obj,Object...args):
// 呼叫obj物件的成員方法引數為args,回傳值為Object
//公有
Method show12 = userClass.getDeclaredMethod("fun");
User user = userClass.newInstance();
show12.invoke(user);
//私有
Method show13 = userClass.getDeclaredMethod("show1", int.class);
show13.setAccessible(true);//繞過型別檢測機制
User user1 = userClass.newInstance();
show13.invoke(user1,30);
}
}
測驗結果:


四、正則運算式
正則運算式的作用:
使用簡潔的代碼,嚴謹的驗證文本框中的內容
正則運算式的模式:
- 簡單模式:只能表示具體的匹配
- 復合模式:可以使用通配符表達更為抽象的規則模式
正則運算式符號:
| 符號 | 功能描述 |
|---|---|
| 匹配的內容 | |
| /…/ | 表示一個模式的開始和結束 |
| ^ | 表示匹配字串的開始 |
| $ | 表示匹配字串的結束 |
| \s | 表示任何的空白字符 |
| \S | 表示任何的非空白字符 |
| \d | 表示匹配一個數字字符,等價于[0-9] |
| \D | 表示除了數字之外的任何字符,等價于[^0-9] |
| \w | 表示匹配一個數字、下劃線或字母字符,等價于[A-Za-z0-9_ ] |
| \W | 表示任何非單字字符,等價于[^a-zA-z0-9_ ] |
| . | 表示除了換行符之外的任意字符 |
| [a-z] | 表示匹配a到z之間的任意字符 |
| 匹配的次數 | |
| {n} | 表示匹配前一項n次 |
| {n,} | 表示匹配前一項n次,或者多次 |
| {n,m} | 表示匹配前一項至少n次,但是不能超過m次 |
| * | 表示 匹配前一項0次或多次,等價于{0,} |
| + | 表示匹配前一項1次或多次,等價于{1,} |
| ? | 表示匹配前一項0次或1次,也就是說前一項是可選的,等價于{0,1} |
正則運算式的功能
匹配: matches
切割: split
替換: replaceAll
獲取: find、group
正則運算式的使用
【案例一】:判斷QQ號是否合法
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Task {
public static void main(String[] args) {
//判斷QQ號(5-10位)是否合法,例如:12345678(5-8位數字)
String qq="2601149032";
//寫正則運算式
String reg="^[1-9]{5,9}$";
//轉換String->Reg
//使用Pattern類compile()方法
Pattern compile = Pattern.compile(reg);
//匹配,呼叫Matcher類的matcher()方法,匹配判斷是否合法
Matcher matcher = compile.matcher(qq);
//呼叫find()方法,判斷匹配是否合法
boolean b = matcher.find();
System.out.println(b);//回傳true,合法
}
}
【案例二】:判斷手機號是否合法
public class Task {
public static void main(String[] args) {
//判斷手機號(1開頭,11位數)是否合法
String qq="13850536081";
//寫正則運算式
String reg="^1[0-9]{10}$";
//轉換String->Reg
//使用Pattern類compile()方法
Pattern compile = Pattern.compile(reg);
//匹配,呼叫Matcher類的matcher()方法,匹配判斷是否合法
Matcher matcher = compile.matcher(qq);
//呼叫find()方法,判斷匹配是否合法
boolean b = matcher.find();
System.out.println(b);//true,合法
}
}
【案例三】:判斷QQEmail是否合法
public class Task {
public static void main(String[] args) {
//驗證QQ郵箱是否合法(0不能開頭,6-10位數字,后綴 @qq.com)
String qqemail="123ab67891@qq.com";
String reg ="^[1-9][0-9]{5,9}@qq.com$";
Pattern compile = Pattern.compile(reg);
Matcher matcher = compile.matcher(qqemail);
boolean b = matcher.find();
System.out.println(b);//回傳false,不合法
}
}
【案例四】:判斷郵箱的格式是否正確
以123ab67891@qq.com和a1236548@163.com為例演示
public class Task {
public static void main(String[] args) {
//驗證郵箱格式是否合法(10位數字,后綴 @qq.com或則@163.com)
//QQ郵箱,(0不能開頭,6-10位數字,后綴 @qq.com)
String qqemail="123ab67891@qq.com";
//網易郵箱,允許有一個字母5-11個數字@163.com
String wyemail="a1236548@163.com";
//String reg ="^(([1-9][0-9]{5,9}@qq.com)|([A-z][0-9]{5,11}@163.com))$";
String reg ="^([1-9][0-9]{5,9}@qq)|([A-z][0-9]{5,11}@163).com$";
Pattern compile = Pattern.compile(reg);
Matcher matcher = compile.matcher(qqemail);
boolean b = matcher.find();
System.out.println(b);//回傳false,不合法
Matcher matcher1 = compile.matcher(wyemail);
boolean b1 = matcher1.find();
System.out.println(b1);//回傳true,合法
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/291457.html
標籤:java
下一篇:用Java撰寫簡單的撲克牌游戲
