唠嗑
好久不写博客了,刚起笔还不知道说些什么呢,目前安卓开发所要具备的语言林林总总有这么几种:java必备,kotlin必备,c和c++作为安卓高级进阶语言,dart作为目前最火的跨平台(flutter)的开发语言也要学。
虽然看起来很重,会感觉要学的好多好多啊,其实我想说的是,最重要的还是把一种语言学精学明白,这样接下来的路会很好走。真的尝试过精通一种特长的人,以后不管学什么,甚至打王者都不掉星了,好啦,我们一起努力,给自己加个油。不扯淡了。
概述
先问问自己,为什么我们要学泛型,谈谈我自己用泛型的感受,使用泛型搭建架构,会让代码更加灵活,提高了代码的可重用性,泛型是在JDK 5中引入进来的,我们平时用的数据集合类大多都是被泛型化的,比如ArrayList(),这里的T就是我们所指的泛型。
泛型主要分为两大种,一种是泛型类,也就是修饰类的,另一种是修饰方法的,也就是泛型方法
定义
这是百度百科的定义:泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型
走起
下面开始聊代码示例
第一种 泛型类的定义
举一个例子,BaseBean都在用吧,从服务器请求回来的大部分格式应该都是这样的:
//成功
{
code:"响应码",
message:"响应信息",
data:{
name:"张三",
age: 18
}
}
//
{
code:"响应码",
message:"响应信息",
data:{
name:"张三",
age: 18
}
}
我想大家对json格式都特别熟悉吧,大家在项目中一般都会这样创建,这种定义就叫泛型类的定义:
public class LoginWrapper<DDDD,EEEE> {
private int code;
private String message;
private DDDD d;
private EEEE e;
}
public class LoginResponseBean{
private String name;
private int age;
}
这里我强调一下,泛型的字母没有确定的,可以这样说,你可以用任何字母,甚至可以用小写(不建议,毕竟你写一个private d d;阅读性很差)。一般用的泛型字母都是想要表达类型的英文首字母,这样阅读性强一点,最能表达这个的案例就是HashMap<K,V>,K就代表key,V就代表value
我在有一篇博客里写的对RecyclerView的适配器的扩展,里面也是用了泛型,大家有兴趣的可以去看一看首发-----RecyclerView的暴力封装适配器
第二种 方法函数的定义
private static <S> S getName(S s){
}
private static <S,T> S getName(S s,T t){
return s;
}
第三种 限定类型
限定泛型,也就是你传入的泛型类必须是我规定的类型,比如我规定泛型是属于String类型的,你就比如传String类型,我规定的是View类型,你传的就必须是属于View的
private <V extends View> ImageView getView(V v){
return (ImageView) v;
}
这里还要强调一点,限定可以限定多个,但是只能一个限定类,或者多个接口,而且有类的话,必须类在最前面
interface Haha {
}
interface XiXi {
}
private <V extends View & Haha & XiXi> ImageView getView(V v) {
return (ImageView) v;
}
第四种 泛型上届
这个说起来就有点小绕了,建议多看几遍,比如有这么几个类,A,B,C三个类,B继承了A,C继承了B,然后又创建了一个泛型类Letter如下: //看注释
public class Letter<T> {
//泛型变量
private T t;
//getter
public T getT(){
return t;
}
//setter
public void setT(T t) {
this.t = t;
}
//上届泛型方法
public static void print(Letter<? extends B> letter){
System.out.println("-----");
}
public static void main(String[] args) {
Letter<A> a=new Letter<>();
Letter<B> b=new Letter<>();
Letter<C> c=new Letter<>();
print(a); //报错
print(b);//可以写入
print(c); //可以写入,说明方法参数Letter<? extends B>是以B类作为上届写入的,他的子类可以正常传入,这时候如果有个D类继承C,也是正常可以的
Letter<? extends B> letter=new Letter<>();
A acl=new A();
B bcl=new B();
C ccl=new C();
letter.setT(acl);//报错
letter.setT(bcl);//报错
letter.setT(ccl);//报错,说明上届(extends)泛型不支持setter写入
A a11=letter.getData(); //可以正常获取
B b11=letter.getData();//可以正常获取,即只能正常获取B以及B的父类
C c11=letter.getData();//报错
Object o=letter.getData();//正常
}
}
多看几遍,实在不行自己试一试,实践出真理
泛型下届(建议和上一个只记住一个,一起记容易记混)
public class Letter<T> {
private T t;
public void getT() {
}
public T getData(){
return t;
}
public void setT(T t) {
this.t = t;
}
public static void print(Letter<? super B> letter){
System.out.println("-----"+letter.getClass().getName());
}
public static void main(String[] args) {
Letter<A> a=new Letter<>();
Letter<B> b=new Letter<>();
Letter<C> c=new Letter<>();
print(a);//正常
print(b); //正常 说明方法参数Letter<? super B>是以B类作为下届写入的,他以及父类可以正常传参
print(c); //报错
Letter<? super B> letter=new Letter<>();
A acl=new A();
B bcl=new B();
C ccl=new C();
letter.setT(acl);//报错
letter.setT(bcl);//正常
letter.setT(ccl);//正常 写入B以及自己的子类可以正常写入
A a11=letter.getData();//报错
B b11=letter.getData();//报错
C c11=letter.getData();//报错 super 下届 不支持读
Object o=letter.getData();//正常
}
}
约束
1,泛型不能实例
new T();//错误
2,静态域不能使用泛型
因为泛型类对象在实例的时候才确定类型,而在运行的时候,static变量是先被执行的,这时候虚拟机根本不知道T是什么玩意
private static T t;//错误
3,基本类型不能作为泛型参数传递的,基本类型不能当做对象用,可以用包装类Interger
new BaseBean<int>(); //错误
4,泛型类不能用instanceof判断类型
Basebean<Double> baseBean;
if(baseBean instanceof Basebean<Double>)//报错{
}
5,泛型不能不活泛型类对象
public <T extents Throwable> void do(T t){
try{}
catch(T t)//报错{}
}
但是可以这样写
public <T extents Throwable> void do(T s) throws T{
try{}
catch(Throwable t){
throw x;//把参数返回
}
}