学习RxJava之Java的泛型

在RxJava的代码中,使用了大量的泛型,如果不熟悉的话,阅读源码非常的困难,比如非常核心的Observable类中,lift()方法代码:

public final  Observable lift(final Operator operator) {
        return new Observable(new OnSubscribe() {
            @Override
            public void call(Subscriber o) {
                try {
                    Subscriber st = hook.onLift(operator).call(o);
                    try {
                        // new Subscriber created and being subscribed with so 'onStart' it
                        st.onStart();
                        onSubscribe.call(st);
                    } catch (Throwable e) {
                        // localized capture of errors rather than it skipping all operators 
                        // and ending up in the try/catch of the subscribe method which then
                        // prevents onErrorResumeNext and other similar approaches to error handling
                        Exceptions.throwIfFatal(e);
                        st.onError(e);
                    }
                } catch (Throwable e) {
                    Exceptions.throwIfFatal(e);
                    // if the lift function failed all we can do is pass the error to the final Subscriber
                    // as we don't have the operator available to us
                    o.onError(e);
                }
            }
        });
    }

所以这里把Java的泛型相关的知识总结一下。

1. 什么是泛型

百度百科中的描述是:泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
Java语言引入泛型的好处是安全简单。

2.泛型的使用方式

泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法

2.1 泛型类

  • 格式:public class 类名<泛型类型1,…>
  • 注意:泛型类型必须是引用类型

看一个例子

// 泛型类:把泛型定义在类上 
public class ObjectTool { 
    private T obj; 
    public T getObj() { 
        return obj; 
    } 
    public void setObj(T obj) { 
        this.obj = obj;
    }
}
//  泛型类的测试 
public class ObjectToolDemo { 
    public static void main(String[] args) { 
        ObjectTool ot = new ObjectTool();
        ot.setObj("demo1");
        String s = ot.getObj();
        System.out.println(s);
        
        ObjectTool ot2 = new ObjectTool();
        ot2.setObj(2018);
        Integer i = ot2.getObj();
        System.out.println(i);
   }
}

输出:

demo1
2018

2.2 泛型方法

  • 格式:public <泛型类型> 返回类型 方法名(泛型类型 .)

看一个例子

public class ObjectPrint {  
    public  void show(T t) {
        System.out.println(t); 
    }
}
public class ObjectToolDemo { 
    public static void main(String[] args) { 
        ObjectPrint op = new ObjectPrint();
        op.show("demo2");
        op.show(2222);
        op.show(true);
    }
}

看下输出:

demo2
2222
true

2.3 泛型接口

  • 格式:public interface 接口名<泛型类型1…>

看个例子:

/* * 泛型接口:把泛型定义在接口上 */
public interface Inter { 
    public abstract void show(T t);
}
//实现类在实现接口的时候,我们会遇到两种情况
//第一种情况:已经知道是什么类型的了
public class InterImpl implements Inter { 
    @Override 
    public void show(String t) { 
        System.out.println(t);
    }
}
//第二种情况:还不知道是什么类型的
public class InterImpl implements Inter { 
    @Override 
    public void show(T t) { 
           System.out.println(t);
    }
}
public class InterDemo { 
    public static void main(String[] args) {
        // 第一种情况的测试
        Inter i = new InterImpl(); 
        i.show("hello"); 
        // 第二种情况的测试
        Inter i = new InterImpl(); 
        i.show("hello"); 
        Inter ii = new InterImpl(); 
        ii.show(100);
   }
}

2.4 可变参数与泛型方法可以很好的共存

看一个例子

private static  List makeList(T... args) {
    List result = new ArrayList();
    result.addAll(Arrays.asList(args));
    return result;
}

public static void main(String[] args){
    List ls = makeList("A", "B", "C");
        System.out.println(ls);
}

3.Java泛型边界问题(super和extends关键字)

Java泛型中的PECS原则
总结一下就是:

  • 如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)
  • 如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)
  • 如果既要存又要取,那么就不要使用任何通配符。

看一下大神的化简的rx代码: Rxjava深入理解之自己动手编写Rxjava

// Observer.java
// 观察者
public interface Observer {
    void onUpdate(T t);
}
// ObservableSource.java
// 被观察者(主题)接口
public interface ObservableSource {
    void subscribe(Observer observer);
}
// Observable.java
// 具体的被观察者(主题)
public class Observable implements ObservableSource {
    private T t;
    public Observable(T t) {
        this.t = t;
    }
    @Override
    public void subscribe(Observer observer) {
        // 调用订阅时,触发观察者更新
        observer.onUpdate(t); 
    }
}

observer.onUpdate(t) 这个地方就类似于把T类型,放到observer的盘子里,所以命中了第二条规则,因此使用,如果把这里的代码改成 extends,编译器是会报错的。

capture  can not be apply to T

再回头看一下RxJava的代码,你会发现非常多的,这回就好理解了吧。简单看下文中最开头的lift()。非常类似与2.4中的列子。

 Observable lift(final Operator operator)
//是泛型类型
//Observable 是lift的返回值类型
//参数只有一个operator,它的类型是 Operator
//T 是 public abstract class Observable implements ObservableSource中的类型

参考资料

  • Rxjava深入理解之自己动手编写Rxjava
  • Java泛型中的PECS原则
  • Java知识点总结(Java泛型)
  • Java中泛型的概述、使用、泛型类、泛型方法、泛型接口、泛型高级(通配符)

你可能感兴趣的:(学习RxJava之Java的泛型)