为什么要用泛型?
在java集合中储存数据会被当做Object类型来存储,可能有些类型会失去原本的特性,所以可以用泛型来统一集合当中的存储类型。
class Test3 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("1212");
list.add(121);
List<String> lists = new ArrayList<String>();
lists.add("2121");
//lists.add(2121); //报错
}
}
在我看来泛型就是一个辅助我们编译的东西,在很多复杂类型中可以使用泛型来解决。
泛型不止可以用作集合上,还能用作在参数、方法、类等…
利用泛型还可以解决ClassCastException问题.
class CeShi4<T> { //T属于类型标记,可以设置多个
//T返回的是什么数据类型,下面属性就是什么数据类型
private T x; //x轴坐标
private T y; //y轴坐标
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
class Test3 {
public static void main(String[] args) {
//实例化CeShi4对象,设置"T"数据类型
CeShi4<Integer> ceShi4 = new CeShi4<Integer>();
ceShi4.setX(10);
ceShi4.setY(20);
int x = ceShi4.getX();
int y = ceShi4.getY();
System.out.println("x轴坐标:"+x+",y轴坐标:"+y);
}
}
输出结果:
x轴坐标:10,y轴坐标:20
例子:
Number[] nums = new Integer[10]; // OK
因为Integer是Number的子类,一个Integer对象也是一个Number对象,所以一个Integer的数组也是一个Number的数组,这就是数组的协变。
java数组的协变是有一定的缺陷的,就算是把Integer[]赋给Number[],但是数组元素类型还是Integer,智能放入Integer子类或者Integer对象。如果放入Number子类或者Number对象,那么在运行的时候JVM能够知道数组元素的类型是Integer,所以会报java.lang.ArrayStoreException错误
那么我们可以使用泛型的通配符来解决这种问题
向上转型:
List<? extends Number> nums = new ArrayList<Integer>(); // OK
当你不知道泛型返回的是什么类型可以用>
class Test3 {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("121");
list1.add("222");
show(list1);
}
public static void show(List<?> c){ //当你不知道泛型是什么类型时用?
for (Object object : c) {
System.out.println(object);
}
}
}
121
222
List>和List的区别
< ? extends E>:接收E类型或者E的子类型对象
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student extends Person{
public Student(String name, int age) {
super(name, age);
}
}
class Test3 {
public static void main(String[] args) {
List<Person> list1 = new ArrayList<Person>();
list1.add(new Person("sss", 12));
List<Student> list2 = new ArrayList<Student>();
list2.add(new Student("ccc",13));
show(list1);
show(list2);
}
public static void show(List<? extends Person> c){ //当你不知道泛型是什么类型时用?
Iterator<? extends Person> it = c.iterator();
while(it.hasNext()){
Person p = it.next();
System.out.println("姓名:"+p.getName()+",年龄:"+p.getAge());
}
}
}
输出结果
姓名:sss,年龄:12
姓名:ccc,年龄:13
< ? super E >:接收E类型或者E的父类型
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student extends Person{
public Student(String name, int age) {
super(name, age);
}
}
class Test3 {
public static void main(String[] args) {
List<Person> list1 = new ArrayList<Person>();
list1.add(new Person("sss", 12));
List<Student> list2 = new ArrayList<Student>();
list2.add(new Student("ccc",13));
show(list1);
show(list2);
}
public static void show(List<? super Student> c){ //当你不知道泛型是什么类型时用?
Iterator<? super Student> it = c.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
输出结果
main.Person@15db9742
main.Student@6d06d69c
例子:
//泛型接口
interface Person<T>{
public void show(T t);
}
//子类继承泛型接口
class Student<Q> implements Person<Q>{
@Override
public void show(Q q) {
// TODO Auto-generated method stub
System.out.println("show:"+q);
}
}
class Test3 {
public static void main(String[] args) {
Person<Integer> p = new Student<Integer>();
p.show(2222);
}
}
输出结果
show:2222
例子:
class Person{
//泛型方法
public <T> void show(T t){
System.out.println(t);
}
public <U,T> void show(U u,T t){
System.out.println(u);
System.out.println(t);
}
}
class Test3 {
public static void main(String[] args) {
Person person = new Person();
person.show("sb");
person.show(123, "小红");
}
}
输出结果:
sb
123
小红