原文请戳此处!!!
1. 普通泛型
class Point<T>{ //此处可以随便写标识符号,T只是Type的简称
private T var; // var的类型由T指定,也就是:由外部指定
public T getVar(){ //返回值得类型也是由外部决定的
return var;
}
public void setVar(T var){ //设置的类型也由外部决定
this.var = var;
}
}
public class GenericsDemo01{
public static void main(String args[]){
Point<String> p = new Point<String>(); //此处决定了类Point<T>里面的var类型为String类型
p.setVar("forfan06"); //设置字符串
System.out.println(p.getVar().length()); //此处分两步,一是取得字符串;二是获得字符串长度
}
}
-----------------------------------------------------------------------------------------------------------
class Notepad<K, V>{ //指定了两个泛型类型T和V,当然,此处的T和V可以换成其他字符。但是为了方便识别,一般取一个有意义单词的大写首字母
private K key; // 此处的T和V均是由外部决定的
private V value;
public K getKey(){
return this.key;
}
public V getValue(){
return this.value;
}
public void setKey(K key){
this.key = key;
}
public void setValue(V value){
this.value = value;
}
}
public class GenericsDemo02{
public static void main(String args[]){
Notepad<String, Integer> t = null; //定义了两个泛型类型的对象。
t = new Notepad<String, Integer>(); //里面的key和value分别为String和Integer类型。
t.setKey("饭饭"); //设置对象t的内容
t.setValue(20);
System.out.print("姓名:" + t.getKey()); //获取对象t的属性
System.out.println(", 年龄:" + t.getValue());
}
}
2. 通配符
class Info<T>{
private T var; //定义泛型变量,由外部决定
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){ //直接打印
return this.var.toString();
}
}
public class GenericsDemo03{
public static void main(String args[]){
Info<String> i = new Info<String>(); //使用String类型为泛型类型
i.setVar("forfan06");
fun(i);
}
public static void fun(Info<?> info){ //此处Info<?>里面没有明确指明泛型类型,说明可以接受任意的泛型对象。
System.out.println("内容是:" + info);
}
}
更好的验证通配符的作用:增加Info<Integer>如下代码:也可以正常运行!!!
class Info<T>{
private T var; //定义泛型变量,由外部决定
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){ //直接打印
return this.var.toString();
}
}
public class GenericsDemo03{
public static void main(String args[]){
Info<String> i = new Info<String>(); //使用String类型为泛型类型
i.setVar("forfan06");
fun(i);
Info<Integer> s = new Info<Integer>();
s.setVar(28);
fun(s);
}
public static void fun(Info<?> info){ //此处Info<?>里面没有明确指明泛型类型,说明可以接受任意的泛型对象。
System.out.println("内容是:" + info);
}
}
上面程序若修改为:
class Info<T>{
private T var; //定义泛型变量,由外部决定
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){ //直接打印
return this.var.toString();
}
}
public class GenericsDemo03{
public static void main(String args[]){
Info<String> i = new Info<String>(); //使用String类型为泛型类型
i.setVar("forfan06");
fun(i);
Info<Integer> s = new Info<Integer>();
s.setVar(28);
fun(s);
}
public static void fun(Info<T> info){ //此处Info<?>里面没有明确指明泛型类型,说明可以接受任意的泛型对象。
System.out.println("内容是:" + info);
}
}
则会出现编译错误!!!!!!!!!!!!
GenericsDemo03.java:22: error: cannot find symbol
public static void fun(Info info){
^
symbol: class T
location: class GenericsDemo03
1 error
编译错误
3. 受限泛型
上限:
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo04{
public static void main(String args[]){
Info<Integer> i1 = new Info<Integer>(); //声明Integer类的泛型对象
Info<Float> i2 = new Info<Float>(); //声明Float类的泛型对象
i1.setVar(27); //设置整数(小数), 自动装箱!!
i2.setVar(10.53f);
fun(i1);
fun(i2);
}
public static void fun(Info<? extends Number> temp){ //只能接受Number类及其子类的实例!!!!
System.out.print(temp + "、");
}
}
下限:
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo04{
public static void main(String args[]){
Info<String> i1 = new Info<String>();
Info<Object> i2 = new Info<Object>();
i1.setVar("forfan06");
i2.setVar(new Object());
fun(i1);
fun(i2);
}
public static void fun(Info<? super String> temp){ //只能接收String类或其父类(Object类)类型的泛型
System.out.print(temp + "、");
}
}
4. 泛型无法向上转型
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo05{
public static void main(String args[]){
Info<String> i1 = new Info<String>();
Info<Object> i2 = null;
i2 = i1; //此句会出错:error: incompatible types
}
}
运行得到错误:
GenericsDemo05.java:17: error: incompatible types
i2 = i1; //此句会出错:incompatible types
^
required: Info
found: Info
1 error
编译错误
- 此时Info<String> i1, Info<Object> i2中,i2已经不是i1的基类了!!!所以不存在向上转型这一说法!!!!!
5. 泛型接口
interface Info<T>{ //在接口中定义泛型
public T getVar(); //定义抽象方法,抽象方法的返回值就是泛型类型
}
class InfoImpl<T> implements Info<T>{ //定义泛型接口的子类
private T var;
public InfoImpl(T var){ //通过构造方法设置属性内容
this.var = var;
}
public T getVar(){
return this.var;
}
public void setVar(T var){
this.var = var;
}
}
public class GenericsDemo06{
public static void main(String args[]){
Info<String> i = null; //声明接口对象,泛型T此时为String类型
i = new InfoImpl<String>("forfan06"); //通过子类实例化对象
System.out.println("内容:" + i.getVar());
}
}
interface Info<T>{ //在接口中定义泛型
public T getVar(); //定义抽象方法,抽象方法的返回值就是泛型类型
}
class InfoImpl implements Info<String>{ //定义泛型接口的子类
private String var;
public InfoImpl(String var){ //通过构造方法设置属性内容
this.var = var;
}
public String getVar(){
return this.var;
}
public void setVar(String var){
this.var = var;
}
}
public class GenericsDemo06{
public static void main(String args[]){
Info i = null; //声明接口对象
i = new InfoImpl("forfan06"); //通过子类实例化对象
System.out.println("内容:" + i.getVar());
}
}
6. 泛型方法
声明格式:
[访问权限] <泛型标识> 泛型标识 方法名称([泛型标识 参数名称])
class Demo{
public <T> T fun(T t){ //可以接收任意类型的数据
return t; //直接把参数返回
}
}
public class GenericsDemo07{
public static void main(String args[]){
Demo d= new Demo();
String str = d.fun("forfan06");
int i = d.fun(28); //传递数字,自动装箱
System.out.println(str);
System.out.println(i);
}
}
7. 通过泛型方法返回泛型类型实例
class Info<T extends Number>{ //指定上限,只能是数字类型。(只能是Number类的子类)
private T var;
public T getVar(){
return this.var;
}
public void setVar(T var){
this.var = var;
}
public String toString(){ //覆写Object类中的toString()方法
return this.var.toString();
}
}
public class GenericsDemo08{
public static void main(String args[]){
Info<Integer> i = fun(30);
System.out.println(i.getVar());
}
public static <T extends Number> Info<T> fun(T param){ //方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定
Info<T> temp = new Info<T>(); //根据传入的数据类型实例化Info
temp.setVar(param); //将传递的内容设置到Info对象的var属性中
return temp; //返回实例化对象
}
}
8. 使用泛型统一传入的参数类型
class Info<T>{
private T var;
public T getVar(){
return this.var;
}
public void setVar(T var){
this.var = var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo09{
public static void main(String args[]){
Info<String> i1 = new Info<String>();
Info<String> i2 = new Info<String>();
i1.setVar("forfan06");
i2.setVar("你好!");
add(i1,i2);
}
public static <T> void add(Info<T> i1, Info<T> i2){
System.out.println(i1.getVar() + " " + i2.getVar());
}
}
9. 泛型数组
public class GenericsDemo10{
public static void main(String args[]){
Integer i[] = fun1(1, 2, 3, 4, 5, 6); //返回泛型数组
fun2(i);
}
public static <T> T[] fun1(T...arg){ //接收可变参数
return arg; //返回泛型数组
}
public static <T> void fun2(T param[]){ //输出
System.out.println("接收泛型数组:");
for(T t:param){
System.out.print(t + "、");
}
}
}
此时运行会得到以下警告:
GenericsDemo10.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
出现上面警告是因为用到了JAVA5.0的泛型,而5.0的泛型不做类型检查,例如ArrayList = a new ArrayList(); a.add("hello");这样会出现警告!解决方法有以下几种:
- 在方法的前面加上@SuppressWarnings("unchecked")
- 声明泛型类型,例如ArrayList<Object> a = new ArrayList<Object>();
- 使用1.4兼容JDK来编译, javac -source 1.4 Test.java
- 也可以查看警告信息,javac Xlint:unchecked Test.java。这样会显示详细的警告信息。
10. 泛型的嵌套设置
class Info<T, V>{
private T var;
private V value;
public Info(T var, V value){
this.setVar(var);
this.setValue(value);
}
public void setVar(T var){
this.var = var;
}
public void setValue(V value){
this.value = value;
}
public T getVar(){
return this.var;
}
public V getValue(){
return this.value;
}
}
class Demo<S>{
private S info;
public Demo(S info){
this.setInfo(info);
}
public void setInfo(S info){
this.info = info;
}
public S getInfo(){
return this.info;
}
}
public class GenericsDemo11{
public static void main(String args[]){
Demo<Info<String, Integer>> d = null; //将Info作为Demo的泛型类型
Info<String, Integer> i = null; //Info指定两个泛型类型
i = new Info<String, Integer>("forfan06", 30); //实例化Info对象
d = new Demo<Info<String, Integer>>(i); //在Demo类中设置Info类的对象
System.out.println("内容一:" + d.getInfo().getVar());
System.out.println("内容二:" + d.getInfo().getValue());
}
}
泛型方法不一定要通过参数来确定泛型准确类型,可以只通过返回值,比如:
public static <E> ArrayList<E> new ArrayList(){
return new ArrayList<E>();
}
public List<PrepaidHistory> queryHistories(Long skyid, PrepaidHistoryType type, Date from, Date end){
...
return Lists.newArrayList();
}
这样Lists.newArrayList();
智能的知道返回类型为PrepaidHistory