泛型

泛型

***泛型(generic)***的本质是类型参数化,解决不确定具体对象类型的问题。
泛型可以定义在类、接口、方法中,编译器通过识别尖括号和尖括号内的字母来解析泛型。在泛型的定义中我们通常用:E代表Element,用于集合元素,T代表the Type of object,表示某一个类,K代表Key、V代表value,用于键值对元素。
我们来一个例子瞅瞅:

public class Generic<E> {
    private E foo;
    public E getFoo(){
        return foo;
    }
   public void setFoo(E foo) {
        this.foo = foo;
    }
    public static void main(String []args){
        Generic<Boolean> generic1=new Generic<>();
        Generic<Integer> generic2=new Generic<>();
        generic1.setFoo(new Boolean(false));
        generic2.setFoo(new Integer(14));
        Boolean i=generic1.getFoo();
        Integer s=generic2.getFoo();
        System.out.println(i);
        System.out.println(s);
    }
}

看了例子我们可以总结出:
①尖括号的每一个元素都指代一种未命名的类型。
②尖括号的位置非常讲究,必须在类名之后或者返回值之前。
③泛型在定义处只具备执行Object方法的例子的能力。
④对于编译后的字节码指令,并没有花头花脑的方法签名,充分说明泛型只是一种编写代码的语法检查。

public class GenericFoo<T1,T2> {
    private T1 foo1;
    private T2 foo2;

    public T2 getFoo2() {
        return foo2;
    }

    public void setFoo2(T2 foo2) {
        this.foo2 = foo2;
    }

    public T1 getFoo1() {
        return foo1;
    }

    public void setFoo1(T1 foo1) {
        this.foo1 = foo1;
    }
    public static void main(String[]args){
        GenericFoo<Integer,Boolean> generic=new GenericFoo<Integer,Boolean>();
        generic.setFoo1(-20);
        generic.setFoo2(false);
        System.out.println(generic.getFoo1());
        System.out.println(generic.getFoo2());
    }
}

用泛型来定义一个数组:

public class Generic1<T> {
  private T [] Array;


    public T[] getArray() {
        return Array;
    }

    public void setArray(T[] array) {
        Array = array;
    }
    public static void main(String[]args){
        Generic1<String> g=new Generic1<>();
         String[] str= {"hello", "wrold","!"};
         g.setArray(str);
         String[] str1=null;
         str1=g.getArray();
         for (int i=0;i<str.length;i++){
               System.out.print(str1[i]+" " );
         }
    }
}

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

import java.util.ArrayList;
import java.util.LinkedList;

public class List<E extends java.util.List<String>> {
    private E[] fooArray;

    public E[] getFooArray() {
        return fooArray;
    }

    public void setFooArray(E[] fooArray) {
        this.fooArray = fooArray;
    }
    public static void main(String[]args){
        List<LinkedList<String>> foo1=new List<>();
        List<ArrayList<String>> foo2=new List<>();
       LinkedList[] linkedLists=new LinkedList[10];
       foo1.setFooArray(linkedLists);
       ArrayList[] arrayLists=new ArrayList[10];
       foo2.setFooArray(arrayLists);
    }
}

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

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class GenericTest <T>{
    private T foo;

    public T getFoo() {
        return foo;
    }

    public void setFoo(T foo) {
        this.foo = foo;
    }
    public static void main(String[]args){
        GenericTest<?extends List> ge=null;
        ge=new GenericTest<ArrayList>();
        ge=new GenericTest<LinkedList>();
        GenericTest<?  super List> ge2=null;
        ge2=new GenericTest<Object>();
        GenericTest<String> ge3=new GenericTest<>();
        ge3.setFoo("hello world");
        GenericTest<? extends Object> ge4=ge3;
        System.out.println(ge4.getFoo());
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值