泛型:
1.方法的可变参数:数组
【在方法中使用 ... 表示可变参数】,可变参数必须放在方法参数最后一个,并且有且只有一个。
2.foreach循环
for(数据类型 临时变量 : 数组(集合)) {
// 循环次数为数组长度,而每一次循环都会顺序取出数组中的一个元素赋值给临时变量
}
3.静态导入(import)
import static 导入一个类的所有静态域(方法或属性)
使用导入类的静态域就像是在本类中定义的一样。
4.泛型:语法糖 类型守门员(编译时出错会拦截)
ClassCastException:在强转时,两个毫无关系的类产生的异常。
安全隐患;存在于强转。
泛型:在定义时类型不确定(任何类型),只有在具体使用时才确定具体类型。
泛型类:
class Myclass<T>{
private T t;
}
其中尖括号内的 T 表示类型参数,用于指代任意类型,不包括基本类型。
规范而言:一般使用单个的大写字母来表示类型参数。
引入泛型后,一个泛型类的类型在使用时已经确定好,因此无需向下转型。
泛型方法:
在方法声明上
class Myclass{
public static <T> void method(T t){
System.out.println("hehe!");
}
}
***泛型类中的类型参数与泛型方法中的类型参数是没有相应的联系的,泛型方法始终以自己定义的类型参数
为准,为了避免混淆,一般使用不同的类型参数来定义泛型类和泛型方法。
通配符:
问题:引入泛型后参数类型被确定,方法参数只能接收一种类型的泛型类。
eg:public static void fun(Myclass<String> myclass){}
1.?通配符。只能用在方法级别上,不能定义类,表示指代任意类型的泛型。
只能取得泛型对象中的值,无法通过类似setter方法设置值。
由于传入类型无法确定,所以无法设具体指到相应对象中。
eg:public static void fun(Myclass< ?> myclass){}//可以接收所有类型
2.?extens 类. 表示泛型上限,类与方法均可使用。
eg:规定上限父类是Number类
类:
class Myclass<T extends Number>{]
此时T必须是Number的子类,设定上限
方法:
public void fun (Myclass<?extends Number> myclass){}//规定上限父类是Number类
?指代任意类型,但是此时必须传入Number及其子类Myclass对象。
此时方法中依然不能设置值,只能取得值。只能确定父类,不能确定子类。此时发生向下转型存在不确定性,
因此不能设置具体指。
3.?super 类. 表示泛型下限,只能用在方法级别。
public void fun (Myclass<? super String> myclass){}
此时可以设置值,因为发生天然的向上转型
总结:
1.只有上限通配符可以用在泛型类的声明上,T extends Number,此时T必须是Number及其子类。
2.只有下限通配符能在方法总修改泛型对象的内容。(天然向上转型)
*泛型接口:
interface IMessage<T>{
public void print(T t);
}
子类在实现接口时有两种方法:
1.在实现接口时就确定好接口的类型;(普通类)
class MessageImpl implement IMessage<String>{
@override
public void print(String s){
}
}
2.子类在实现接口时仍然保留泛型。(泛型类)
class MessageImpl<T> implement IMessage<T>{
@override
public void print(T t){
}
}
5.类型擦除(向下兼容)
泛型只存在于编译阶段,进入JVM之前,与泛型相关的信息会被完全擦除。
在JVM看来,根本就不存在泛型的概念。
泛型类在进行类型擦除时,若未指定泛型的上限,泛型相关信息会被擦除为Object类型。否则,擦除
为相应的类型上限
class Myclass<T,E extends Number>{
public T t;
public E e;
}
T被擦除成Object;
E被擦除成Number;