最近,为了充分发挥retrofit的优势,我又去看了rxjava。说是看呢,其实也就是简单的入了个门。rxjava中用到了很多泛型的知识,所以不注意很容易出错。为了把rxjava搞明白,我学习了泛型通配符。
一.关于泛型通配符
在代码中,用“?”(这个‘?’名为通配符)表示未知类型,通配符可以用作各种情况:
1.通配符做参数
import java.util.ArrayList;
import java.util.List;
public class WildCardA {
public static void fun(List<?> list){
System.out.println(list);
}
public static void main(String args[]){
List<String> list1=new ArrayList<String>();
list1.add("happy new year");
list1.add("long time no see");
fun(list1);
List<Integer> list2=new ArrayList<Integer>();
list2.add(9090);
list2.add(7799);
fun(list2);
}
}
//运行结果
[happy new year, long time no see]
[9090, 7799]
Process finished with exit code 0
2.通配符做字段
https://www.baidu.com/s?ie=utf-8
//这个url中通配符用来表示未知的拼接参数
3.通配符做局部变量的类型
先来看我的错误示范:
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
//这是一个错误实例:
public class WildCardB {
public static void main(String args[]){
ArrayList<?> arr=new ArrayList<String>();
arr.add("sss");
}
}
注意!!!不可以对list<?>使用add方法。我们new出来的arr不是真正的String类型——这就是用通配符的代价:类型丢失。我们无法确定这个arr究竟是什么类型,也就不能向其添加元素。
下面是一个正常案例
mport java.util.ArrayList;
public class WildCardC {
public static void main(String args[]) {
ArrayList<?> arr = new ArrayList<String>();
System.out.println(arr);
}
}
//结果,这个案例简直什么都没做,只是单纯的表明他可以做成员变量而已,但这样一个arr,就个get方法能用,
//一get(0)还要超下标,我着实不造该怎么用==||
[]
Process finished with exit code 0
4.通配符做返回类型
import java.util.ArrayList;
import java.util.List;
public class WildCardD {
public static List<?> fun(List<?> list){
System.out.println(list.get(0));
return list;
}
public static void main(String args[]){
List<String> list1=new ArrayList<String>();
list1.add("happy new year");
list1.add("long time no see");
fun(list1);
System.out.println(list1);
List<Integer> list2=new ArrayList<Integer>();
list2.add(9090);
list2.add(7799);
fun(list2);
}
}
//结果
happy new year
[happy new year, long time no see]
9090
Process finished with exit code 0
上界通配符
声明一个上界通配符,用使用"?"后跟extends关键字,再后跟其上界。要处理编写含float,double,Integer类型的数字列表,要指定
<? extends Number>。"?"代表的是Number类本身或者Number类的子类。List<Number>只能匹配Number类型的列表。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class WildCard_Upper {
public static void main(String args[]){
/*注意:List<? extends Number>不能使用add方法*/
//List<? extends Number> mlist=new ArrayList<>();
// mlist.add(new Integer(30));
List<Integer> mlist=Arrays.asList(1,2,3);
/*Arrays.asList()方法将数组转化为list*/
System.out.println("sum="+sumOfList(mlist));
List<Double> mlist1=Arrays.asList(1.1,2.3,3.6);
System.out.println("sum1="+sumOfList(mlist1));
}
public static double sumOfList(List<? extends Number> list){
double s=0.0;
for(Number n:list){
s+=n.doubleValue();
}
return s;
}
}
//结果
sum=6.0
sum1=7.0
Process finished with exit code 0
下界通配符
上界通配符将未知类型限定为该类型的特定类型或子类型,类似地,下界通配符将未知类型限定为特定类型或该类的超类型。下界通配符的表示使用“?”后接Super关键字,再后跟其下界。
//将1——10添加到列表
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i);
}
}
二.关于 rxjava
实际上,关于通配符的内容还有许多,比如通配符的捕获,都是需要理解和掌握的。但,饭要一口一口吃,事要一件一件做。此次总结泛型通配符,只是为了更好地理解rxjava,实现rxjava的简单运用,乃至rxjava与retrofit结合的写法。因此为了突出重点,我们这就开始回顾rxjava,以免一次性学的太多太杂,反不得学以致用。
这是我看的关于rxjava的一篇介绍,讲明了概念与基本方法。该文很长,很详细,但看完后你至少应该理解的是:1.什么是观察者模式 2.rxjava的优势是什么 3.rxjava的本质是异步。理解这几点后我就开始使用它。这是MainActivity中的全部代码
package com.example.lenovo.rxjavademo;
import android.nfc.Tag;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.Scheduler;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import static io.reactivex.Observable.create;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建观察者,产生事件
io.reactivex.Observable.create(new ObservableOnSubscribe<String>(){
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("rxjava NB!");
e.onNext("onNext方法一次发送一条信息");
e.onNext("可以多次调用onNext方法");
//停止接收信息
e.onComplete();
}//线程调度器,将耗时的操作放到一个新线程里,主线程就只负责显示,这样就不会有卡顿
//也就是接收者在主线程,发送者在其他线程,subscribeOn操作符的作用是设置线程调度器
}).subscribeOn(Schedulers.newThread()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i("0000","在哪个线程:"+Thread.currentThread().getName());
}
@Override
public void onNext(String value) {
Log.i("1111",value);
}
@Override
public void onError(Throwable e) {
Log.i("2222","error:"+e);
}
@Override
public void onComplete() {
Log.i("3333","compelete");
}
});
}
}
这只是最简单的一个使用案例,但也体现了rxjava的优点:可以轻松的切换线程,增加了代码的简洁性和使用的流畅性。本篇就到这里,希望大家和我一起继续深入学习rxjava。下一步,就是将rxjava与retrofit结合起来。