这一篇将系统的回忆起泛型的知识

在做Android的时候用到泛型的类有很多,很多时候会遇到将数据保存到一个List集合,Map等等,他们之间使用<>来填写数据类型,说一个我现在想到的就是Android中异步加载这个类AsyncTask《Params, Progress, Result》,第一个参数是在execute()中写入的参数,然后在doInBackgound中中传入了这个参数,最后返回了Result这个类型值。说了有点多,下面就说一下泛型的知识。

首先来一段简单的泛型代码
格式 :

  • <数据类型>
  • 此处的数据类型只能是引用类型。
ArrayList<String> array = new ArrayList();
     array.add("fat");
     array.add("one");
     Iterator<String> it = array.iterator();
     while(it.hasNext()){
         System.out.println(it.next());
     }

把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型—引用类型就是一个对象类型

泛型类

就是把泛型定义在类上,类中的参数是泛型

public class Test {
    //泛型类 --类中使用的参数是泛型
    public static class Fat<T>{
        private T obj;
        public T getObj(){
            return obj;
        }
        public void setObj(T obj){
            this.obj = obj;
        }
    }
    public static void main(String[] args) {
      Fat<String> fat = new Fat<String>();
       fat.setObj("一个胖儿");
      System.out.println( fat.getObj());
       Fat<Integer> age = new Fat();
       age.setObj(22);
       System.out.println(age.getObj());
    }

}

泛型方法

就是将泛型定义在方法上,此方法就可以传任意类型的参数,定义泛型方法的格式是

public <T> 方法名 (T t){}
//注意 泛型方法所在的类是个泛型类,因为前面生命的<T>就是泛型类中的泛型

看代码

public class Test {
    public static class Fat<T>{
        private T obj;
        public T getObj(){
            return obj;
        }
        public void setObj(T obj){
            this.obj = obj;
        }
        public <T> void show(T obj){
            System.out.println(obj);
        }
    }
    public static void main(String[] args) {
       Fat<String> fat = new Fat<String>();
       fat.setObj("一个胖儿");
//      System.out.println( fat.getObj());
       fat.show(fat.getObj());
       Fat<Integer> age = new Fat();
       age.setObj(22);
//       System.out.println(age.getObj());
       fat.show(age.getObj());
    }
}

泛型接口

格式:public interface 接口名<泛型>
看代码

//定一个父接口
public interface Finterface <T>{
    public  void show(T t);
}
//然后定义一个子类来实现这个父类接口
public class Zinterfaceimpl<T> implements Finterface<T>{
    @Override
    public void show(T t) {
        System.out.println(t);
    }
//测试
public class Test {
    public static void main(String[] args) {
        Finterface<Integer> one = new Zinterfaceimpl();
        one.show(123);
    }
}
//当然实现接口的时候可以确定类型
public class Zinterfaceimpl implements Finterface<String>{
    @Override
    public void show(String t) {
        System.out.println(t);
    }

通配符–?

  • 类< ?>
    表示任意类型,如果没有明确,就是Object以及任意的java类
  • ? extends E
    向下限定,E及其子类,就是所有继承了E的类才可以传入
  • ? super E
    向上限定,E及其父类,就是所有E的类或者E的父类。

看代码好理解一点:

//首先定义了一个A类
  public class A<T> {
    private T t;
    A(){}
    A(T t){
        this.t = t;
    }
    public void show(){
        System.out.println(t);
    }
}
//定一个Fat类
public class Fat {   
    public void show(){
        System.out.println("一个胖儿");
    }
}
//测试
public class D {
    public static void main(String[] args) {
      A<Object> a = new A<Object>();
     // A<Object> b = new A<Fat>();报错 ,必须前后一致
     //为了解决这个问题使用通配符 ?
      A<?> b = new A<Fat>();
     //? extends E
       A<? extends Fat> c = new A<>();//这个的意思就是限定了传入继承Fat或者Fat类的类类型
       c.show(); //这里会输出一个null 注意这里调用的是A中的show方法
       //如果我非要调用Fat中的show方法呢?这就要改一下A中的show代码

    }
}

//修改后的A类show方法 还是得定义一个类的引用,其实这样我感觉根本就没体现向下限定
  public void show(){
        Fat f = (Fat) t;
        f.show();
    }

关于向上限定和向下限定有什么用呢?在Android中目前我还没用过,不过可以限定你传入对象的类型,必须是你想要对象的子类,或者必须是实现了这个接口的类。比如说

//将Fat定义成接口
public interface Fat {
    public void show();
}

//B类
public class B implements Fat{
    @Override
    public void show() {
    }   
}
//测试
public class D {
    public static void main(String[] args) {
      B ccc =new B();
       A<? extends Fat> d = new A<B>(ccc);
       d.show();
       //结果为 one fat
    }
}
//注意A类,没有任何改动,使用Fat接口引用
ublic class A<T> {
    private T t;
    A(){}
    A(T t){
        this.t = t;
    }
    public void show(){
        Fat f = (Fat) t;
        f.show();
    }
}

接口作为引用类型来使用,任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类中所实现的接口中的方法,Java 运行时系统会动态地确定应该使用哪个类中的方法,实际上是调用相应的实现类的方法。

================================================================================