以下為本人的學習筆記 1.為什麼需要泛型 public class GenericDeom{ @Test public void test1(){ List list = new ArrayList(); list.add("tste"); list.add(10); list.add(new Ob ...
以下為本人的學習筆記
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=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+"));
}
■免責申明
⒈ 本站是純粹個人學習網站,與朋友交流共賞,不存在任何商業目的。
⒉ 本站利用了部分網路資源,版權歸原作者及網站所有,如果您對本站所載文章及作品版權的歸屬存有異議,請立即通知我們,我們將在第一時間予以刪除,同時向你表示歉意!