在没学习泛型之前,在java的编程中,无论是类还是函数,它们的参数,成员变量的类型都是唯一确定的,即使对不同类型的数据进行相同的处理,也要定义多个函数去完成,这使得编程变得十分的复杂,因此,java引入了泛型的概念。
所谓泛型,就是不确定的类型,类似于C++中的模板,换句话说,泛型就相当于一个类型变量,只有在调用时才会确定泛型的具体类型
泛型有两种基本运用:泛型类和泛型方法
泛型类:当类中的一些成员的类型不确定时,就会用到泛型类
格式:1,定义时:class 类名<T>
2,调用时:类名<C(一个确定的类)> a=new 类名<C>();
举例:
//假设一个科学实验的结果有可能是数字(整形,浮点都有可能)也可能是字符串(比如一些结论)
import java.util.*;
class Science<T>//T就代表泛型,在类中用T定义的成员类型是根据调用结果决定的
{
private T ans;
public Science(T ans)//注意构造函数是没有<T>的
{
this.ans=ans;
}
public void getAns()
{
System.out.println(ans);
}
}
class GenericDemo
{
public static void main(String[] args)
{
Science<Integer> a=new Science<Integer>(1);//注意不能写int,只有Integer才是类
a.getAns();
Science<String> b=new Science<String>("haha");
b.getAns();
}
}
/*
结果是:1
haha
*/
当然,如果在一个类中只有那么一个函数的参数不能确定,那就没必要定义一个泛型类,可以直接把函数定义为泛型
举个例子:
import java.util.*;
class Tool
{
public <T> void show(T a)
{
System.out.println(a);
}
}
class GenericDemo
{
public static void main(String[] args)
{
Tool t=new Tool();
t.show(1.5);//实参决定T为double
t.show(1);//实参决定T为<span style="font-family: Arial, Helvetica, sans-serif;">int</span>
t.show('a');//实参决定T为char
t.show("abc123");//实参决定T为String
}
}
/*
结果:1.5
1
a
abc123
*/
在泛型类和泛型方法中也可以定义多个泛型
泛型类:
import java.util.*;
class Science<T1,T2>
{
private T1 ans1;
private T2 ans2;
public Science(T1 ans1,T2 ans2)
{
this.ans1=ans1;
this.ans2=ans2;
}
public void getAns()
{
System.out.println(ans1+""+ans2);
}
}
class GenericDemo
{
public static void main(String[] args)
{
Science<Integer,String> b=new Science<Integer,String>(123,"haha");
b.getAns();
}
}
/*
结果是:123haha
*/
泛型方法:
import java.util.*;
class Tool
{
public <T1,T2> void show(T1 a,T2 b)
{
System.out.println(a+""+b);
}
}
class GenericDemo
{
public static void main(String[] args)
{
Tool t=new Tool();
t.show(123,"hahah");
}
}
/*
结果:123hahah
*/
===============================================================================================================================
泛型的高级用法:
限制泛型类型:<T extends anyClass>
上限泛型的作用是:在调用时,泛型T只能变成anyClass或它的子类
举例:
import java.util.*;
class Person
{
private int age;
private String name;
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
public void show()
{
System.out.println(name+"..."+age);
}
}
class Student extends Person
{
public Student(String name,int age)
{
super(name,age);
}
}
class tool
{
public static <T extends Person> void show(T a)
{
a.show();
}
}
class GenericDemo
{
public static void main(String[] args)
{
tool t=new tool();
Person p=new Person("01",15);
Student s=new Student("02",20);
t.show(p);
t.show(s);
}
}
/*
结果是:01...15
02...20
*/
如果把tool类改为:
class tool
{
public static <T extends Student> void show(T a)
{
a.show();
}
}
会出错:
==================================================================================================
还要介绍一个小知识点,即使类型配符(?)
类型通配符的主要作用是在创建一个泛型类对象时(也就是说在初始化对象时使用,自定义类时按照正常进行)限制这个泛型类的类型实现或继承某个接口或类的子类,换句话说,也是用来限制范围的
具体格式:
上限泛型:
泛型类名称<? extends E> a=new 泛型类名称<D>()//D是E的子集
下限泛型:
泛型类名称<? super E> a=new 泛型类名称<D>()//D是E的父集
举例说明:
import java.util.*;
class Person
{
private int age;
private String name;
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
public void show()
{
System.out.println(name+"..."+age);
}
}
class Student extends Person
{
public Student(String name,int age)
{
super(name,age);
}
}
class tool<T>
{
public tool(T t)
{
if(!(t instanceof Person))
throw new RuntimeException();
Person p=(Person)t;//如果不强转,t是用不了show方法的,这也是泛型的弊端,不能直接使用类特有方法
p.show();
}
}
class GenericDemo
{
public static void main(String[] args)
{
tool<? extends Person> t1=new tool<Student>(new Student("01",15));
tool<? super Student> t2=new tool<Person>(new Person("02",20));
}
}
/*
结果是:01...15
02...20
*/
如果把第二个tool的初始化改为:tool<? super Person> t2=new tool<Student>(new Student("02",20));
结果:
虽然和限制泛型类型用法近似,但是不要弄混!!
================================================================================================================
泛型经常运用在集合中,在各种集合,以及比较器的定义中,都使用了泛型,因此,在使用集合的过程中如果出现由于数据类型而产生的错误,或者是由于类型差异而出现代码繁琐的现象,都应该先查阅API文档,尤其注意其泛型定义