您的位置:首页 > 编程语言 > Java开发

和Java泛型谈谈

2016-04-18 10:53 501 查看
泛型,把类型参数化。

泛型的命名规则:

不要小写字母表示泛型名字,虽然这也没什么错。如果可以的话,泛型就用“T”来表示。

还有就是类上的泛型和方法上的泛型,名字尽量不要相同。

它在JDK1.5之后出现,主要的作用是解决安全问题

比如下面的安全问题:

private static void method_1() {
ArrayList al=new ArrayList();
al.add("abc01");
al.add("abc0991");
al.add("abc014");
al.add(4);
Iterator it=al.iterator();
while(it.hasNext()){
String next=(String)it.next();
System.out.println(next);
}
}


ArrayList可以添加任何类型的元素,该方法在程序编译时并不会出现问题。但是在迭代取值时,Integer类型的值无法转换为String,会出现ClassCastException异常。

而避免这种问题的,就是指定ArrayList的元素的类型,把类型参数化。比如这样:

ArrayList<String> al=new ArrayList<String>();
al.add("abc01");
al.add("abc0991");
al.add("abc014");
//al.add(4);    编译时提示错误


本例子中,泛型可以把一些错误提前到了编译时期,方便了调试。而且在迭代时,不再需要强制转化。

Iterator<String> it=al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}


1,泛型定义在类上

ArrayList类上的泛型

public class ArrayList<E> extends AbstractList<E>


ArrayList al=new ArrayList();

传递进去的类的泛型是String,而定义在类上的泛型,在整个类中都是有效的。

类上的泛型可以由一个也可以由多个:

class GenericForClass1<T>{
private T temp;

private void set(T t){
this.temp=t;
}

private T get(){
return temp;
}

private void print(){
System.out.println(temp);
}
}

private void generic_1() {
GenericForClass1<Integer> generic=
new GenericForClass1<Integer>();
generic.set(1);
generic.print();
}


class GenericForClass2<T1,T2>{
private T1 t1;
private T2 t2;

private void setT1(T1 t){
this.t1=t;
}

private T1 getT1(){
return t1;
}

private void setT2(T2 t){
this.t2=t;
}

private T2 getT2(){
return t2;
}

private void print(){
System.out.println(t1+"----"+t2);
}
}

private void generic_1() {
GenericForClass2<Integer,String> generic=
new GenericForClass2<Integer,String>();
generic.setT1(1);
generic.setT2("ronaldo");
generic.print();
}


2,泛型定义在方法上

class GenericForClass1<T>{
private T temp;

private void set(T t){
this.temp=t;
}

private T get(){
return temp;
}

private void print(){
System.out.println(temp);
}
}


泛型定义在类上后,操作的类型就固定了。比如下面的写法就有问题:

GenericForClass1<Integer> generic=
new GenericForClass1<Integer>();
eneric.set("1");//编译出错


为了让不同的方法操作不同的类型,我们可以不把泛型定义在类上,而是定义在方法上。

注意的是泛型如果定义在方法上,只对该方法是有效的。

如下:

class GenericForClass1{
private <T>void show(T t){
System.out.println(t);
}
}

private void generic_1() {
GenericForClass1 generic=
new GenericForClass1();
generic.show("1");
generic.show(1);
}


当然也可以在类上定义泛型,而在方法上也定义泛型来操作不同类型。如:

class GenericForClass1<T>{
private T t;

private void set(T t){
this.t=t;
}

private T get(){
return t;
}

private void print(){
System.out.println(t);
}

private <S>void show(S s){
System.out.println(s);
}
}

private void generic_1() {
GenericForClass1<Integer> generic=
new GenericForClass1<Integer>();
generic.set(1);
generic.set("1");//编译错误,set方法的泛型和类是绑定的
generic.print();
generic.show("1");
}


静态方法的泛型:

class Demo1<T>{
private void show(T t){
System.out.println(t);
}

private <T>void set(T t){
System.out.println(t);
}

//编译时会出现错误
private static <T> void method(T t){
System.out.println(t);
}
}


静态方法访问类上的泛型,编译出错。原因是,建立对象后才会有泛型。

比如ArrayList al=new ArrayList();

我们知道静态成员是先加载的。

既然静态方法无法访问类上的泛型,我们可以为它在方法上定义泛型。

private static <S>  void method(S s){
System.out.println(s);
}


3,泛型定义在接口上

//泛型定义在接口上
interface MyInter<T>{
void access(T t);
}

//实现接口指定泛型
class MyImpl1 implements MyInter<String>{
@Override
public void access(String t) {

}
}

//实现接口后不知道传递什么类型
class MyImpl2<T> implements MyInter<T>{
@Override
public void access(T t) {

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: