泛型(規定集合中存取數據的類型)
泛型的概念
泛型的好處:
創建集合對象,不使用泛型
好處:集合不使用泛型,默認的類型就是object類型,可以存儲任意類型的數據
弊端:不安全,會引發異常
創建集合對象,使用泛型
好處:
1.避免了類型轉換的麻煩,存儲的是什么類型,取出的就是什么類型
2.把運行期異常(代碼運行之后拋出異常),提升到編譯期(寫代碼的時候)
弊端:泛型是什么類型,只能存儲什么類型的數據
定義和使用含泛型的類
package commonclass;
public class TestGeneric01 {
public static void main(String[] args) {
//不寫泛型,默認泛型為object類型
GenericClass genericClass01 = new GenericClass();
genericClass01.setName("object對象");
Object name = genericClass01.getName();//object類型
System.out.println(name);
//在創建對象時,泛型使用Integer類型,
GenericClass<Integer> genericClass02 = new GenericClass<>();
genericClass02.setName(1);//自動裝箱
System.out.println(genericClass02.getName());//自動拆箱
//在創建對象時,泛型使用String類型
GenericClass<String> genericClass03 = new GenericClass<>();
genericClass03.setName("張三");
System.out.println(genericClass03.getName());
}
}
/*定義一個含有泛型的類
* 泛型是一個未知的數據類型,只有在創建對象是才被確定,所有當我們不確定使用什么數據類型時,可以使用泛型
* 泛型可以接收任何引用數據類型,不能接收基本數據類型(需要用到其包裝類)
* 在創建對象的時候,才能確定泛型的數據類型*/
class GenericClass<E> {
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
定義和使用含泛型的方法
package commonclass;
public class TestGenericMethod01 {
public static void main(String[] args) {
GenericMethod01 genericMethod01 = new GenericMethod01();
//傳遞什么類型,泛型就是什么類型
genericMethod01.printE(1);
genericMethod01.printE("hello");
}
}
/*定義含有泛型的方法:泛型定義在修飾符和返回值之間
* 格式:
* 修飾符 <泛型> 返回值 方法名(參數列表(使用泛型)){
* 方法體;
* }
* 含有泛型的方法,在調用方法的時候確定泛型的數據類型
* 傳遞什么參數,泛型就是什么類型*/
class GenericMethod01{
public <E> void printE(E e){
System.out.println(e);
}
}
泛型接口的定義和使用
package commonclass;
//定義含有泛型的接口
public interface GenericIterface<E> {
public abstract void method(E e);
}
package commonclass;
//含有泛型的接口的兩種使用方式
//第一種:定義接口的實現類,實現其接口,並指定接口的泛型
public class GenericIterfaceImpl implements GenericIterface<String>{
@Override
public void method(String s) {
System.out.println(s);
}
}
class Test01{
public static void main(String[] args) {
GenericIterfaceImpl genericIterface = new GenericIterfaceImpl();
genericIterface.method("哈哈哈哈");
}
}
package commonclass;
//含有泛型的接口的第二種使用方式:接口使用什么泛型,類就使用什么泛型,類跟着接口走
//就相當於創建了一個含有泛型的類,創建對象時確定泛型
//注意:類名和接口名后都要加泛型格式
public class GenericIterfaceImpl2<E> implements GenericIterface<E>{
@Override
public void method(E e) {
System.out.println(e);
}
}
class Test2{
public static void main(String[] args) {
GenericIterfaceImpl2<String> genericIterfaceImpl2 = new GenericIterfaceImpl2<>();
genericIterfaceImpl2.method("哈哈哈哈哈哈");
}
}
泛型的通配符:<?>
?:代表任意類型的數據
使用方式:不能創建對象時使用,只能作為方法參數使用
package commonclass;
import java.util.ArrayList;
public class TestGeneric02 {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
ArrayList<String> arrayList1 = new ArrayList<>();
arrayList1.add("abc");
arrayList1.add("abc");
arrayList1.add("abc");
printArrayList(arrayList);
printArrayList(arrayList1);
}
/*定義一個方法,能夠打印任意數據類型的arrayList集合
* 由於不知道arrayList集合里面的數據類型,可以用通配符來接收數據
* 注意:泛型沒有繼承關系的*/
public static void printArrayList(ArrayList<?> arrayList){//如果寫成ArrayList<object> ,調用方法時會出錯,泛型沒有繼承關系的
for (Object o : arrayList) {
System.out.println(o);
}
}
}
通配符的高級使用---受限泛型
package commonclass;
import java.util.ArrayList;
import java.util.Collection;
/*
* 泛型的上限限定:<? extends E> 代表泛型只能使用其子類/本身
* 泛型的下限限定:<? super E> 代表泛型只能使用其父類/本身
* */
public class TestGeneric03 {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<>();
Collection<String> list2 = new ArrayList<>();
Collection<Number> list3 = new ArrayList<>();
Collection<Object> list4 = new ArrayList<>();
getElement1(list1);
getElement1(list2);//報錯
getElement1(list3);
getElement1(list4);//報錯
getElement2(list1);//報錯
getElement2(list2);//報錯
getElement2(list3);
getElement2(list4);
}
/*繼承關系
* Integer extends Number extends Object
* String extends Object*/
//泛型的上限限定:<? extends E> 代表泛型只能使用其子類/本身
public static void getElement1(Collection<? extends Number> collection){}
//泛型的下限限定:<? super E> 代表泛型只能使用其父類/本身
public static void getElement2(Collection<? super Number> collection){}
}
練習:斗地主綜合案例
分析:
package commonclass;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
//模仿斗地主發牌
public class PracticeAll {
public static void main(String[] args) {
//准備54張牌
Collection<String> arrayList = new ArrayList<>();
arrayList.add("♠");
arrayList.add("♥");
arrayList.add("♣");
arrayList.add("♦");
Collection<String> arrayList2 = new ArrayList<>();
for (int i = 2; i <= 10; i++) {
arrayList2.add(Integer.toString(i));
}
arrayList2.add("J");
arrayList2.add("Q");
arrayList2.add("K");
arrayList2.add("A");
ArrayList<String> list = new ArrayList<>();//54張牌集合
for (String al2 : arrayList2) {
for (String al1 : arrayList) {
list.add(al1+al2);
}
}
list.add("joker");
list.add("JOKER");
//輸出檢查54張牌
for (String s : list) {
System.out.print(s+"\t");
}
System.out.println();
//將54張牌打亂
Collections.shuffle(list);
//輸出檢查54張牌
for (String s : list) {
System.out.print(s+"\t");
}
System.out.println();
//准備四個集合,容納三個人的牌和底牌
ArrayList<String> a1 = new ArrayList<>();
ArrayList<String> a2 = new ArrayList<>();
ArrayList<String> a3 = new ArrayList<>();
ArrayList<String> bottom = new ArrayList<>();
//依次每人發一張牌,留下最后三張牌,插底
for (int i = 0; i < list.size(); i++) {
if (i >= 51) {
bottom.add(list.get(i));
continue;
}
if (i % 3 == 0){
a1.add(list.get(i));
continue;
}
if (i % 3 == 1){
a2.add(list.get(i));
continue;
}
if (i % 3 == 2){
a3.add(list.get(i));
continue;
}
}
//對每個人手中的牌進行排序,按花色類型(這兒還可以優化,先按牌大小,再按花色排序)
Collections.sort(a1);
Collections.sort(a2);
Collections.sort(a3);
Collections.sort(bottom);
//查看三個人手中的牌,插底的牌
System.out.println("第一個人手中的牌:");
for (String s : a1) {
System.out.print(s+"\t");
}
System.out.println();
System.out.println("第二個人手中的牌:");
for (String s : a2) {
System.out.print(s+"\t");
}
System.out.println();
System.out.println("第三個人手中的牌:");
for (String s : a3) {
System.out.print(s+"\t");
}
System.out.println();
System.out.println("插底的三張牌:");
for (String s : bottom) {
System.out.print(s+"\t");
}
}
}
加強版:可對看牌進行排序
package commonclass;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
//斗地主發牌,改進版,在看牌時,可對牌進行排序
public class PracticeAll02 {
public static void main(String[] args) {
//准備54張牌
ArrayList<Poker> pokerAll = new ArrayList<>();
String[] types = {"♠","♥","♣","♦"};
String[] nums ={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
for (String type : types) {
for (int i = 0; i < nums.length; i++) {
pokerAll.add(new Poker(type,nums[i],i));
}
}
pokerAll.add(new Poker("□","joker",13));
pokerAll.add(new Poker("■","JOKER",14));
System.out.println(pokerAll);
//打亂54張牌
Collections.shuffle(pokerAll);
System.out.println(pokerAll);
//准備四個集合,放三個玩家的牌和底牌
ArrayList<Poker> p1 = new ArrayList<>();
ArrayList<Poker> p2 = new ArrayList<>();
ArrayList<Poker> p3 = new ArrayList<>();
ArrayList<Poker> bottom = new ArrayList<>();
ArrayList[] arrayLists = {p1,p2,p3,bottom};
//開始發牌
for (int i = 0; i < pokerAll.size(); i++) {
if (i >= 51){
bottom.add(pokerAll.get(i));
}else if (i % 3 == 0){
p1.add(pokerAll.get(i));
}else if (i % 3 == 1){
p2.add(pokerAll.get(i));
}else if (i % 3 == 2){
p3.add(pokerAll.get(i));
}
}
//對玩家手中的牌進行排序
for (ArrayList list : arrayLists) {
Collections.sort(list, new Comparator<Poker>() {
@Override
public int compare(Poker o1, Poker o2) {
int result = o2.getWeight() - o1.getWeight();//先按權重
if (result == 0){
result = o1.getType().hashCode() - o2.getType().hashCode();//再根據花色
}
return result;
}
});
}
//查看每位玩家的牌和底牌,優化
for (int i = 0; i < arrayLists.length; i++) {
if (i == arrayLists.length - 1){
System.out.println("底牌為:");
}else {
System.out.println("第"+(i+1)+"位玩家手中的牌:");
}
Iterator iterator = arrayLists[i].iterator();
while (iterator.hasNext()){
Poker poker = (Poker) iterator.next();
System.out.print(poker.getType()+poker.getNum()+"\t");
}
System.out.println();
}
/* System.out.println("第一位玩家手中的牌:");
for (Poker poker : p1) {
System.out.print(poker.getType()+poker.getNum()+"\t");
}
System.out.println();
System.out.println("第二位玩家手中的牌:");
for (Poker poker : p2) {
System.out.print(poker.getType()+poker.getNum()+"\t");
}
System.out.println();
System.out.println("第三位玩家手中的牌:");
for (Poker poker : p3) {
System.out.print(poker.getType()+poker.getNum()+"\t");
}
System.out.println();
System.out.println("底牌為:");
for (Poker poker : bottom) {
System.out.print(poker.getType()+poker.getNum()+"\t");
}
*/
}
}
class Poker{
private String type;
private String num;
private int weight;
public Poker() {
}
public Poker(String type, String num, int weight) {
this.type = type;
this.num = num;
this.weight = weight;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Poker{" +
"type='" + type + '\'' +
", num='" + num + '\'' +
", weight=" + weight +
'}';
}
}