以下為本人的學習筆記
1.為什么需要泛型
public class GenericDeom{
@Test
public void test1(){
List list = new ArrayList();
list.add("tste");
list.add(10);
list.add(new Object());
//List中可以添加任意型別,因為引數是Object,這樣一個我們在遍歷這個集合時:
for(int i = 0;i<list.size();i++){
//如果我們不能確定集合中的元素型別,那么我們需要在處理元素時
//要判斷元素的型別,才能做相應的操作
}
}
}
以上操作主要存在兩個問題:
1.當我們將一個物件放入集合中,集合不會記住物件的型別,當再次從集合中取出此物件時,改變物件的編譯型別變成了Object型別,但其運行時型別仍然為其本身型別,
2.因此,//1處取出集合元素時需要認為的強制型別轉化到具體的目標型別,且很容易出現“java.lang.ClassCastException”例外
那么有沒有辦法可以是集合能夠記住集合中元素各型別,且能夠達到只要編譯時不出現問題,運行時就不會出現“java.lang.ClassCastException”例外呢?答案就是使用泛型
泛型三種寫法:
-
List<String> list = new ArrayList<String>();
-
List<String> list = new ArrayList<>();//JDK1.7以上
-
List<String> list = new ArrayList();
2.什么是泛型
JDK1.5之后出現了新的技術——泛型(Generic),此技術的最大特點是類中的屬性的型別可以由外部決定,
泛型又稱為引數化型別,是一種編譯時型別安全檢測機制,型別引數的魅力在于,使得程式具有更好的可讀性和安全性,
引數化型別就是將型別由原來的具體的型別引數化,類似于方法中的變數引數,此時型別也定義成引數形式(可以稱為型別形參),然后再使用/呼叫時傳入具體的型別(型別實參)
<E>:不確定引數化型別
3.自定義泛型介面、泛型類
//泛型類
//T,E,K,V:引數化型別,也叫泛型形參,在實際使用時才會指定具體型別
//泛型只是作用于代碼編譯階段,編譯后會被擦除
public class Node<T>{
private T date;
public Node(){}
public Node(T data){
this.data=https://www.cnblogs.com/lyh1024/archive/2022/10/28/data;
}
...//getter和setter
}
//測驗方法
public void testNode(){
Node<Number> numberNode = new Node<>();
Node<Integer> intNode = new Node<>();
}
泛型只是作用于代碼編譯階段,在編譯程序中,對于正確檢驗泛型結果后,會將泛型的相關資訊擦除,也就是說,成功編譯過后的class檔案中是不包含任何泛型資訊的,泛型資訊不會進入到運行時階段
4.通配符
public void test2(){
Node<Number> n1 = new Node<>(10);
Node<Integer> n2 = new Node<>(20);
getData(n1);
//getData(n2);//盡管兩者有繼承關系,編譯報錯,因為方法指定了具體的泛型型別
//n1 = n2 ;//不支持
getData2(n2);//不報錯
}
public static void getDate(Node<Number> node){
System.out.println(node.getData());
}
//改進
public static void getDate2(Node<?> node){
// node.setData(20);//會報錯,不能修改值,“?”表示可以接收任意的泛型型別,但是只是接收輸出,并不能修改
System.out.println(node.getData());
}
“?”表示可以接收任意的泛型型別,但是只是接收輸出,并不能修改
所以,使用通配符可以參考其他各種引數化型別,通配符定義的變數主要用作參考,可以呼叫與引數無關的方法,不能呼叫與引數有關的方法
泛型上限就指一個的操作泛型最大的操作父類,例如,現在最大的上限設定為“Number”型別,那么此時,所能夠接收到的型別只能是Number及其子類(Integer),
-
語法:?extends類 如:(Node<?extends Number> data)只能是Number類以及其子類
泛型下限就指只能設定其具體的類或者父類,
-
語法: ?super類
注意:?extends類和?super類跟?一樣只是接收輸出,并不能修改
5.泛型方法
泛型除了在類中定義之外,還可以在方法上定義,而且在方法上使用泛型,此方法所在的類不一定是泛型的操作類
//泛型方法
//例子:交換位置方法
//static 后,回傳值型別前,加上泛型
public static <T> T[] func(T[] array,int i,int t){//定義一個回傳型別T[]是泛型<T>
T temp = array[i];
array[i] = array[t];
array[t] = temp;
return array;
}
6.泛型的嵌套使用
在使用集合Map的時候,我們可以這樣遍歷
public void test5(){
Map<Integer,String> map = new HashMap<>();
map.put(1,"ss");
map.put(2."tt");
Set<Map.Entry<Integer,Strig>> entrySet = map.entrySet();
for(Map.Entry entry:entrySet){
System.out.println(entry.getKey()+"-"+entry.getValue());
}
}
7.正則運算式
正則運算式(Regular Expression)使用單個字串描述、匹配一系列符合某個句法規則的字串,
正則運算式通常被用來檢索、替換那些符合某個模式 的文本
java.util.regex包中提供以下兩個類對正則運算式的支持:
Matcher(匹配)類:通過解釋Pattern對character sequence執行匹配操作的引擎
Pattern(模式)類:正則運算式的編譯表示形式
//eg.如何直到一串字串是由數字組成
//沒有使用正則運算式
public void test1(){
String s = "7894562";
char[] chars = s.toCharArray();
boolean flag = true;
for(int i = 0;i<chars.length;i++){
if(chars[i]<'0' || chars[i]>9){
flag = false;
break;
}
}
if(flag){
System.out.println("是由數字組成");
}else{
System.out.println("不是由數字組成");
}
}
?
//使用正則運算式
public void test3(){
String s = "7894562";
boolean b = s.matches("[0-9]+");
boolean b1 = s.matches("\\d+");
System.out.println(b+"-"+b1);
}
8.Pattern類
public final class Pattern extends Objectimplements Serializable
正則運算式的編譯表示形式,指定為字串的正則運算式必須首先被編譯為此類的實體
典型的呼叫順序是
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
public void test2(){
//創建一個匹配模式(模板)
Pattern p = Pattern.compile("a*b");//*代表0到多個a
Matcher matcher = p.matcher("aaaaab");
boolean b = m.matches();//匹配
System.out.println(b);
}
9.Matcher類
public final class Matcherextends Objectimplements MatchResult
Matcher類的主要功能是用于正則的匹配,通過Pattern類中定義完的正則,再使用Matcher類進行驗證或者替換
常用方法:
| Method | 說明 |
|---|---|
| boolean matches() | 嘗試將整個區域與模式匹配 |
| String replaceAll(String replacement) | 替換模式與給定替換字串相匹配的輸入序列的每個子序列 |
| String replaceFirst(String replacement) | 替換模式與給定替換字串相匹配的輸入序列的第一個子序列 |
regex引數表示正則運算式的模板
10.String類對正則的支持
JDK1.4加入了正則
| Method | 說明 |
|---|---|
| boolean matches(String regex) | 告知此字串是否匹配給定的正則運算式 |
| String replaceAll(String regex,String replacement) | 使用給定的replacement替換此字串所有匹配給定的正則運算式的子字串 |
| String replaceFirst(String regex,String replacement) | 使用給定的replacement替換此字串所有匹配給定的正則運算式的第一個子字串 |
| String[] split(String regex) | 根據給定正則運算式的匹配拆分此字串 |
11.正則運算式示例
-
驗證電話號碼(如:066-98563256)
-
驗證手機號碼
-
驗證用戶名,只能是字母開頭的數字、字母或下劃線的組合
-
驗證IP地址(如:192.168.0.1)
-
驗證網址(如:http://www.baidu.com)
-
驗證年齡(100以內)
-
驗證金額(可以有小數位)
public void test(){
//匹配電話號碼
String phoneNumber = "010-38389438";
boolean b = phoneNumber.matches("\\d{3,4}-\\d{7,8}");// //d 是數字,{}表示位數,-原意輸出
System.out.println(b);
//匹配手機號碼
String phone = "17239947985";
System.out.println(phone,matches("[1][3-9]\\d{9}"));//[3-9]表示3到9都可以
//匹配用戶名,只能是字母開頭的數字、字母或下劃線的組合
String username= "abk123";
System.out.println(username.matches("[a-zA-Z]+[\\w|_]*"));//+表示一次或多次,|表示或,\\w表示單詞字符
//匹配IP地址
String ip = "20.10.20.123";
System.out.println(ip.matches("\\d{1,3}.d{1,3}.d{1,3}.d{1,3}."));//{1,3}表示1到3位
//匹配網址
String addr = "http://www.baidu.com";
System.out.println(username.matches("[http://\\w+.\\w+.\\S*"));// \\S表示非空白字符
//匹配年齡(100以內)
String age = "19";
System.out.println(username.matches("\\d{1,3}"));
//匹配金額(可以有小數位)
String price = "23.3";
System.out.println(username.matches("\\d+.\\d+"));
?
}
■免責申明
⒈ 本站是純粹個人學習網站,與朋友交流共賞,不存在任何商業目的,
⒉ 本站利用了部分網路資源,著作權歸原作者及網站所有,如果您對本站所載文章及作品著作權的歸屬存有異議,請立即通知我們,我們將在第一時間予以洗掉,同時向你表示歉意!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/522886.html
標籤:其他
上一篇:【HDLBits刷題日記】08 Karnaugh Map to Circuit
下一篇:三、回圈陳述句基礎
