泛型产生的意义
泛型是在JDK1.5之后增加的新功能,泛型Generice
- 泛型产生的意义,为了保证数据的安全性
- 泛型的基本使用,由外部指定其具体的操作类型
使用泛型类
为什么要使用泛型?有如下需求:
设计一个可以表示出坐标点的类,坐标又X和Y组成,坐标的表示方法有以下三种
- 整数表示: x=100,y=30
- 小数表示:x=10.5,y=10.5
- 字符串表示: x="东经180度", y = "北纬200度"
如何设计这个类?
我们要定义一个表示坐标点的类,根据描述的内容,我们需要在类中定义两个属性x,y。而这两个属性的取值,可以是数字,小数和字符串
泛型擦除
java中的泛型只在源代码中存在,在运行时,Java不会保留范型。
List<String> listStr = new ArrayList<>();
listStr.add("aaa");
listStr.add("xxx");
//泛型被擦除
List list = listStr;
list.add(100);
list.add(200);
为什么可以这么玩?因为Java的范型只存在于源码里,编译的时候给你静态地检查一下范型类型是否正确,而到了运行时就不检查了。上面这段代码在JRE(Java运行环境)看来和下面这段没区别:
List listStr = new ArrayList();
listStr.add(100);
listStr.add(200);
为什么要类型擦除?
为了向下兼容。
Java 5才引入了范型,在此之前都是没有范型的。当时引入范型只是为了解决遍历集合的时候总要手动强制转型的问题。
泛型通配符 ?
在程序开发中对象的引用传递是最常见的,但是如果方法参数是泛型类对象,则传入的泛型数据必须匹配才可以,否则是无法传递的。
public class Info<T>{
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
@Override
public String toString() {
return "Info [var=" + var + "]";
}
}
改为String类型的泛型之后,则可以传递参数
另外如果方法的参数没有指定泛型的时候,这种情况也可以传递参数。此时使用擦除泛型的特性。
另外一种接受泛型参数的方法是,使用?通配符设置泛型类型
public class Test {
public static void main(String[] args) {
Info<String> i=new Info<String>();
i.setVar("张无忌");
fun(i); }
public static void fun(Info<?> info){
System.out.println(info);
//使用通配符?可以接受任意泛型参数,但是此时泛型对象,不能修改数据
//info.setVar("aaa");
}
}
受限泛型
在引用传递的过程中,泛型操作也可以设置一个泛型对象的范围上限和范围下限,范围上限使用extends关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类,而范围下限使用super进行声明,表示参数化的类型可能是所指定的类型,或者此类型的父类型,直至Object类型。
设置泛型上限
public class Info<T> {
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
@Override
public String toString() {
return "Info [var=" + var + "]";
}
}
public class Test {
public static void main(String[] args) {
Info<Integer> ii=new Info<Integer>();
ii.setVar(100);
fun(ii);
Info<Double> id = new Info<Double>();
id.setVar(12.234);
fun(id);
}
//接受info对象,范围上限设置为Number,所以只能接受数字类型
public static void fun(Info<? extends Number> info){
System.out.println(info);
}
}
也可以直接在定义类的时候,设置好泛型范围
public class Info<T extends Number> {
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
@Override
public String toString() {
return "Info [var=" + var + "]";
}
}
设置泛型下限
当使用的泛型只能在本类及其父类类型上应用的时候,就必须使用泛型的范围下限配置。(不能在定义类的时候使用下限定义,只能用?方式定义)
public class Test {
public static void main(String[] args) {
Info<String> i1 = new Info<String>();
i1.setVar("张三");
fun(i1);
Info<Object> i2=new Info<Object>();
i2.setVar(100);
fun(i2);
}
public static void fun(Info<? super String> i){
System.out.println(i);
}
}
一个类的子类可以通过对象多态性,为其父类实例化。但是在泛型操作中,子类的泛型类型是无法使用父类的泛型类型接受,例如:Info<String>
不能使用Info<Object>
接受
泛型方法
针对某个方法设置泛型
public class Info2 {
//泛型方法,无返回值
public <T> void test(T val){
System.out.println(val);
}
//返回字符串的泛型方法
public <T> String test2(T val){
return val.toString();
}
//返回任意类型的泛型方法
public <T> T test3(T val){
return val;
}
}
public class Test2 {
public static void main(String[] args) {
Info2 i1 = new Info2();
i1.test("100");
i1.test(100);
String s1 = i1.test2("aaa");
String s2 = i1.test2(100);
System.out.println(s1);
System.out.println(s2);
int s3 = i1.test3(100);
String s4 = i1.test3("bbb");
System.out.println(s3); S
ystem.out.println(s4);
}
}