博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于泛型
阅读量:5923 次
发布时间:2019-06-19

本文共 12863 字,大约阅读时间需要 42 分钟。

泛型:

泛型是JDK1.5中一个最重要的特性,通过引入泛型,我们将获得编译时类型的安全,和运行时更小的抛出ClassCastexceptions的可能.在JDK1.5中,你可以声明一个集合接收或者返回的对象的类型.

 泛型之前:

类别定义时的逻辑完全一样,只是里面成员变量的类型不同.

如果需要多个相似的类,需要定义多个文件,不同的只是变量的类别,而逻辑是完全一样的.

IntergerFoo.java

1 public class IntegerFoo{ 2     private Integer foo; 3  4     public Integer getFoo(){ 5         return foo; 6     } 7  8     public void setFoo(Integer foo){ 9         this.foo = foo;10     }11 }

BooleanFoo.java

1 public class BooleanFoo{ 2     private Boolean foo; 3  4     public Boolean getFoo()    { 5         return foo; 6     } 7  8     public void setFoo(Boolean foo){ 9         this.foo = foo;10     }11 }

如果有很多类型的话想用一个类型来替代以上等的类型怎么办,只能用Object类.

ObjectFoo.java

1 public class ObjectFoo{ 2     private Object foo; 3  4     public Object getFoo(){ 5         return foo; 6     } 7  8     public void setFoo(Object foo){ 9         this.foo = foo;10     }11     12     public static void main(String[] args){13         ObjectFoo foo1 = new ObjectFoo();14         ObjectFoo foo2 = new ObjectFoo();15         16         foo1.setFoo(new Boolean(false));17         Boolean b = (Boolean)foo1.getFoo();18         19         foo2.setFoo(new Integer(10));20         Integer i = (Integer)foo2.getFoo();21         22         ObjectFoo foo3 = new ObjectFoo();23         foo3.setFoo(new Boolean(false));24         25         String str = (String)foo3.getFoo();26         //这个时候编译不会报错,但是运行的时候Object不能转换成String类型的,一定会出错27         //java.lang.ClassCastException: java.lang.Boolean cannot be caast to java.lang.String28     }29 }

定义泛型类别:

如果使用泛型,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException

所谓泛型就是变量的类型参数化(不是变量本身,是变量的类型).

GenericFoo.java

1 public class GenericFoo
{ 2 private T foo; 3 4 public T getFoo(){ 5 return foo; 6 } 7 8 public void setFoo(T foo){ 9 this.foo = foo;10 }11 12 public static void main(String[] args){13 GenericFoo
foo1 = new GenericFoo
();14 GenericFoo
foo2 = new GenericFoo
();15 16 foo1.setFoo(new Boolean(false));17 foo2.setFoo(new Integer(3));18 19 Boolean b = foo1.getFoo();20 Integer i = foo2.getFoo();21 22 System.out.println(b);//打印输出:false23 System.out.println(i);//打印输出:324 25 //foo1 = foo2;26 //报错Type mismatch: cannot convert from GenericFoo
to GenericFoo
27 28 GenericFoo a = new GenericFoo();29 a.setFoo("hello");30 31 String str = (String)a.getFoo();32 System.out.println(str);//输出:hello33 }34 }

 Generic.java

1 public class Generic
{ 2 private T1 foo1; 3 4 private T2 foo2; 5 6 public T1 getFoo1(){ 7 return foo1; 8 } 9 10 public void setFoo1(T1 foo1){11 this.foo1 = foo1;12 }13 14 public T2 getFoo2(){15 return foo2;16 }17 18 public void setFoo2(T2 foo2){19 this.foo2 = foo2;20 }21 22 public static void main(String[] args){23 Generic
foo = new Generic
();24 25 foo.setFoo1(new Integer(-20));26 foo.setFoo2(new Boolean(false));27 28 System.out.println(foo.getFoo1());29 System.out.println(foo.getFoo2());30 }31 }

 

打印输出:

-20

false

Generic2.java

1 public class Generic2
{ 2 private T[] fooArray; 3 //泛型数组 4 5 public T[] getFooArray(){ 6 return fooArray; 7 } 8 9 public void setFooArray(T[] fooArray){10 this.fooArray = fooArray;11 }12 13 public static void main(String[] args){14 Generic2
foo = new Generic2
();15 16 String[] str1 = {"hello", "world", "welcome"};17 String[] str2 = null;18 19 foo.setFooArray(str1);20 21 str2 = foo.getFooArray();22 23 for(int i = 0; i < str2.length; i++){24 System.out.println(str2[i]);25 }26 }27 }

 

打印输出:

hello

world
welcome

SimpleCollection.java

1 public class SimpleCollection
{ 2 private T[] objArr; 3 4 private int index = 0; 5 6 public SimpleCollection(){ 7 objArr = (T[])new Object[10]; 8 //这个时候编译器会有一个警告: 9 //Type safety: Unchecked cast from Object[] to T[]10 //这个时候老师领着看的ArrayList的源码中的get()方法11 12 //objArr = new T[10];13 //报错:Cannot create a generic array of T14 //语法上不允许这样创建一个泛型数组.这个时候怎么办?15 //只能用Object类型.16 17 }18 19 public SimpleCollection(int capacity){20 objArr = (T[])new Object[capacity];21 }22 23 public void add(T t){24 objArr[index++] = t;25 }26 27 public int getLength(){28 return this.index;29 }30 31 public T get(int i){32 return objArr[i];33 }34 35 public static void main(String[] args){36 SimpleCollection
c = new SimpleCollection
();37 38 for(int i = 0; i < 10; i++){39 c.add(new Integer(i));40 }41 42 for(int i = 0; i < 10; i++){43 Integer in = c.get(i);44 45 System.out.println(in);46 }47 }48 }

 

打印输出:1~9

ArrayListTest.java

1 public class ArrayListTest{ 2     public static void main(String[] args){ 3         List
list = new ArrayList
(); 4 5 list.add("a"); 6 list.add("b"); 7 list.add("c"); 8 list.add("d"); 9 //第一种遍历10 for(int i = 0; i < list.size(); i++){11 String value = list.get(i);12 System.out.println(value);13 }14 15 //第二种:使用迭代器16 for(Iterator
iter = list.iterator(); iter.hasNext();){17 String value = iter.next();18 System.out.println(value);19 }20 }21 }

 

 

打印输出:两次a b c d

SetTest.java

1 package cn.shengsiyuan.jdk5;  2   3 import java.util.HashSet;  4 import java.util.Iterator;  5 import java.util.Set;  6   7 public class SetTest{  8     public static void main(String[] args){  9         Set
set = new HashSet
(); 10 11 set.add("aa"); 12 set.add("bb"); 13 set.add("cc"); 14 15 for (Iterator
iter = set.iterator(); iter.hasNext();){ 16 String value = iter.next(); 17 System.out.println(value); 18 } 19 20 System.out.println("----------------"); 21 22 Set
set2 = new HashSet
(); 23 24 set2.add(new People("zhangsan", 20, "beijing")); 25 set2.add(new People("lisi", 30, "shanghai")); 26 set2.add(new People("wangwu", 40, "tianjin")); 27 28 for(Iterator
iter = set2.iterator(); iter.hasNext();){ 29 People people = iter.next(); 30 31 String name = people.getName(); 32 int age = people.getAge(); 33 String address = people.getAddress(); 34 35 System.out.println(name + "," + age + "," + address); 36 } 37 } 38 } 39 40 class People{ 41 private String name; 42 43 private int age; 44 45 private String address; 46 47 public People(String name, int age, String address){ 48 this.name = name; 49 this.age = age; 50 this.address = address; 51 52 } 53 54 public int hashCode(){ 55 final int prime = 31; 56 int result = 1; 57 result = prime * result + ((address == null) ? 0 : address.hashCode()); 58 result = prime * result + age; 59 result = prime * result + ((name == null) ? 0 : name.hashCode()); 60 return result; 61 } 62 63 public boolean equals(Object obj){ 64 if (this == obj) 65 return true; 66 if (obj == null) 67 return false; 68 if (getClass() != obj.getClass()) 69 return false; 70 People other = (People) obj; 71 if (address == null){ 72 if (other.address != null) 73 return false; 74 } 75 else if (!address.equals(other.address)){ 76 return false; 77 } 78 if (age != other.age){ 79 return false; 80 } 81 if (name == null){ 82 if (other.name != null){ 83 return false; 84 } 85 } 86 else if (!name.equals(other.name)){ 87 return false; 88 } 89 return true; 90 } 91 92 public String getName(){ 93 return name; 94 } 95 96 public void setName(String name){ 97 this.name = name; 98 } 99 100 public int getAge(){101 return age;102 }103 104 public void setAge(int age){105 this.age = age;106 }107 108 public String getAddress(){109 return address;110 }111 112 public void setAddress(String address){113 this.address = address;114 }115 }

aa

bb
cc
----------------
wangwu,40,tianjin
zhangsan,20,beijing
lisi,30,shanghai

MapTest.java

1 public class MapTest{ 2     public static void main(String[] args){ 3         Map
map = new HashMap
(); 4 5 map.put("a", "aa"); 6 map.put("b", "bb"); 7 map.put("c", "cc"); 8 map.put("d", "dd"); 9 10 Set
set = map.keySet();11 12 for (Iterator
iter = set.iterator(); iter.hasNext();){13 String key = iter.next();14 String value = map.get(key);15 16 System.out.println(key + ":" + value);17 }18 19 System.out.println("----------------------------------");20 21 Set
> set2 = map.entrySet();22 23 for (Iterator
> iter = set2.iterator(); iter24 .hasNext();){25 Map.Entry
entry = iter.next();26 27 String key = entry.getKey();28 String value = entry.getValue();29 30 System.out.println(key + ":" + value);31 }32 }33 }

d:dd

b:bb
c:cc
a:aa
----------------------------------
d:dd
b:bb
c:cc
a:aa

限制泛型可用类型:

在定义泛型类别时,预设可以使用任何的类型来实例化泛型类型中的类型,但是如果想要限制使用泛型类别时,只能用某个特定类型或者是其子类才能实例化该类型时,可以再定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口.

当没有指定泛型继承的类型或接口时,默认使用T extends Object,所以默认情况下任何类型都可以作为参数传入.

 ListGenericFoo.java

1 public class ListGenericFoo
{ 2 // 虽然这个地方List也是一个接口,但是在泛型中仍然要用extends.不能用implements. 3 // 不管面是类还是接口都要用extends 4 private T[] fooArray; 5 6 public T[] getFooArray() { 7 return fooArray; 8 } 9 10 public void setFooArray(T[] fooArray) {11 this.fooArray = fooArray;12 }13 14 public static void main(String[] args) {15 ListGenericFoo
foo1 = new ListGenericFoo
();16 ListGenericFoo
foo2 = new ListGenericFoo
();17 18 LinkedList[] linkedList = new LinkedList[10];19 20 foo1.setFooArray(linkedList);21 22 ArrayList[] arrayList = new ArrayList[10];23 24 foo2.setFooArray(arrayList);25 26 // ListGenericFoo
foo3 = new ListGenericFoo
();27 // 报错,HashMap和List没有关系.28 // Bound mismatch: The type HashMap is not a valid substitute for29 // the bounded parameter
of the type ListGenericFoo
30 }31 }

 

类型通配声明:

现在有这么一个需求,你希望哟u一个参考名称foo可以接受所有下面的实例:

foo = new Generic Foo
();foo = new Generic Foo
();

 

简单的说,实例化类型持有者时,它必须是实现List的类别或其子类别,要定义这样一个名称,你可以使用"?"通配字符,并使用extends关键字限定类型持有者的形态.

GenericFoo
foo = null;foo = new GenericFoo
();foo = new GenericFoo
();

 

GenericTest.java

1 public class GenericTest
{ 2 private T foo; 3 4 public T getFoo(){ 5 return foo; 6 } 7 8 public void setFoo(T foo){ 9 this.foo = foo;10 }11 12 public static void main(String[] args){13 GenericTest
ge = null;14 15 ge = new GenericTest
();16 ge = new GenericTest
();17 18 //ge = new GenericTest
();19 20 GenericTest
ge2 = null;21 //这种super的非常少用,传递的值的类型必须是List的父类....22 ge2 = new GenericTest
();23 24 //ge2 = new GenericTest
();25 //Type mismatch: cannot convert from GenericTest
to GenericTest
26 27 GenericTest
ge3 = new GenericTest
();28 ge3.setFoo("hello world");29 //GenericTest
ge4 = ge3;30 //如果后面是Object的话可以简写成一个问号"?"31 GenericTest
ge4 = ge3;32 System.out.println(ge4.getFoo());//打印输出:null33 34 35 ge4.setFoo(null);36 System.out.println(ge4.getFoo());//打印输出:null37 //ge4.setFoo("welcome");38 //eclipse的提示错误信息:The method setFoo(capture#7-of ?) 39 //in the type GenericTest
is not applicable for the arguments (String)40 //这个错误信息不好理解.老师的解释是,当你上面GenericTest
ge4 的时候,编译器知道ge4的类型是41 //Object或者其子类.但是当你进行ge4.setFoo("welcome");时候,当进行get的时候必须是一个String类型的,这个和泛型的42 //的初衷想违背,所以是错误的.43

 

 

使用<?>或是<? extends SomeClass>的声明方式,意味著您只能通过该名称來取得所参考实例的信息,或者是移除某些信息,但不能增加它的信息,因为只知道当中放置的是SomeClass的子类,但不确定是什么类的实例,编译器不让您加入信息,理由是,如果可以加入信息的話,那么您就得記得取回的实例是什么类型,然后转换为原來的类型方可进行操作,这就失去了使用泛型的意义。

 

转载地址:http://vqxvx.baihongyu.com/

你可能感兴趣的文章
冷启动问题
查看>>
软件编程的那些事(1)-前言
查看>>
jmeter高级用法例子,如何扩展自定义函数
查看>>
Part1——政府机构面临的安全威胁
查看>>
exp
查看>>
oracle教程之oralce非归档模式下的恢复(二)
查看>>
Oracle技术之普通库迁移至ASM存储
查看>>
Tomcat下Solr安装配置
查看>>
区块链3.0才能真正推动区块链时代大步向前!
查看>>
怎么去掉Xcode工程中的某种类型的警告
查看>>
希尔排序算法
查看>>
批量替换 MySQL 指定字段中的字符串
查看>>
mysql常见命令
查看>>
创建日志打印对象
查看>>
按Sybase的PowerDesigner工具设计的数据库模型 ---> 解析生成能兼容多种数据库的相应的C#底层代码...
查看>>
海思SDK Q&A
查看>>
APT 使用!!
查看>>
Linux-shell-完全详解(3)
查看>>
我的友情链接
查看>>
lvs
查看>>