JDK 令我们期待很久可是当他发布的时候却更换版本号为这说明Java已经有大幅度的变化本文将讲解JDK支持的新功能Java的泛型
Java泛型
其实Java的泛型就是创建一个用类型作为参数的类就象我们写类的方法一样方法是这样的method(String strString str )方法中参数strstr的值是可变的而泛型也是一样的这样写class Java_Generics<KV>这里边的K和V就象方法中的参数str和str也是可变下面看看例子
//code list
import JavautilHashtable;
class TestGen<KV>{
public Hashtable<KV> h=new Hashtable<KV>();
public void put(K k V v) {
hput(kv);
}
public V get(K k) {
return hget(k);
}
public static void main(String args[]){
TestGen<StringString> t=new TestGen<StringString>();
tput(key value);
String s=tget(key);
Systemoutprintln(s);
}
}
正确输出:value
这只是个例子(Java中集合框架都泛型化了这里费了遍事)不过看看是不是创建一个用类型作为参数的类参数是KV传入的值是String类型这个类他没有特定的待处理型别以前我们定义好了一个类在输入输入参数有所固定是什么型别的有要求但是现在编写程序完全可以不制定参数的类型具体用的时候来确定增加了程序的通用性像是一个模板
呵呵类似C++的模板(类似)
泛型通配符
下面我们先看看这些程序
//Code list
void TestGenMedthod(List l) {
for (Object o : l)
Systemoutprintln(o);
}
看看这个方法有没有异议这个方法会通过编译的假如你传入String就是这样List<String>
接着我们调用它问题就出现了我们将一个List<String>当作List传给了方法JVM会给我们一个警告说这个破坏了类型安全因为从List中返回的都是Object类型的而让我们再看看下面的方法
//Code list
void TestGenMedthod(List<String> l) {
for (Object o : l)
Systemoutprintln(o);
}
因为这里的List<String>不是List<Object>的子类不是String与Object的关系就是说List<String>不隶属于list<Object>他们不是继承关系所以是不行的这里的extends是表示限制的
类型通配符是很神奇的List<?>这个你能为他做什么呢?怎么都是?它似乎不确定他总不能返回一个?作为类型的数据吧是啊他是不会返回一个?来问程序员的?JVM会做简单的思考的看看代码吧更直观些
//code list
List<String> l = new ArrayList<String>();
liadd(String);
List<?> l = l;
Systemoutprintln(lget());
这段代码没问题的lget()将返回一个Object
编写泛型类要注意
) 在定义一个泛型类的时候在 <>之间定义形式类型参数例如class TestGen<KV>其中K V不代表值而是表示类型
) 实例化泛型对象的时候一定要在类名后面指定类型参数的值(类型)一共要有两次书写例如
TestGen<StringString> t=new TestGen<StringString>()
) 泛型中<K extends Object>extends并不代表继承它是类型范围限制
泛型与数据类型转换
消除类型转换
上面的例子大家看到什么了数据类型转换的代码不见了在以前我们经常要书写以下代码如
//code list
import JavautilHashtable;
class Test {
public static void main(String[] args) {
Hashtable h = new Hashtable();
hput(key value);
String s = (String)hget(key);
Systemoutprintln(s);
}
}
这个我们做了类型转换是不是感觉很烦的并且强制类型转换会带来潜在的危险系统可能会抛一个ClassCastException异常信息在JDK中我们完全可以这么做如
//code list
import JavautilHashtable;
class Test {
public static void main(String[] args) {
Hashtable<StringInteger> h = new Hashtable<StringInteger> ();
hput(key new Integer());
int s = hget(key)intValue();
Systemoutprintln(s);
}
}
这里我们使用泛化版本的HashMap这样就不用我们来编写类型转换的代码了类型转换的过程交给编译器来处理是不是很方便而且很安全上面是String映射到String也可以将Integer映射为String只要写成HashTable<IntegerString> h=new HashTable<IntegerString>();hget(new Integer())返回value果然很方便
自动解包装与自动包装的功能
从上面有没有看到有点别扭啊hget(new Integer())这里的new Integer();好烦的在JDK之前我们只能忍着了现在这种问题已经解决了请看下面这个方法我们传入一个int这一基本型别然后再将i的值直接添加到List中其实List是不能储存基本型别的List中应该存储对象这里编译器将int包装成Integer然后添加到List中去接着我们用Listget();来检索数据并返回对象再将对象解包装成int恩JDK给我们带来更多方便与安全
//Code list
public void autoBoxingUnboxing(int i) {
ArrayList<Integer> L= new ArrayList<Integer>();
Ladd(i);
int a = Lget();
Systemoutprintln(The value of i is + a);
}
限制泛型中类型参数的范围
也许你已经发现在code list 中的TestGen<KV>这个泛型类其中KV可以是任意的型别也许你有时候呢想限定一下K和V当然范围怎么做呢?看看如下的代码
//Code list
class TestGen<K extents StringV extends Number>
{
private V v=null;
private K k=null;
public void setV(V v){
thisv=v;
}
public V getV(){
return thisv;
}
public void setK(K k){
thisk=k;
}
public V getK(){
return thisk;
}
public static void main(String[] args)
{
TestGen<StringInteger> t=new TestGen<StringInteger>();
tsetK(new String(String));
tsetV(new Integer());
Systemoutprintln(tgetK());
Systemoutprintln(tgetV());
}
}
上边K的范围是<=String V的范围是<=Number注意是<=对于K可以是String的V当然也可以是Number也可以是IntegerFloatDoubleByte等看看下图也许能直观些请看上图A是上图类中的基类AA分别是A的子类A有个子类分别是A_A_
然后我们定义一个受限的泛型类class MyGen<E extends A>这个泛型的范围就是上图中兰色部分
这个是单一的限制你也可以对型别多重限制如下
class C<T extends Comparable<? super T> & Serializable>
我们来分析以下这句T extends Comparable这个是对上限的限制Comparable< super T>这个是下限的限制Serializable是第个上限一个指定的类型参数可以具有一个或多个上限具有多重限制的类型参数可以用于访问它的每个限制的方法和域
多态方法
//Code list
class TestGen {
<T extends Object> public static List<T> make(T first) {
return new List<T>(first);
}
}