### 概述
泛型:泛泛的類型.就是不確定的類型.
集合中是可以存放任意對象的,只要把對象存儲集合后,那么這時它們都會被提升為object類型. 當我們在取出每一個對象,并且進行相應的操作, 這時必須采用類型轉換 . 由于集合什么類型的元素都可以存儲 .導致取出時 ,如果出現強轉就會引發運行時classCastException .怎么來解決這個問題呢 ? 使用集合時,必須明確集合中元素的類型. 這種方式稱為"泛型" .
為了避免安全隱患, 1.5出現新的安全機制,保證程序的安全性 , 這就是泛型 .
~~~
ArrayList<String> arr = new ArrayList<String>(); //中括號的內容就是指定泛型
~~~
## 泛型中的好處
1. 將運行時期的ClassCastException,轉移到了編譯時期的編譯失敗.
2. 避免了類型強制轉換的麻煩.
~~~
public static void main(String[] args)
{
dome1();
dome2();
}
//不使用泛型
public static void dome1()
{
ArrayList names = new ArrayList();
names.add("鋼鐵俠");
names.add(123);
names.add(true);
for (Object o : names) {
System.out.println(((String) o).length()); //下面沒法操作了
}
}
//使用泛型
public static void dome2()
{
ArrayList<String> names = new ArrayList();
names.add("超人"); //如果傳入不是String類型就報錯了
names.add("鋼鐵俠");
names.add("蝙蝠俠");
for (String s : names) {
System.out.println(s.length());
}
}
~~~
## 泛型中E的含義
就是儲存類型的變量,等待接收一種數據類型.

