2018.4.19
泛型
泛型簡述。
[問題]
1.發現ArrayList可以放入任意類型的數據,但是實際操作中發現數據類型
不一致會導致更多的錯誤。
2.就是知道取出的數據是一個String類型,但是還是要通過【強轉】才能真正拿到想要的
String類型數據,這個操作很麻煩。
【期望】
集合中的數據類型能夠統一。
數據類型一致化問題。
【解決問題】
泛型
java jdk1.5之後的新特徵。
public class Demo1 {
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<Object>();
list.add(new Demo1());//自定義類對象
list.add("今天週四");
list.add(3);
System.out.println(list);
Object object = list.get(1);
String string = (String) object;
System.out.println(string.length());
System.out.println(string);
Object[] arr = list.toArray();
//Arrays.sort(arr);
System.out.println(arr.toString());
}
}
結果:
[genericity.Demo1@6486b4d5, 今天週四, 3]
4
今天週四
[Ljava.lang.Object;@47ca3f82
泛型實例
使用泛型來解決之前遇到的問題
1.解決集合中數據類型一致化問題,要求保存什麼數據就保存什麼數據,添加其他數據的話報錯。
異常提前。
2.從集合中取出數據,保存的是什麼類型,拿出來的就是什麼類型,不需要無意義的【強制類型轉換】。
標準格式:
ArrayList<String> list = new ArrayList<String>(); <E>佔位符。無意義
以下情況也允許:
1.ArrayList list = new ArrayList<String>();
2.ArrayList<String> list = new ArrayList();
爲了照顧不同的版本和不同IDE工具。
【 但是以下情況不允許】
ArrayList<Object> list = new ArrayList<String>();
ArrayList<String> list = new ArrayList<Object>();
public class Demo2 {
public static void main(String[] args) {
//<String>這是泛型,要求這個ArrayList集合中有且只能保存String類型的數據
ArrayList<String>list = new ArrayList<String>();
list.add("今天阿根廷被灌了6個球。");
list.add("西班牙真牛逼");
list.add("梅西提前離場了");
//這裏無法保存除string類型之外的任意其他類型。
//list.add(new Demo2());
//list.add(1);
String str = list.get(2);
System.out.println(str);
}
}
結果:
梅西提前離場了
泛型的運用
需求:
定義一個方法,可以接受任意數據類型,而且要求返回的數據類型,就是你傳入的數據類型。
例如:
傳入String返回String
傳入Demo3類型返回Demo3類型
泛型的使用需要:
佔位符!<一個大寫字母>,只是一個佔位符,沒有實際含義,而且不同地方定義的佔位符沒有聯繫。
泛型在函數中使用的格式:
修飾符<聲明的自定義泛型佔位符> 返回值類型(可以使用自定義泛型) 函數名(形式參數列表“也可以使用泛型”) {
函數體
在函數體中,所有用到自定義泛型的地方,都可以被替換
}
包裝類:
JAVA是完全面向對象的語言,在JAVA中萬物皆對象,如果是要保存類對象,那麼八大基本數據類型就無法使用,
所以JAVA提供了一個包裝機制,包裝基本數據類型,讓他們成爲類對象,自動封箱。
Integer --> int
Byte --> byte
Long --> long
Short --> short
Double --> double
Float --> float
Boolean --> boolean
Character -> char
如果使用包裝類直接賦值給普通的基本數據類型,這個操作稱之爲拆箱。
public class Demo3 {
public static void main(String[] args) {
String string = getType("String");
Demo3 demo3 = getType(new Demo3());
int num = getType(5);//integer int的包裝類。
}
自定義泛型的佔位符<E>
<E>是自定義泛型的佔位符,表示在該函數中可以使用佔位符E,而E的具體數據類型,由傳入參數控制
這樣操作可以讓函數多樣化,多元化,代碼更加簡單。
public static <E> E getType(E e) {
return e;
}
}
類內使用泛型。
在類內使用泛型。
格式:
class 類名<自定義泛型的佔位符> {
//在這裏所用的泛型和用戶創建對象時聲明的一致。
}
注意事項:
1.一個類聲明的自定義泛型,如果在創建類對象時定了泛型的具,確體數據類型,那麼在整個類內所有用到
該泛型佔位符的非靜態成員方法,使用的數據類型都是創建時創建的類型。
2.如果創建使用了自定義泛型的類對象,但是沒有確定泛型的具體類型,那麼編譯器會把這個
泛型認爲是Object類型。
3.類中聲明的自定義泛型,不能在內的靜態方法使用,如果想讓靜態方法使用泛型,自己聲明自己使用
類似於方法中使用泛型。
4.建議:如果在代碼中出現了多個使用泛型的地方,請使用多個名字。 T E
class InvalidArrayException extends Exception {
public InvalidArrayException(String message) {
super(message);
}
}
class invalidComparatoraException extends Exception {
public invalidComparatoraException(String message) {
super(message);
}
}
class ArrayTools<A> {
/**
* 利用泛型來滿足不同數據類型的排序算法,可以在創建類對象時約束!!
* @param array A類型,泛型的數組,可以是任意類型
* @param com <? super A>是A類型的比較器或者其父類的比較器
* @throws InvalidArrayException 數組無效異常
* @throws invalidComparatoraException 比較器無效異常
*/
public void selectSortUsingCompare(A[] array,Comparator<? super A> com) throws InvalidArrayException, invalidComparatoraException {//?在A之上。
//參數合法性判斷
if(null == array || array.length == 0) {
throw new InvalidArrayException("數組無效");
}else if(null == com) {
throw new invalidComparatoraException("比較器無效");
}
for (int i = 0; i < array.length - 1; i++) {
int index = i;
for(int j = i + 1;j <array.length;j++) {
if(com.compare(array[index], array[j]) > 0) {
index = j;
}
}
if (index != i) {
A tempA = array[index];
array[index] = array[i];
array[i] = tempA;
}
}
}
public void printArray(A[] array) {
for (A a : array) {
System.out.println(a);
}
}
- 靜態成員方法加載的比類早,所以類聲明的泛型是在創建類的時候需求,是不能約束靜態方法的,是無關的,,可以在靜態方法中自己聲明泛型
public static <T> void test(T a) {
System.out.println(a);
}
}
public class Demo4 {
public static void main(String[] args)
throws InvalidArrayException, invalidComparatoraException {
Integer[] array = {1,3,5,6,7,8,2,4};
ArrayTools<Integer> tools = new ArrayTools<Integer>();//
//匿名內部類的匿名對象。 心臟是成員變量描述合適還是成員方法描述合適? 發動機對於汽車? 都不是,屬於成員內部類。
tools.selectSortUsingCompare(array, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
tools.printArray(array);
}
}
結果:
1
2
3
4
5
6
7
8
HashMap
---| Collection
------| List(接口)
---------| ArrayList(實現類)
---------| LinkedList(實現類)
------| Set(接口)
---------| HashSet(實現類)
---------| TreeSet(實現類)
比較器:
Comparable接口 實現 compareTo方法
Comparator接口 實現 compare方法
生活中,有關係的數據更多一點
賬號 密碼
鑰匙 鎖
英文 解釋
NSDictionary Objective-C Next Step公司。
---| Map<K,V> 雙列集合,這是一個接口 Key值不能重複
------| HashMap 實現類
------| TreeMap 實現類
K:key 鍵! 是一個不允許重複的唯一值。
V: Value 值 一個鍵(key)對應一個值(value) 可以重複的
在Map<K,V> 雙列集合中,保存的只能是一個鍵(key)值(value)對。
Map中要學習的方法:
增
put(K key, V value);//添加一個鍵(K)值(value)對
putAll(Map<? extends K,? extends V> map);//添加一個符合數據類型的Map雙列集合
刪
remove(Object key);//根據key刪除對應的鍵值對。
clear();//清空所有鍵值對。
改
put(K key,V value);//當鍵key存在的時候,這個操作時重新修改值。
查
size();//獲取鍵值對個數
get(Object key);//通過鍵獲取對應的值value。
containsKey(Object key);//查看這個key是否在Map中存在。
containsValue(Object value);//查看這個value是否在map中存在
keySet();//返回所有鍵(key)的set的集合
values();//返回所有值(value)的Collection集合
public class Demo1 {
public static void main(String[] args) {
Map<String, String>map = new HashMap<String,String>();
//使用put(k,v)添加元素
map.put("薛之謙", "高磊鑫");
map.put("鹿晗", "關曉彤");
map.put("宋仲基", "宋慧喬");
map.put("余文樂", "王棠雲");
map.put("王寶強", "馬蓉");
System.out.println(map);
Map<String,String> map2 = new HashMap<String,String>();
map2.put("科比", "瓦妮莎");
//添加另一個Map
map.putAll(map2);
System.out.println(map);
//清空當前map雙列集合
map2.clear();
System.out.println(map2.isEmpty());
System.out.println(map2);
//根據Key刪除對應的鍵值對
map.remove("科比");
System.out.println(map);
//當key值存在時,這個操作是修改對應的value
map.put("王寶強", null);
System.out.println(map);
System.out.println(map.size());
System.out.println(map.containsKey("謝霆鋒"));
System.out.println(map.containsKey("薛之謙"));
System.out.println(map.containsValue("高磊鑫"));
System.out.println(map.containsValue("王菲"));
System.out.println(map.get("科比"));
System.out.println(map.get("鹿晗"));
Set<String> set = map.keySet();
for (String string : set) {
System.out.println(string);
}
System.out.println("........................");
Collection<String> c = map.values();
for (String string : c) {
System.out.println(string);
}
System.out.println(c.toString());
}
}
MAP集合遍歷
public class Demo1 {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String,Integer>();
map.put("macpro",28888);
map.put("iphoneX", 8300);
map.put("ipad pro",5190);
System.out.println(map);
//第一種遍歷方式,藉助於keySet
Set<String> set = map.keySet();
//使用Set集合的Iterator迭代器
Iterator<String> it = set.iterator();
while(it.hasNext()) {
String key = it.next();//獲取每一個map中key值
int value = map.get(key);
System.out.println(key+"="+value);
}
//以上方法,其實不太合適,獲取的是key值,再藉助於Map裏面的get方法,獲取相應的value
//並沒有獲取到完整的鍵值對。
//第二種方式,藉助於values
Collection<Integer> c = map.values();
for (Integer i : c) {
System.out.println(i);
}
//以上方法不合適,只能拿到value,不能獲得Key
//在java中,萬物皆對象。[]
/*
這裏把鍵值對認爲是一個對象組成一個類,稱之爲Entry。
class Entry<k,v> {
K key;
V value;
}
//這裏可以認爲在map集合中,保存的每一個鍵值對都是一個entry對象,把這些entry對象獲取出來,
作成一個集合,進行遍歷。
entrySet();
map.Entry
*/
Set<Entry<String,Integer>> entrySet = map.entrySet();
Iterator<Entry<String,Integer>> it2 = entrySet.iterator();
while (it2.hasNext()) {
System.out.println(it2.next());
}
}
}
泛型複習--------錯誤提前
爲了解決數據類型一致化的問題
避免沒有意義的強制類型轉換。
自定義泛型使用的格式
<大寫字母> 一般用T E。
佔位符 沒有任何含義。
泛型在函數中的使用
格式:
權限修飾符<自定義泛型> 返回值類型(可以使用泛型) 函數名(形式參數列表“自定義泛型”) {
同樣可以使用泛型
}
泛型在類中使用
格式:
class 類名<自定義泛型> {
非靜態的成員變量或者方法都可以使用類中定義的<自定義泛型>
靜態方法不能使用類中自定義泛型,但是可以方法中自己定義泛型
}
Array.sort(T[] t,Comparator<? super T> c)
泛型在接口中的使用
格式:
interface 接口名<自定義泛型> {
//成員變量 缺省屬性: public static final 必須初始化因爲final不可變
//成員方法 缺省屬性: abstract
}
一個類遵從帶有自定義泛型的有兩種方式:
例如:
interface A<T> {
public void testA(T t);
}
1.方式1:
class Test1<T> implements A<T> {
public void testA(T t) {
實現方法
}
}
更加自由 在創建類對象時,纔對泛型進行約束。
2.方式2:
class Test implements A<String> {
public void testA(String t) {
//實現方法
}
}
遵從接口時,接口直接確定了泛型的具體類型。
泛型的上下限:
<? super T>
表示數據類型是T對象或者是其父類對象
<? extends T>
表示數據類型是T對象或者其子類對象
##Map
Map<K,V> K不可重複,V可重複 1,1對應。
---| HashMap
---| TreeMap
put(K key, V value);
putAll(map<? extends k,? extends v> map);
clear();
remove(Object k);
size();
containsKey(object Key);
containsValue(Object value);
keySet();
values();
get(Object l);