泛形和枚举

泛型

定义

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

兼容版本

java 1.5

解决什么问题

Java语言引入泛型的好处是安全简单。

在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

泛型的几个特点

  • 泛型的好处是在编译的时候检查类型安全。

    List<Integer> li = new ArrayList<Integer>();
    li.put(“123”);
    

这行代码在编译时期就会报错。

  • 所有的强制转换都是自动和隐式的。

该代码不使用泛型:

List li = new ArrayList();
li.put(new Integer(3));
Integer i = (Integer) li.get(0);

该代码使用泛型:

List<Integer> li = new ArrayList<Integer>();
li.put(new Integer(3));
Integer i = li.get(0);

可以看出,在使用泛型的地方,省去了类型强制转换的麻烦

  • 泛型不是协变的

关于泛型的混淆,一个常见的来源就是假设它们像数组一样是协变的。其实它们不是协变的。List 不是 List 的父类型。

泛型的使用

泛型类

这时Stack的源码,我们这里仅看和繁星相关的两个操作

public class Stack<E> extends Vector<E> {

 @SuppressWarnings("unchecked")
 public synchronized E pop() {
    if (elementCount == 0) {
        throw new EmptyStackException();
    }
    final int index = --elementCount;
    final E obj = (E) elementData[index];
    elementData[index] = null;
    modCount++;
    return obj;
 }

 public E push(E object) {
    addElement(object);
    return object;
 }
}
泛型接口
public interface HasComponent<C> {
    C getComponent();
}

接口实现

public class BusHistoryDetailActivity implements HasComponent<HistoryMissionDetailComponent> {
   @Override
public HistoryMissionDetailComponent getComponent() {
    return component;
}
}

在实现类中,具体指定了泛型的具体类型。

泛型方法
protected <C> C getComponent(Class<C> componentType) {
    return componentType.cast(((HasComponent<C>) getActivity()).getComponent());
}

这个方法是我们fragment中,获取在 activity里面初始化的Component,如果没有泛型的话,我们需要根据具体的需要,写好多方法去获取Component。从这个角度看,泛型提高了代码的重用性。

枚举

定义

枚举在C/C++/c#中,是一个被命名的整型常数的集合。
仿照上述定义,那么在java中枚举是一个被命名的实例对象的集合。
用于表示属于某一组的几个选择。

兼容版本

java 1.5

解决什么问题

  • 类型安全

当程序遇到几个不同选择而进行不同的逻辑控制的时候。在1.5之前的版本中,一般采用定义一些常量来解决。虽然采用常量也能解决问题,但容易出错。采用枚举解决问题,在编译时就能解决非法赋值得问题,代码更不容易出错。

举个例子

比如我们安排一周的任务,用常量是这样的

public String getTask(int dayInWeek){
    switch (dayInWeek){
        case 1:
            return "休息";
        case 2:
            return "上班";
        case 3:
            return "上班";
        case 4:
            return "上班";
        case 5:
            return "上班";
        case 6:
            return "上班";
        case 7:
            return "休息";

    }
    return "诸事不宜";
}

或许你会觉得这样有点怪怪的,毕竟谜之数字,让读程序的人产生迷惑,然后你就采用了下面的方式

public interface DayInWeekInterFace{
    int SUNDAY = 1;
    int MONDAY = 2;
    int TUESDAY = 3;
    int WEDNESDAY = 4;
    int THURSDAY = 5;
    int FRIDAY = 6;
    int SATURDAY = 7;
}

public String getTaskByContract(int dayInWeek){
    switch (dayInWeek){
        case DayInWeekInterFace.SUNDAY:
            return "休息";

        case DayInWeekInterFace.MONDAY:
            return "上班";
        case DayInWeekInterFace.TUESDAY:
            return "上班";
        case DayInWeekInterFace.WEDNESDAY:

            return "上班";
        case DayInWeekInterFace.THURSDAY:
            return "上班";
        case DayInWeekInterFace.FRIDAY:
            return "上班";
        case DayInWeekInterFace.SATURDAY:
            return "休息";

    }
    return "诸事不宜";
}