## 泛型類
什么時候確定使用的類型呢?當創建該類對象的時候就可以確定了.
### 偽泛型
java中的泛型是偽泛型 , 是一種編譯手段 . 如下面這段代碼, 如果add的是String類型則編譯成功,如果不是String類型則編譯失敗 . 編譯成功后在class文件中是不存在泛型的 . 也就是說泛型只是在編譯時有泛型 , 編譯成功后是不存在 .
~~~
ArrayList<String> arr = new ArrayList<String>();
arr.add("")
~~~
### 使用泛型的好處
1. 將運行時期的ClassCastException轉移到了編譯期,變成了編譯失敗 .
2. 避免了類型強轉的麻煩 .
~~~
ArrayList<String> arr = new ArrayList<String>();
arr.add("123"); //當集合明確類型之后,存放不一致的類型就會編譯失敗
arr.add("456"); //集合已經明確存放的元素類型,那么在使用迭代器的時候,迭代器也同樣會知道具體遍歷元素類型
arr.add("789");
Iterator<String> it = arr.iterator(); //當使用Iterator<String>控制元素類型后,就不需要強轉了.獲取到的元素直接就是String類型
while(it.hasNext())
{
System.out.println(it.next());
}
~~~
### 泛型方法
~~~
public class GenericityDome<E>
{
E name;
public E getName()
{
return name;
}
public void setName(E n) //使用了類的泛型方法
{
this.name = n;
}
public <T> void show(T t) //泛型方法
{
System.out.println(t);
}
}
~~~
調用
~~~
GenericityDome<String> g = new GenericityDome<>();
g.show(1); //調用方法傳遞參數的時候才能確定類型.這個就是泛型方法
~~~
### 帶有泛型接口
泛型接口上的泛型到底什么時候確定?
1. 當子類實現接口的時候確定接口上的泛型.
2. 當子類實現接口的時候,還是不確定泛型,把接口的泛型繼續實現下來.
~~~
public interface GenericityDome<E>
{
public abstract void show(E e);
}
//子類實現接口的時候確定
class MyClass1 implements GenericityDome<String>
{
public void show(String s)
{
}
}
//當實現類創建對象的時候確定泛型
class MyClass2<Q> implements GenericityDome<Q>
{
public void show(Q s)
{
}
}
~~~
### 泛型通配符
? 代表任意類型
~~~
?
~~~
優點 : 各種類型的泛型都可以迭代 .
缺點 : 類型已經不確定了 .
所以這個方法只適合做遍歷 .
~~~
public class Test {
public static void main(String[] args)
{
ArrayList<Integer> arr = new ArrayList<Integer>();
arr.add(123);
arr.add(456);
HashSet<String> set = new HashSet<String>();
set.add("123");
set.add("456");
it(set);
}
public static void it(Collection<?> collection)
{
Iterator<?> coll = collection.iterator();
while(coll.hasNext()){
System.out.println(coll.next());
}
}
}
~~~
## 泛型通配符注意
泛型通配符是沒有意義單獨的,一般是組合使用.
~~~
<? extends Animal> //泛型必須是Animal或者Animal的子類
~~~
~~~
<? super Animal> //泛型必須是Animal或者Animal的父類
~~~
~~~
public static void main(String[] args)
{
ArrayList<String> names1 = new ArrayList<>();
names1.add("111");
names1.add("222");
names1.add("333");
ArrayList<String> names2 = new ArrayList<>();
names2.add("aaa");
names2.add("bbb");
names2.add("ccc");
names1.addAll(names2);
ArrayList<Integer> names3 = new ArrayList<>();
names3.add(111);
names3.add(222);
names3.add(333);
names1.addAll(names3); //這里是加不進去的,可以查看addAll()的源碼,它使用泛型通配符控制住了添加進去的類型.
}
~~~
- 環境
- Java基礎
- 數據類型
- 基本類型
- 引用類型
- Array
- Class
- ArrayList
- 流程控制
- ASCII碼表
- 面向對象
- 概述
- 變量
- this
- 修飾符
- 封裝
- 繼承
- final
- static
- 接口
- 接口
- 抽象類
- overload
- 接口和抽象類區別
- 案例
- 多態
- 構造方法
- super
- 匿名對象
- 內部類
- 靜態導入
- 包的聲明和訪問
- 代碼塊
- 代理設計模式
- 靜態代碼塊
- Object類
- lambda表達式
- 枚舉
- 定義枚舉
- 常用方法
- 枚舉常量
- 異常
- 可變參數
- Properties
- 概述
- Properties和持久化有關的方法
- 反射
- 類加載器
- 概述
- Class類
- 獲取構造方法并運行
- 獲取成員變量并改值
- 獲取成員方法并運行
- 反射泛型擦除
- 反射通過配置文件運行
- 常用 API
- Date類
- DateFormat類
- Calendar類
- Math類
- String類
- object類
- System類
- 正則表達式
- BigInteger類
- BigDecimal類
- Arrays工具類
- StringBuffer類
- 基本類型包裝類
- 自動裝箱和自動拆箱
- 框架集合
- collection接口
- 概述
- 接口方法
- 迭代器
- 迭代器并發異常
- 增強for循環
- 泛型
- hashCode和equals
- List接口
- 概述
- ArrayList
- LinkedList
- vector
- Set接口
- 概述
- 對象的哈希值
- HashSet
- LinkedHashSet
- 保證自定義元素的唯一性(重寫)
- ArrayList和HashSet的contains原理
- Map接口
- 概述
- Map集合常用方法
- 迭代Map
- Map存儲自定義類型
- HashMap
- LinkedHashMap
- Hashtable
- 嵌套Map遍歷
- 方法的可變參數
- collections工具類
- 集合嵌套
- 集合特點總結
- Collection集合工具類
- Arrays工具類
- File類
- 概述
- 獲取方法
- 創建和刪除
- 判斷方法
- 其他方法
- 文件過濾器
- IO流
- 字節流
- 概述
- 字節流
- 字節流復制文件
- 字節緩沖流
- 復制單級文件夾
- 使用字節流讀取中文的亂碼問題
- 字符編碼表
- 方便程序員的IO流
- 轉換流
- 概述
- OutputStreamWriter類
- InputStreamWriter類
- 轉換流和其他子類的區別
- 序列化流
- 概述
- 序列化接口以及版本號問題
- transient
- 打印流
- 多線程
- 概述
- main線程介紹
- 開啟線程方式一:Thread類
- 開啟線程方式二:Runnable類
- 線程的執行原理
- 使用哪種方式好
- 使用匿名內部類創建線程
- 線程安全
- ThreadLocal
- 網絡編程
- XML
- 概述
- 語法
- 元素標簽
- 屬性
- 轉義字符
- CDATA區
- XML約束
- DTD約束
- 三種引入DTD的方式
- DTD語法
- Schema約束
- JDBC
- 概述
- JDBC原理
- JDBC查詢操作
- JDBCUtils
- 預處理對象
- JDBC連接池
- 概述
- DBCP
- C3P0
- DBUtils操作
- ArrayHandler
- ArrayListHandler
- BeanHandler
- BeanListHandler
- ColumnListHandler
- MapHandler
- MapListHandler
- ScalarHandler
- 事務
- 事務概述
- 原生JDBC完成轉賬
- DBUtils完成轉賬
- 事務特性
- 三層思想
- 概述
- JavaWEB
- tomcat
- servlet
- 概述
- 映射servlet
- Servlet接口
- HttpServlet類
- load-on-startup
- servletContext
- ServletRequest
- ServletResponse
- Cooike&Session
- servlet三大域對象
- JSP
- 概述
- jsp內置對象
- 指令
- page
- include
- taglib
- JSP中的四個域對象
- jsp的一個動作標簽
- EL表達式
- 概述
- 獲取域中數據
- 執行運算
- el表達式中的內置對象
- jsti標簽
- 概念
- jstl分類
- Filter過濾器
- 概述
- 生命周期
- url-pattern配置
- filter的chain過濾鏈
- filter-mapping子標簽
- 全局統一錯誤頁面
- filterConfig
- 自動登錄實例
- 全局統一編碼
- Listener監聽器
- 概念
- 監聽器分類
- 監聽三個對象的創建和銷毀
- 監聽三個對象屬性的變化
- 監聽javabean在session中的狀態變化
- 定時器
- 概念
- calendar日歷
- 郵件
- 概述
- JSON
- 數據結構
- 堆棧結構
- 隊列結構
- 數組結構
- 鏈表結構
- 基礎加強
- 面試題:增強一個對象的方法有幾種方式?
- 裝飾者增強
- 動態代理
- 動態代理
- 動態代理細節
- 使用動態代理解決字符集編碼
- 注解
- 概述
- 擴展的自定義注解
- 類加載器
- 全盤負責托管機制
- 開發模式
- 問題
- lambda
- 函數式編程思想概述
- String字符串