android框架之基础泛型

今天讲讲泛型,也许很多人会说这个都懂,但是还是想回忆下,它也是在写框架中必用的一个知识点,系统的学习一下,我大概对泛型如下几大分类进行讲解!

android框架之基础泛型_第1张图片

泛型出现的好处:

泛型是在jdk1.5后出现的,在jdk1.4之前是这么玩的

package com.generic;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by admin on 2017/2/3.
 */
public class GenericDemo1 {
    public static  void add(){
        List list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add(1);//1自动装箱成对象
    }
}
我们发现List集合中存储了String和Integer二种类型,也许在存储你会发现没啥问题,但是我们存储数据肯定是要拿出来使用的,我们如果对这个集合进行遍历:
Iterator iterator = list.iterator();
while (iterator.hasNext()){
    Object obj = iterator.next();
    Log.e(TAG,"obj="+obj);
}
我们发现获取集合中的每个元素返回的是Object,如果这个时候你想对获取的元素进行操作,比如截取等,你会发现最后一个从集合中获取的元素是1,哪它怎么对字符串进行截取等操作啊,哪你是不是要对obj进行类型操作
if(obj instanceof String){
    //截取字符串操作
}
这样每次都要去判断类型,然后做下面的操作,然后obj是String类型,那么obj就要强转成String,如果obj不是String类型,那么你强转会造成错误的,程序可能直接挂了,这就是为啥出现泛型,因为泛型是出现在编译时期,会避免在运行时候程序因为强转导致程序挂了,多麻烦啊,所以泛型出现的好处有二点

1:避免了强转

2:把运行时期改成了在编译时期检查语法

在jdk源码中到处使用了泛型,特别是在集合中.我们在jdk1.5后使用集合一般就是使用了泛型

android框架之基础泛型_第2张图片

你会发现我集合中存储的是String类型,你存储一个进去在编译器就报错了,这就是使用泛型的好处之一

泛型类使用

泛型类意思是泛型定义在类上,

格式:public class A

比如我们在操作数据库的时候在dao层你不知道你操作的是那个对象,所以我们一般都是使用泛型,

package com.generic;
/**
 * Created by admin on 2017/2/3.
 */
public  class BaseDao<T> {
    public void insert(T entity){

    }
    public void  update(T entity, T where){
        
    }
}
User.java
package com.generic;
/**
 * Created by admin on 2017/2/3.
 */
public class User {
    private String id;
    private String name;
    private int age;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
使用:
BaseDao baseDao = new  BaseDao();
User user = new User();
baseDao.insert(user);
这是在操作User对象,你也可以操作Person等其他对象啊,这就是为啥泛型定义在类上,比如我们自定义一个容器,里层还是使用List集合:
package com.generic;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by admin on 2017/2/3.
 */
public class CustomList<T> {
    public List<T> list = new ArrayList<>();
    public void add(T t){
        list.add(t);
    }
}

框架中泛型用的最多了,平时到的用的很少,但是我们菜鸟也是有梦想的,也是想写框架的,所以必须得学习这些框架的基础知识,

在泛型类型参数化不能使用继承,什么意思呢?


上面我们看到都报错了在程序编译时期,如下写法:

android框架之基础泛型_第3张图片

你会发现objs4添加Integer类型就会报错,objs3添加Integer就不会报错,

List objs4 = new ArrayList();
这种写法是泛型推断,
List objs3 = new ArrayList();
这种写法就不是了,所以objs4在编译时期检查语法更加严格!

泛型接口

泛型接口就是泛型定义在接口上:

package com.example.dao;
/**
 * Created by admin on 2017/1/18.
 */
public interface IBaseDao<T> {
    /**
     * 插入数据
     * @param entry
     * @return
     */
    long insert(T entry);
    /**
     * @param entity 更新实体对象
     * @param where 更新条件
     * @return
     */
    int  update(T entity, T where);
}
这个是操作数据库的dao层,上面定义的是接口,所以要使用必须有具体的类去实现这个接口
package com.generic;
import android.util.Log;
/**
 * Created by admin on 2017/2/3.
 */
public class BaseDao implements IBaseDao {
    private static final String TAG ="BaseDao" ;
    @Override
    public long insert(User entry) {
        Log.e(TAG,"name="+entry.getName());
        return 0;
    }
    @Override
    public int update(User entity, User where) {
        return 0;
    }
}
使用:
BaseDao baseDao = new  BaseDao();
User user = new User();
baseDao.insert(user);
上面的BaseDao是实现了IBaseDao接口,并且已经确定了泛型具体的类型就是User,如果这个时候还没确定具体的类型的话,要这么使用:
package com.generic;
/**
 * Created by admin on 2017/2/3.
 */
public class BaseDao<T> implements IBaseDao<T> {
    private static final String TAG ="BaseDao" ;
    @Override
    public long insert(T entry) {
        return 0;
    }
    @Override
    public int update(T entity, T where) {
        return 0;
    }
}
UserDao是继承了BaseDao,
package com.generic;
import android.util.Log;
/**
 * Created by admin on 2017/2/3.
 */
public class UserDao extends BaseDao {
    private static final String TAG = "UserDao";
    @Override
    public long insert(User entry) {
        Log.e(TAG,"插入数据");
        return super.insert(entry);
    }
    @Override
    public int update(User entity, User where) {
        return super.update(entity, where);
    }
}
使用:
UserDao baseDao = new  UserDao();
User user = new User();
baseDao.insert(user);

如果你在那个类上确定了操作那个类(泛型)就可以直接写,不然就写

泛型方法:

泛型方法是泛型定义在方法上,我们做android发现老是去findViewById()显得很麻烦,于是我们可以使用泛型在父类中写个通用的findViewById(),然后在每个子类activity中去使用:

package com.generic;
import android.app.Activity;
/**
 * Created by admin on 2017/2/3.
 */
public class BaseActivity extends Activity {
    public <T> T $(int resId){
        return (T) findViewById(resId);
    }
}
子类使用:
button = $(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.e(TAG,"button点击");
    }
});
泛型方法分几种,一种是有返回值,一种是没返回值,还有就是形参中带泛型