这样看上去舒服多了,但是,我们调用的时候,不小心传错了数据,getTaskByContract(18)获取到的结果是,今天诸事不宜,所以你就决定去山里躲一下晦气,这是一种很迷信的做法

为了防止你在不该爬山的时候跑到山上去,我们采用了这样的做法

public enum DayInWeek {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY;
}
public String getTaskByEnum(DayInWeek dayInWeek){

    switch (dayInWeek){
        case SUNDAY:
            return "休息";

        case MONDAY:
            return "上班";
        case TUESDAY:
            return "上班";
        case WEDNESDAY:

            return "上班";
        case THURSDAY:
            return "上班";
        case FRIDAY:
            return "上班";
        case SATURDAY:
            return "休息";

    }
    return "诸事不宜";
}

这样就再也不用担心诸事不宜的问题了

关于枚举的争议

在Dalvik虚拟机还没JIT编译器优化代码的时候,不建议android平台使用枚举类型,因为和使用整形常量相比,这种设计带来的内存和性能损失更大。这就是为什么在一些老版本的Android API中还存在如此多的整形常量的原因。如今有了更强大的JIT编译器以及不断改进的Dalvik虚拟机,开发者不必担心这个问题,放心大胆地使用类型安全枚举即可。(摘自android编程实战)

java语言特性

  • 支持构造方法传值(建议使用,而非默认整型值 value)

  • 可以定义方法

来个��

public enum ZMTaskType {

ZOUME_BUS_ORIGIN(1, "定点巴士任务",""),                  //
ZOUME_BU_CUSTOM(5, "巴士任务",""),                  //
SHUTTLE(2, "接驳任务",""),                         //
SPECIAL_CAR_SHARE(3, "快车任务(拼车)",""),            //
SPECIAL_CAR_CHARTERED(4, "快车任务(包车)",""),         //
OFFICIAL_CAR_MILEAGE(6, "公务用车任务","单程用车"),        //
OFFICIAL_CAR_TIMING(7, "公务用车任务","分时租车"),
EXCLUSIVE_CAR_WAY(8, "专车任务","单程"),            //
EXCLUSIVE_CAR_TIME(9, "专车任务","分时");       //

private int type;
private String title;
private String subTitle;

ZMTaskType(int type, String title,String subTitle) {
    this.type = type;
    this.title = title;
    this.subTitle = subTitle;
}

/**
 * 根据任务类型编号获取任务字符串
 *
 * @param type
 * @return
 */
public static String getTaskTypeStrByType(int type) {
    String taskTypeStr = "";
    for (ZMTaskType taskType : ZMTaskType.values()) {
        if (type == taskType.type) {
            taskTypeStr = taskType.title;
        }
    }
    return taskTypeStr;
}

/**
 * 根据类型获取枚举
 *
 * @param type
 * @return
 */
public static ZMTaskType getEnumByType(int type) {
    ZMTaskType zmTaskType = null;
    for (ZMTaskType taskType : ZMTaskType.values()) {
        if (type == taskType.type) {
            zmTaskType = taskType;
        }
    }
    return zmTaskType;
}

public String getTypeStr() {
    return title;
}

public String getSubTitle(){
    return subTitle;
}
}

在这个例子中,我们采用了枚举来表示不同类型的业务类型。
可以看到,我们的业务类型,没有0这个类型。
所以构造方法传值,可以给枚举赋值任何数值(不必向c那样必须是从0开始的连续整型)。
另外,我们还可以在枚举中定义业务类型的相关描述,通过一个方法可以很方便的获取与业务类型对应的业务描述。

总结

泛形和枚举,主要的作用就是在编译时期执行类型安全检查,让我们的错误出在编译时期而非运行时期,提高开发效率。

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值