声明:该文章是在网上查找相关资料后,并站在自己的角度重新梳理的,有些内容以及代码是摘抄的,有些是自己总结编写的,主要的目的是为了自己学习,同时也希望我的整理可以帮助其他对Java 泛型有疑惑的朋友,在此感谢给我提供帮助的前辈们,还请多多指教~
Java 泛型的概念
泛型 即“参数化类型”,顾名思义就是将原来具体类型参数化,在使用和调用的时候传入具体的类型。T、E、K、V都是泛型参数,一般都是单个大写字母,很少用小写,用于区分多个泛型化参数。在Java中泛型只在编译阶段存在,在生成个的Class文件不存在泛型
注意:关于泛型化参数大写字母并没有限定,不一定是上文中的四个,可以任意指定。 |
泛型的作用
1. 在引入范型之前,要在类中的方法支持多个数据类型,就需要对方法进行重载,在引入范型后,可以解决此问题(多态),更进一步可以定义多个参数以及返回值之间的关系。
2. 明确当前类所操作的类型的具体类型,对于list等集合类型的参数进行明确化定义。在泛型出现之前,所有集合都是采用Object类型作为参数类型的。这样就避免了在具体使用的时候出现类型转化错误的情况
3. 其他作用还有待发现。。。
泛型的定义
泛型类
package com.sxd.generics.demo; /** * 普通的泛型, * */ class Common<Textends String>{ private T var;
public Common(Tvar){ this.var =var;
}
public T getVar() { return var; }
public void setVar(T var) { this.var =var; }
}
class Student<K,V>{ private K name;
private V value;
public Student(Kk,V v){ this.name =k; this.value =v; }
public K getName() { return name; }
public void setName(K name) { this.name =name; }
public V getValue() { return value; }
public void setValue(V value) { this.value =value; } } public class GenericsDemo4 {
public static void main(String[] args) { Student<String,String> student =new Student<String,String>("姓名","张三"); System.out.println(student.getName()+":"+student.getValue()); } } |
泛型接口
package com.sxd.generics.demo; /** * 定义泛型接口 * */ interface Info<T>{ public T getVar(); }
class InfoImpl<T>implements Info<T>{
private T var;
public InfoImpl(Tvar){ this.var =var; }
public void setVar(T var){ this.var =var; }
@Override public T getVar() { return var; }
}
class InfoImpl2implements Info<Integer>{
private Integervar;
public InfoImpl2(Integervar){ this.var =var; }
public void setVar(Integer var){ this.var =var; }
@Override public Integer getVar() { return var; }
}
public class GenericsDemo1 { public static void main(String[] args) { Info<String> info1 = new InfoImpl<String>("sxd"); printInfo(info1);
Info info2 = new InfoImpl2(123); printInfo(info2); }
public static void printInfo(Info<?> info){ System.out.println(info.getVar()); }
/** 通配符上限即所有Number类型以及子类*/ public static void printInfo1(Info<? extends Number> info){ System.out.println(info.getVar()); }
/**通配符下限即只能是String或者Object类型,下限的作用在哪里呢,直接放String类型就不可以了吗*/ public static void printInfo2(Info<? super String> info){ System.out.println(info.getVar()); }
/** 泛型的范围*/ public static <T extends Number> Info<T> func(Tparam){ Info<T> info = new InfoImpl<T>(param); return info; }
} |
泛型方法
package com.sxd.generics.demo; /** * 定义泛型方法 * * */ class Demo{ //告诉编译器泛型的名称是T,所以在定义泛型方法的时候,必须有<T> public <T> T fun(Tt){ return t; } }
public class GenericsDemo2 { public static void main(String[] args) { Demo demo = new Demo(); String str = demo.fun("sxd"); int i = demo.fun(1235); System.out.println(str +i); } } |
泛型数组
package com.sxd.generics.demo; /** * 泛型数组 * */ public class GenericsDemo3 {
//定义泛型数组不能采用New的方式,这种方式比较简洁 public static <T> T[] func1(T...arg){ return arg; } /** * 接收泛型数组,并且打印泛型数组中的内容 * */ public static <T> void func2(Tparam[]){ System.out.println("接收泛型数组"); for(T t : param){ System.out.println(t); } }
public static void main(String[] args) { //回顾一下数组的定义方式 //静态数组 String[] s = new String[10]; String a[] = new String [15];
String b[] = {"a","b","c"}; String[] b1 = {"a","b","c"};
Integer i[] = func1(1,2,3,4,5,6); func2(i); } } |
类型通配符 ?的使用
类型通配符一般代替具体的实参,例如Box<?> 在可以认为是Box<Integer>,Box<String>等所有Box<具体类型参数的>父类
类型通配符上限
说明类型只能是Number类型的子类
Public static void function(info <? extends Number> temp){ System.out.println(“内容”+ temp); } |
类型通配符下限
说明所有类型值Double的父类即以上类型,例如Number类型和Object类型
Public static void function(info <? super Double> temp){ System.out.println(“内容”+ temp); } |
高级应用
多接口限制
<T extends somclass & interface & interface2 & interfaces3> 要求改泛型需要继承superCLass并实现多个接口才可以 |
泛型限制
<T extends SuperClass> 表示该泛型必须继承该superClass才可以 |
泛型类无父子
在泛型中,泛型之间继承关系,并不会影响泛型类之间的继承关系,泛型的通用表示就是通配符了
package com.sxd.generics; /** * 定义人类 * */ public class Person{
/** 姓名*/ private Stringname;
/** 年龄*/ private int age;
/** 家庭住址*/ private Stringaddress;
/** 联系电话*/ private Stringphone;
public String getName() { return name; }
public void setName(String name) { this.name =name; }
public int getAge() { return age; }
public void setAge(intage) { this.age =age; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address =address; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone =phone; }
@Override public String toString() { return "Person [name=" + name + ", age=" + age + ", address=" + address + ", phone=" + phone +"]"; }
} //编写women类,继承Person类 package com.sxd.generics;
public class Women extends Person{
/** 性别*/ private Stringsex;
public String getSex() { return sex; }
public void setSex(String sex) { this.sex =sex; }
@Override public String toString() { return "Women [getSex()=" + getSex() + ", getName()=" + getName() +", getAge()=" + getAge() + ", getAddress()=" + getAddress() + ", getPhone()=" + getPhone() +"]"; }
} //我们看看结果 package com.sxd.generics; import java.util.ArrayList; import java.util.List; /** * Java 中泛型的定义和测试 * */ public class GenericsTest { public static void main(String[] args) {
Person person = new Person(); person.setName("张三"); person.setAge(18); person.setPhone("15658725126"); person.setAddress("南京东路");
Women women = new Women(); women.setName("张女士"); women.setAge(28); women.setPhone("15654065126"); women.setAddress("南京东路"); women.setSex("女");
//如果你想对集合的类型进行限定,即只有Person类型或者是Person的子类 List<Person> persons = new ArrayList<Person>();
List<Women> womens = new ArrayList<Women>(); /* * 这行是报错的,在这里List<Person> 与List<Women> * 不会因为Person和women的关系而变成父子关系,对于List而言, * 这里只是两个存放着两个不同的类型的集合。 * */ List<Person> persons1= womens;
}
} |