美文网首页
学习RxJava之Java的泛型

学习RxJava之Java的泛型

作者: 沙夏cc | 来源:发表于2018-11-23 15:42 被阅读0次

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

    public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
            return new Observable<R>(new OnSubscribe<R>() {
                @Override
                public void call(Subscriber<? super R> o) {
                    try {
                        Subscriber<? super T> 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<T> { 
        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<String> ot = new ObjectTool<String>();
            ot.setObj("demo1");
            String s = ot.getObj();
            System.out.println(s);
            
            ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
            ot2.setObj(2018);
            Integer i = ot2.getObj();
            System.out.println(i);
       }
    }
    

    输出:

    demo1
    2018
    

    2.2 泛型方法

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

    看一个例子

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

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

    看一个例子

    private static <T> List<T> makeList(T... args) {
        List<T> result = new ArrayList<T>();
        result.addAll(Arrays.asList(args));
        return result;
    }
    
    public static void main(String[] args){
        List<String> 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<T> {
        void onUpdate(T t);
    }
    // ObservableSource.java
    // 被观察者(主题)接口
    public interface ObservableSource<T> {
        void subscribe(Observer<? super T> observer);
    }
    // Observable.java
    // 具体的被观察者(主题)
    public class Observable<T> implements ObservableSource<T> {
        private T t;
        public Observable(T t) {
            this.t = t;
        }
        @Override
        public void subscribe(Observer<? super T> observer) {
            // 调用订阅时,触发观察者更新
            observer.onUpdate(t); 
        }
    }
    

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

    capture <? extends T> can not be apply to T
    

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

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

    参考资料

    相关文章

      网友评论

          本文标题:学习RxJava之Java的泛型

          本文链接:https://www.haomeiwen.com/subject/sxbjqqtx.html