没有返回值的泛型方法:

package com.generic;
/**
 * Created by admin on 2017/2/3.
 */
public class GenericDemo1 {
    public <T> void print(T t){
        System.out.print(t);
    }
}

其中public后面void前面,表示的是

通过反射绕过编译器检查

List list = new ArrayList<>();
Classextends List> clazz = list.getClass();
try {
    Method method = clazz.getMethod("add",Object.class);
    try {
        method.invoke(list,1);
        method.invoke(list,2);
        method.invoke(list,3);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}
上面是通过反射绕过编译器检查对集合进行操作,集合明明是存储了String类型,但是通过反射我在集合中存储了Integer类型,编译器检查是没问题的,在运行时期会擦除泛型类型,

泛型通配符使用

比如现在有一个需求就是打印出集合中所有的元素,但是你作为leader的话,肯定在想写的代码不能太垃圾要考虑各种情况,比如如果集合中全是String类型或者Integer类型或者自定义对象类型怎么办?我会针对每种都要写一个方法么?哪你肯定这个leader不会做的太久了,于是leader想到了一个解决方法:

package com.generic;
import java.util.Collection;
/**
 * Created by admin on 2017/2/3.
 */
public class GenericDemo1 {
    public static void printCollection(Collection collections){
        if(collections!=null&&!collections.isEmpty()){
            for(Object obj:collections){
                System.out.print(obj);
            }
        }
    }
}

使用:

android框架之基础泛型_第4张图片

使用发现这不行啊,我形参传的是Object类型,但是我实际参数传递的是String类型,这个时候leader就想到了泛型通配符,可以匹配任意类型用  "?"表示

package com.generic;
import android.util.Log;
import java.util.Collection;
/**
 * Created by admin on 2017/2/3.
 */
public class GenericDemo1 {
    private static final String TAG ="GenericDemo1" ;
    public static void printCollection(Collection collections){
        if(collections!=null&&!collections.isEmpty()){
            for(Object obj:collections){
                Log.e(TAG,"obj="+obj);
            }
        }
    }
}
使用:
List list = new ArrayList<>();
list.add("1");
list.add("12");
list.add("123");
GenericDemo1.printCollection(list);
这样就没问题了!

但是需求又来了,我一个集合中需要存某一类型,比如我要存储的是Person的子类,

package com.generic;
import android.util.Log;
/**
 * Created by admin on 2017/2/3.
 */
public class Person {
    private static final String TAG = "Person";
    public String name;
    public int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void smoke(){
        Log.e(TAG,name+"-"+age+"岁就开始"+"抽中华烟");
    }
}
子类Stu.java
package com.generic;
/**
 * Created by admin on 2017/2/3.
 */
public class Stu extends Person {
    public Stu(String name, int age) {
        super(name, age);
    }
}
使用:
List persons = new ArrayList<>();
for(int i=0;i<10;i++){
    Stu stu = new Stu("zhouguizhi",18+i);
    persons.add(stu);
}
add(persons);

public void add(Listextends Person> persons){
     for(Person p:persons){
         p.smoke();
     }
}
? extends Person表示的是集合中存储的是Person以及Person的子类起到限制作用,不是什么对象都能存储

如果集合中存储的是某一类型以及这类型的父类


你可能感兴趣的:(架构之路)