java泛型

来源:互联网 发布:我的世界0.15.4枪械js 编辑:程序博客网 时间:2024/06/06 21:39

今天给大家介绍下java泛型


泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。下面我写一段代码来演示下这个隐患。
package com.generic;public class ReturnObject {private Object o;public ReturnObject(Object o) {this.o = o;}public Object get() {return o;}public static void main(String[] args) {String a = "example";ReturnObject re = new ReturnObject(a);// 将返回值强制转换成Double类型,编译时不会报错,执行时才会报错Double b = (Double) re.get();}}

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
下面我们用泛型改写一下上面那个类
package com.generic;//声明类的时候加上泛型标识<T>,表示此类的中类型T可以作为参数指定public class ReturnObject1<T> {// 类型T由外部参数指定private T o;public ReturnObject1(T o) {this.o = o;}public T get() {return o;}public static void main(String[] args) {String a = "example";// 定义时指定T的类型为StringReturnObject1<String> re = new ReturnObject1<String>(a);// 这样我们就不用进行强制转换了String b = re.get();// 下面这句代码在编译期间就会报错,不会等到运行期间了,这样就增强了代码运行的安全性Double c = (Double) re.get();}

泛型也有一些规则和限制:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“受限泛型”。
5、泛型的参数类型还可以是通配符类型。例如ReturnObject1<?> re = new ReturnObject1<String>(a);
以上是关于泛型的简单介绍,我试着在网上找一些关于泛型在各种各样场景下的应用,发现一篇博客写的已经很完整了,特转来跟大家分享:
以下内容为转载,本人只是做了少量修正和注释补充
普通泛型
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 GenericsDemo06{public static void main(String args[]){Point<String> p = new Point<String>() ;// 里面的var类型为String类型p.setVar("it") ;// 设置字符串System.out.println(p.getVar().length()) ;// 取得字符串的长度}};----------------------------------------------------------class Notepad<K,V>{// 此处指定了两个泛型类型private K key ;// 此变量的类型由外部决定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 GenericsDemo09{public static void main(String args[]){Notepad<String,Integer> t = null ;// 定义两个泛型类型的对象t = new Notepad<String,Integer>() ;// 里面的key为String,value为Integert.setKey("汤姆") ;// 设置第一个内容t.setValue(20) ;// 设置第二个内容System.out.print("姓名;" + t.getKey()) ;// 取得信息System.out.print(",年龄;" + t.getValue()) ;// 取得信息}};

通配符
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 GenericsDemo14{public static void main(String args[]){Info<String> i = new Info<String>() ;// 使用String为泛型类型i.setVar("it") ;// 设置内容fun(i) ;}public static void fun(Info<?> temp){// 使用通配符"?"表示可以接收任意的泛型对象System.out.println("内容:" + 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 GenericsDemo17{public static void main(String args[]){Info<Integer> i1 = new Info<Integer>() ;// 声明Integer的泛型对象Info<Float> i2 = new Info<Float>() ;// 声明Float的泛型对象i1.setVar(30) ;// 设置整数,自动装箱i2.setVar(30.1f) ;// 设置小数,自动装箱fun(i1) ;fun(i2) ;}public static void fun(Info<? extends Number> temp){// 只能接收Number及其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 GenericsDemo21{public static void main(String args[]){Info<String> i1 = new Info<String>() ;// 声明String的泛型对象Info<Object> i2 = new Info<Object>() ;// 声明Object的泛型对象i1.setVar("hello") ;i2.setVar(new Object()) ;fun(i1) ;fun(i2) ;}public static void fun(Info<? super String> temp){// 只能接收String或Object类型的泛型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 GenericsDemo23{public static void main(String args[]){Info<String> i1 = new Info<String>() ;// 泛型类型为StringInfo<Object> i2 = null ;i2 = i1 ;//这句会出错 incompatible types}};

泛型接口
interface Info<T>{// 在接口上定义泛型public T getVar() ;// 定义抽象方法,抽象方法的返回值就是泛型类型}class InfoImpl<T> implements Info<T>{// 定义泛型接口的子类private T var ;// 定义属性public InfoImpl(T var){// 通过构造方法设置属性内容this.setVar(var) ;}public void setVar(T var){this.var = var ;}public T getVar(){return this.var ;}};public class GenericsDemo24{public static void main(String arsg[]){Info<String> i = null;// 声明接口对象i = new InfoImpl<String>("汤姆") ;// 通过子类实例化对象System.out.println("内容:" + i.getVar()) ;}};----------------------------------------------------------interface Info<T>{// 在接口上定义泛型public T getVar() ;// 定义抽象方法,抽象方法的返回值就是泛型类型}class InfoImpl implements Info<String>{// 定义泛型接口的子类private String var ;// 定义属性public InfoImpl(String var){// 通过构造方法设置属性内容this.setVar(var) ;}public void setVar(String var){this.var = var ;}public String getVar(){return this.var ;}};public class GenericsDemo25{public static void main(String arsg[]){Info i = null;// 声明接口对象i = new InfoImpl("汤姆") ;// 通过子类实例化对象System.out.println("内容:" + i.getVar()) ;}};

泛型方法

class Demo{public <T> T fun(T t){// 可以接收任意类型的数据,在方法返回值前面标注泛型标识"<T>"return t ;// 直接把参数返回}};public class GenericsDemo26{public static void main(String args[]){Demo d = new Demo();// 实例化Demo对象String str = d.fun("汤姆") ; //传递字符串int i = d.fun(30) ;// 传递数字,自动装箱System.out.println(str) ;// 输出内容System.out.println(i) ;// 输出内容}};

通过泛型方法返回泛型类型实例

class Info<T extends 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 GenericsDemo27{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>() ;// 根据传入的数据类型实例化Infotemp.setVar(param) ;// 将传递的内容设置到Info对象的var属性之中return temp ;// 返回实例化对象}};

使用泛型统一传入的参数类型

class Info<T>{// 指定上限,只能是数字类型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 GenericsDemo28{public static void main(String args[]){Info<String> i1 = new Info<String>() ;Info<String> i2 = new Info<String>() ;i1.setVar("HELLO") ;// 设置内容i2.setVar("汤姆") ;// 设置内容add(i1,i2) ;}public static <T> void add(Info<T> i1,Info<T> i2){System.out.println(i1.getVar() + " " + i2.getVar()) ;}};

泛型数组

public class GenericsDemo30{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.print("接收泛型数组:") ;for(T t:param){System.out.print(t + "、") ;}}};

泛型的嵌套设置

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 GenericsDemo31{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>("汤姆",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> newArrayList() {    return new ArrayList<E>();  }     public List<PrepaidHistory> queryHistories(Long skyid,PrepaidHistoryType type, Date from, Date end) {    。。。             return Lists.newArrayList();    }

这样Lists.newArrayList();
智能的知道返回类型为PrepaidHistory


好了,以上就是全部关于java泛型的内容了,希望对大家的java学习有所帮助

原创粉丝点击