":()V
+ 16: athrow
+ 17: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
+ 20: iload_1
+ 21: iload_2
+ 22: iadd
+ 23: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
+ 26: goto 46
+ 29: astore_1
+ 30: aload_1
+ 31: athrow
+ 32: astore_1
+ 33: getstatic #8 // Field log:Lorg/slf4j/Logger;
+ 36: ldc#9 // String
+ 38: aload_1
+ 39: invokeinterface #10, 3 // InterfaceMethod org/slf4j/Logger.error:(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 44: aload_1
+ 45: athrow
+ 46: return
+ Exception table:
+ from to target type
+0 26 29 Class java/lang/IndexOutOfBoundsException
+0 26 32 Class java/lang/Exception
+
+```
+
+流程:
+1. 偏移9: new一个RuntimeException对象
+1. 12: dup 复制上诉对象到栈顶
+1. 13: invokespecial 调用异常类构造器
+1. 16: athrow
+ - 这个指令运作过程大致是首先检查操作栈顶,这时栈顶必须存在一个reference类型的值,并且是java.lang.Throwable的子类(虚拟机规范中要求如果遇到null则当作NPE异常使用)
+ - 然后暂时先把这个引用出栈,接着搜索本方法的异常表(Exception table)找一下本方法中是否有能处理这个异常的handler
+ - 如果能找到合适的handler就会重新初始化PC寄存器指针指向此异常handler的第一个指令的偏移地址。接着把当前栈帧的操作栈清空,再把刚刚出栈的引用重新入栈。
+ - 如果在当前方法中找不到handler,那只好把当前方法的栈帧出栈(这个栈是VM栈,不要和前面的操作栈搞混了,栈帧出栈就意味着当前方法退出)
+ - 这个方法的调用者的栈帧就自然在这条线程VM栈的栈顶了,然后再对这个新的当前方法再做一次刚才做过的异常handler搜索
+ - 如果还是找不到,继续把这个栈帧踢掉,这样一直到找
+ - 要么找到一个能使用的handler,转到这个handler的第一条指令开始继续执行。
+ - 要么把VM栈的栈帧抛光了都没有找到期望的handler,这样的话这条线程就只好被迫终止、退出了 `线程可设置默认handler setDefaultUncaughtExceptionHandler`。
+
+Exception table: 异常匹配的表格 如果`from` 和 `to` 之间匹配到 `type`的异常抛出,就转到 `target` 处执行代码
+
+
+
diff --git a/Java/AdvancedLearning/Generics.md b/Java/AdvancedLearning/JavaGenerics.md
similarity index 57%
rename from Java/AdvancedLearning/Generics.md
rename to Java/AdvancedLearning/JavaGenerics.md
index a9c7232..ad707b5 100644
--- a/Java/AdvancedLearning/Generics.md
+++ b/Java/AdvancedLearning/JavaGenerics.md
@@ -1,47 +1,91 @@
-`目录 start`
-
-- [泛型](#泛型)
- - [入门](#入门)
- - [简单使用](#简单使用)
- - [类型擦除](#类型擦除)
- - [约束和局限性](#约束和局限性)
- - [泛型类型的继承规则](#泛型类型的继承规则)
- - [通配符类型](#通配符类型)
- - [子类型限定的通配符 extends](#子类型限定的通配符-extends)
- - [超类型限定的通配符 super](#超类型限定的通配符-super)
- - [应用](#应用)
- - [无限定通配符](#无限定通配符)
- - [通配符捕获](#通配符捕获)
- - [反射和泛型](#反射和泛型)
-
-`目录 end` |_2018-08-04_| [码云](https://gitee.com/gin9) | [CSDN](http://blog.csdn.net/kcp606) | [OSChina](https://my.oschina.net/kcp1104) | [cnblogs](http://www.cnblogs.com/kuangcp)
+---
+title: Java泛型
+date: 2018-11-21 10:56:52
+tags:
+ - 泛型
+categories:
+ - Java
+---
+
+💠
+
+- 1. [泛型](#泛型)
+ - 1.1. [简单使用](#简单使用)
+ - 1.2. [类型擦除](#类型擦除)
+ - 1.3. [约束和局限性](#约束和局限性)
+ - 1.4. [泛型类型的继承规则](#泛型类型的继承规则)
+ - 1.5. [通配符类型](#通配符类型)
+ - 1.5.1. [子类 类型限定的通配符 extends](#子类-类型限定的通配符-extends)
+ - 1.5.2. [基类 类型限定的通配符 super](#基类-类型限定的通配符-super)
+ - 1.5.3. [无限定通配符](#无限定通配符)
+ - 1.5.4. [通配符捕获](#通配符捕获)
+ - 1.6. [反射和泛型](#反射和泛型)
+
+💠 2024-07-10 00:40:24
****************************************
# 泛型
-> [开始学习的兴趣来源](https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665514015&idx=1&sn=12409f705c6d266e4cd062e78ce50be0&chksm=80d67c5cb7a1f54a68ed83580b63b4acded0df525bb046166db2c00623a6bba0de3c5ad71884&scene=21#wechat_redirect)
+> [Generics](https://docs.oracle.com/javase/tutorial/java/generics/index.html)
-[参考博客: Java总结篇系列:Java泛型](http://www.cnblogs.com/lwbqqyumidi/p/3837629.html)
+> 泛型程序设计划分为三个熟练级别 基本级别就是仅仅使用泛型类,典型的是像ArrayList这样的集合--不必考虑他们的工作方式和原因,大多数人会停留在这个级别.直到出现了什么问题. 当把不同的泛型类混合在一起的时候,或是对类型参数一无所知的遗留代码进行对接时,可能会看到含糊不清的错误消息.如果这样的话,就需要系统的进行学习Java泛型来系统地解决问题.
+> 泛型类可以看作普通类的工厂 -- Java核心技术卷 2004(1.5)
+
+***************
+
+> [开始学习的兴趣来源 Java帝国之泛型 ](https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665514015&idx=1&sn=12409f705c6d266e4cd062e78ce50be0&chksm=80d67c5cb7a1f54a68ed83580b63b4acded0df525bb046166db2c00623a6bba0de3c5ad71884&scene=21#wechat_redirect)
+
+[参考: Java总结篇系列:Java泛型](http://www.cnblogs.com/lwbqqyumidi/p/3837629.html)
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。
那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
-[参考博客: Java深度历险(五)——Java泛型](http://www.infoq.com/cn/articles/cf-java-generics)
-## 入门
->泛型程序设计划分为三个熟练级别 基本级别就是仅仅使用泛型类,典型的是像ArrayList这样的集合--不必考虑他们的工作方式和原因,大多数人会停留在这个级别.直到出现了什么问题. 当把不同的泛型类混合在一起的时候,或是对类型参数一无所知的遗留代码进行对接时,可能会看到含糊不清的错误消息.如果这样的话,就需要系统的进行学习Java泛型来系统地解决问题.
-> 泛型类可以看作普通类的工厂 -- Java核心技术卷 2004(1.5)
+[参考: Java深度历险(五)——Java泛型](http://www.infoq.com/cn/articles/cf-java-generics)
-### 简单使用
+## 简单使用
>- [简单泛型类示例](https://github.com/Kuangcp/JavaBase/blob/master/src/main/java/com/generic/simple/Pair.java)
例如该行定义 : `public abstract class RoomCache, R extends RoomBO> extends AbstractCache {}`
-
- 类型变量使用大写的一个字母这是代表:
- `E` 集合的元素类型
- `K V` 表示表的关键字和值的类型
- `T U S` 等就表示任意类型
-
-#### 类型擦除
-- 不同于C++的泛型,C++是将模板类组合出来的生成一个新的类,Java则是进行类型擦除,然后再类型强转
+```Java
+ // 根据Class对象 获取泛型的类型信息
+ Type superClass = getClass().getGenericSuperclass();
+ type = ((ParameterizedType) superClass).getActualTypeArguments()[1];
+```
+
+> [参考: 使用通配符简化泛型使用](https://www.ibm.com/developerworks/cn/java/j-jtp04298.html)
+
+- 场景1:`public static > T min(T[] list);`
+ - 限定了入参和返回值是 是实现了Comparable接口的某个类型 因为Comparable也是一个泛型类, 所以也进行限定类型
+ - 这样的写法要比 T extends Comparable 更为彻底
+ - 例如计算一个String数组的最小值 T 就是 String类型的, String是Comparable的子类型
+ - 但是当处理GregorianCalendar, GregorianCalendar是Calendar的子类, 并且Calendar实现了`Comparable`
+ - 因此GregorianCalendar实现的是`Comparable`, 而不是Comparable
+ - 这种情况下 `public static > T min(T[] list)` 就是安全的
+
+- 场景2: `public static List importExcel(Class target)`
+ - 该方法实现了, 传入继承了ExcelTransform接口的类对象, 得到该类的List集合
+ - ` boolean` 这样写编译没报错, 那么就是说, 就是一个泛型的定义, 后面进行引用, 省的重复写
+ - 简单的写法就是 `public static List importExcel(Class target)`
+
+- 场景3: Spring4.x 添加的泛型依赖注入 , 使用的JPA就是依赖该技术 [spring学习笔记(14)——泛型依赖注入](http://blog.csdn.net/u010837612/article/details/45582043)
+
+- 场景4: 泛型嵌套以及传递问题 [实际代码](https://github.com/Kuangcp/JavaBase/tree/generic/src/main/java/com/github/kuangcp/nesting)
+ - 本来的设想是只要声明了具有泛型约束的类, 就应该不用再声明该类中的泛型类型, 但是由于Java的泛型只是在编译前存在, 编译后就被擦除了, 所以没法做到这样简洁的约束
+
+> 对于应用程序员, 可能很快的学会掩盖这些声明, 想当然地认为库程序员做的都是正确的, 如果是一名库程序员, 一定要习惯于通配符
+> 否则还要用户在代码中随意地添加强制类型转换直至可以通过编译.
+
+super 只能用于通配符
+
+*********************
+
+## 类型擦除
+- 不同于C++的泛型,C++是将模板类组合出来生成一个新的类,Java则是进行类型擦除,然后再类型强转
+
- 例如 `public static T min (T[] list)`
- - 擦除后就只剩下一个方法 `public static Comparable min(Comparable[] list)`
+ - 擦除后 `public static Comparable min(Comparable[] list)`
- [泛型类擦除示例](https://github.com/Kuangcp/JavaBase/blob/master/src/main/java/com/generic/simple/DateInterval.java)
- 例如该方法签名 `public static T getMax(T[]list)`
@@ -50,99 +94,116 @@
> 在Java的继承中,可以根据需要拥有多个接口超类型,但限定中至多只有一个类,如果用一个类作为限定,他必须是限定列表中的第一个
+注意:泛型记录在类字节码中的 Signature LocalVariableTypeTable 属性上, [参考: Java泛型-4(类型擦除后如何获取泛型参数)](https://www.jianshu.com/p/cb8ff202797c)
+
******************************
-### 约束和局限性
+## 约束和局限性
> 以下代码示例:涉及的类Pair在上述的代码中已经定义, Human和Student是继承关系
-> 并且因为看的 Java核心技术卷 比较老 jdk是1.5的所以没有用7的菱形语法简化泛型 7可以省去右边的类型: `Pair pair = new Pair<>();`
-- | _不能使用基本类型实例化类型参数_
- - 也就是说没有`Pair`只有`Pair`
+- _不能使用基本类型 实例化类型参数_
+ - 也就是说没有 `Pair` 只有 `Pair`
- 因为类型擦除后,类型是Object并不能放double的值, 但是这样做与Java语言中基本类型的独立状态相一致.
- - 当包装器类型(wrapper type)不能接受替换时,可以使用独立的类和方法处理他们
-- | _运行时类型查询(eq或者instanceof)只适用于原始类型_
- - 比如`Pair` 和`Pair`是等价的,因为类型擦除
- - `Pair pair1` `Pair pair2` pair1.getClass()和pair2.getClass()是等价的都是返回Pair.class
-- | _不能抛出也不能捕获泛型类实例_
+ - *但是* 可以使用 原始类型数组 例如 `byte[]`
+ - [valhalla项目正计划支持原始类型](http://openjdk.java.net/projects/valhalla/)
+
+- _运行时类型查询(eq或者instanceof)只适用于原始类型_
+ - 比如 `Pair` 和 `Pair` 是等价的,因为类型擦除
+ - `Pair pair1 和 Pair pair2` pair1.getClass() 和 pair2.getClass() 是等价的都是返回Pair.class
+
+- _不能抛出也不能捕获泛型类实例_
- 错误的示例:
- `public class Problem extends Exception{}`
- `public static void doWork(){try{}catch(T t){}}`
- 正确示例:
- 在异常声明中使用类型变量
- `public static void doWork() throws T{.. catch(){throw t;}}`
-- | _参数化类型的数组不合法_
- - 例:`Pair[] list = new Pair[10];`
- - 因为擦除后 list是Pair[]类型,然后就能转成Object[], 就失去了泛型的作用
- - 如果要使用的话最好直接使用集合 ArrayList:` ArrayList>`,安全又高效
-```java
- Object[] array = list;
- array[0] = "hi";// 编译错误
- array[0] = new Pair(); //通过数组存储的检测,但实际上类型错误了,所以禁止使用参数化类型的数组
-```
-- | _不能实例化类型变量(T)_
+- _参数化类型的数组不合法_
+ - 例:`Pair[] list = new Pair[10];`
+ - 因为擦除后 list是 `Pair[]` 类型, 能转成 `Object[]` 这样就失去了泛型的作用
+ - 如果要使用的话最好直接使用集合 ArrayList:` ArrayList>` 安全又高效
+ ```java
+ Object[] array = list;
+ array[0] = "hi";// 编译错误
+ array[0] = new Pair(); //通过数组存储的检测,但实际上类型错误了,所以禁止使用参数化类型的数组
+ ```
+
+- _不能实例化类型变量(T)以及数组_
- 非法 `new T(){}`
-```java
- public Pair(){
- first = new T();
- second = new T();
- }
- first = T.class.newInstance() //非法 T.class是不合法的
- //要实例化一个Pair的对象就要如下:
- public static Pair initPair(Class c){
- try{
- return new Pair(c.newInstance(), c.newInstance());
- }catch (Exception e){
- return null;
+ ```java
+ public Pair(){
+ first = new T();
+ second = new T();
}
- }
- // 如下调用
- Pair pair = Pair.initPair(String.class);
- // 因为Class本身是泛型, String.class其实是Class的实例
- // 也不能实例化为一个数组 new T[5]
-```
-- | _泛型类的静态上下文中类型变量无效_
+
+ //非法 T.class是不合法的
+ first = T.class.newInstance()
+
+ //要实例化一个Pair的对象就要如下:
+ public static Pair initPair(Class c){
+ try{
+ return new Pair(c.newInstance(), c.newInstance());
+ }catch (Exception e){
+ return null;
+ }
+ }
+ // 如下调用
+ Pair pair = Pair.initPair(String.class);
+ // 因为Class本身是泛型, String.class其实是Class的实例
+ // 也不能实例化为一个数组 new T[5]
+ ```
+
+- _泛型类的静态上下文中类型变量无效_
- 不能在静态域中使用类型变量 如下:
- 如果这段代码能执行,那就可以声明一个 Singleton 共享随机数生成类,
- 但是声明之后,类型擦除,就只剩下了Singleton类,并不能做对应的事情,所以禁止这样的写法
-```java
- private static T first; // 错误
- public static T getFirst(){ // 错误
- return first;
- }
-```
-- | _注意泛型擦除后的冲突_
+ ```java
+ private static T first; // 错误
+ public static T getFirst(){ // 错误
+ return first;
+ }
+ ```
+
+- _注意泛型擦除后的冲突_
- 当类型擦除时,不能创建引发冲突的相关条件
- 例如 新实现一个类型变量约束的equals方法就会和Object原方法冲突 补救方法就是重命名该方法了
-
-```java
- public class Pair{
- public boolean equals (T value){
- return ..
+ ```java
+ public class Pair{
+ public boolean equals (T value){
+ return ..
+ }
}
- }
-```
+ ```
+
`泛型规范说明`
- 要想支持擦除的转换,就需要强行限制一个类或类型变量不能同时成为两个接口类型的子类,而这两个接口是同一接口的不同参数化
- 以下代码就是非法的, GregorianCalendar 实现了两个接口,两个接口是Comparable接口的不同参数化,这是不允许的
-```java
- class Calendar implements Comparable{}
- class GregorianCalendar extends Calendar implements Comparable{} // 错误
-```
-- 但是如下又是合法的
-```java
- class Calendar implements Comparable{}
- class GregorianCalendar extends Calendar implements Comparable{}
-```
-- 很有可能是桥方法有关,不可能有两个一样的桥方法(因为两个接口其实是一个接口的不同参数化,桥方法的方法签名是一致的)
+ ```java
+ class Calendar implements Comparable{}
+ class GregorianCalendar extends Calendar implements Comparable{} // 错误
+ ```
+ - 但是如下又是合法的
+ ```java
+ class Calendar implements Comparable{}
+ class GregorianCalendar extends Calendar implements Comparable{}
+ ```
+ - 很有可能是桥方法有关,不可能有两个一样的桥方法(因为两个接口其实是一个接口的不同参数化,桥方法的方法签名是一致的)
+
+> Tips
+- Stream Optional结合泛型出现的极端问题 [JDK bugs:嵌套泛型](https://bugs.openjdk.org/browse/JDK-8313448)
+- [Stream bug](https://github.com/Kuangcp/JavaBase/blob/master/java8/src/test/java/com/github/kuangcp/stream/bug/StreamGenericTest.java)
+- [Lambda 多继承bug](https://github.com/Kuangcp/JavaBase/blob/master/java8/src/test/java/com/github/kuangcp/lambda/bug/MultipleExtendsTest.java)
*******************************************
-### 泛型类型的继承规则
+
+## 泛型类型的继承规则
> 例如 父子类: Human Student 那么 Pair Pair 是继承(inherit)关系么,答案是否定的!!
```java
Pair humans = new Pair(man, woman);
Pair classmates = humans;// illegal, but suppose it wasn't
+
classmates.setSecond(junior) // 如果上面合法,那么这里是肯定可以执行的, 因为泛型类型变成了Student
//那么就有了问题了,原有的人类类型限制的对象中,出现了小学生
//所以不允许这样的类型变量约束的类进行多态
@@ -152,6 +213,7 @@
Student[] students = humans;
students[0] = junior ;// 虚拟机将抛出 ArrayStoreException 异常
```
+> 为何 `List