android enum 字符串,Java 枚举和 Android IntDef/StringDef 注解

[TOC]

#Java 枚举 和 Android IntDef/StringDef 注解

##翻译自原文:[Java Enum and Android IntDef/StringDef Annotation]

##使用 Integer 常量

当我们想要一个变量 x,并且它的值来自于一些已经定义好的常量。那么我们可以这样做:我们可以先定义一些常量,然后把这些常量的值赋值给 x 。现在我们假设 x 就是 `currentDay`,以及 x 可以拥有星期一到星期日的 7 个值,那么我们可以在 Java 中定义 `Integer`常量,然后这样写:

~~~

public class Main {

public static final int SUNDAY = 0;

public static final int MONDAY = 1;

public static final int TUESDAY = 2;

public static final int WEDNESDAY = 3;

public static final int THURSDAY = 4;

public static final int FRIDAY = 5;

public static final int SATURDAY = 6;

private int currentDay = SUNDAY;

public static void main(String[] args) {

// TODO Auto-generated method stub

Main obj = new Main();

obj.setCurrentDay(WEDNESDAY);

int today = obj.getCurrentDay();

switch (today) {

case SUNDAY:

System.out.println("Today is SUNDAY");

break;

case MONDAY:

System.out.println("Today is MONDAY");

break;

case TUESDAY:

System.out.println("Today is TUESDAY");

break;

case WEDNESDAY:

System.out.println("Today is WEDNESDAY");

break;

case THURSDAY:

System.out.println("Today is THURSDAY");

break;

case FRIDAY:

System.out.println("Today is FRIDAY");

break;

case SATURDAY:

System.out.println("Today is SATURDAY");

break;

default:

break;

}

}

public void setCurrentDay(int currentDay) {

this.currentDay = currentDay;

}

public int getCurrentDay() {

return currentDay;

}

}

~~~

##使用枚举

上面的代码中存在一个问题:我可以将任何 `Integer` 类型的值赋值给 `currentDay`,例如`obj.setCurrentDay(100);`

编译器不会提示任何错误,而且 `switch` 将匹配不到所对应的 `case`,这种情况是我们不希望看到的,不过 Java 提供了一个解决的方法:**Enum**,就是枚举。如果我们使用枚举重写上面的代码:

~~~

public class Main {

public enum WeekDays {

SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY

}

private WeekDays currentDay = WeekDays.SUNDAY;

public static void main(String[] args) {

// TODO Auto-generated method stub

Main obj = new Main();

obj.setCurrentDay(WeekDays.WEDNESDAY);

WeekDays today = obj.getCurrentDay();

switch (today) {

case SUNDAY:

System.out.println("Today is SUNDAY");

break;

case MONDAY:

System.out.println("Today is MONDAY");

break;

case TUESDAY:

System.out.println("Today is TUESDAY");

break;

case WEDNESDAY:

System.out.println("Today is WEDNESDAY");

break;

case THURSDAY:

System.out.println("Today is THURSDAY");

break;

case FRIDAY:

System.out.println("Today is FRIDAY");

break;

case SATURDAY:

System.out.println("Today is SATURDAY");

break;

default:

break;

}

}

public void setCurrentDay(WeekDays currentDay) {

this.currentDay = currentDay;

}

public WeekDays getCurrentDay() {

return currentDay;

}

}

~~~

现在我们有了类型的限制,`currentDay` 只能接受 `WeekDays` 类型的值,不能接受其他任何值。这比使用 `Integer`常量好了很多,所以我们会认为:我们应该多使用枚举来代替 `Integer` 常量。但是**在 Android 中使用枚举**,又会产生一个新的问题:因为 Enum 在 Java 中是一个完整的类,每个枚举类的值都是枚举类的对象,所以使用枚举要比我们之前使用 `Integer` 常量消耗更多的内存。不过即使是在老的 Android 设备上(系统版本<=2.2),关于使用枚举的一些性能问题也已经通过 JIT 编译器解决了([简单了解JIT]),现在我们是可以在 Android 应用程序中使用枚举的,但是如果我们的应用程序本身就需要消耗很多内存,或者我们的应用程序是一个游戏应用,那么我们最好使用 `Integer` 常量来代替枚举,但是这样做的话,文章开头提到的问题就又会出现,为了解决这个问题,我们可以采用 Android 提供的一种方法。

##使用 Android 注解支持库

Android 提供的方法是:使用 `com.android.support:support-annotations` ,这个官方的注解支持库中包含了许多很好的注解,可以帮助我们在编译的时候就找到错误。`IntDef` 和 `StringDef` 是包含在库中的两个关于常量的注解,我们可以用来代替**枚举**,它们可以帮助我们在编译时检查变量的赋值,就像枚举一样。下面的代码演示了如何通过 `IntDef` 来代替枚举。

~~~

public class MainActivity extends Activity {

public static final int SUNDAY = 0;

public static final int MONDAY = 1;

public static final int TUESDAY = 2;

public static final int WEDNESDAY = 3;

public static final int THURSDAY = 4;

public static final int FRIDAY = 5;

public static final int SATURDAY = 6;

@IntDef({SUNDAY, MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})

@Retention(RetentionPolicy.SOURCE)

public @interface WeekDays {}

@WeekDays int currentDay = SUNDAY;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

setCurrentDay(WEDNESDAY);

@WeekDays int today = getCurrentDay();

switch (today){

case SUNDAY:

break;

case MONDAY:

break;

case TUESDAY:

break;

case WEDNESDAY:

break;

case THURSDAY:

break;

case FRIDAY:

break;

case SATURDAY:

break;

default:

break;

}

}

public void setCurrentDay(@WeekDays int currentDay) {

this.currentDay = currentDay;

}

@WeekDays

public int getCurrentDay() {

return currentDay;

}

}

~~~

现在我们只能把 `@IntDef` 中的值赋值给 `currentDay` 和 `today`,其他的值都不行,同时编译器也会进行检查,并且提示错误。如果我们使用 Android Studio,那么当我们在写赋值代码的时候, IDE 也会提示 `@IntDef` 中的值作为建议。上面的代码是已经全部写好了的,现在我们来一步步演示,如何使用 `@IntDef`。

* 首先定义这些常量:

~~~

public static final int SUNDAY = 0;

public static final int MONDAY = 1;

public static final int TUESDAY = 2;

public static final int WEDNESDAY = 3;

public static final int THURSDAY = 4;

public static final int FRIDAY = 5;

public static final int SATURDAY = 6;

~~~

* 接着通过这些常量来定义一个 `@IntDef` 注解,并且用 `@IntDef` 注解来修饰我们自定义的注解:

~~~

@IntDef({SUNDAY, MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})

@Retention(RetentionPolicy.SOURCE)

public @interface WeekDays {}

~~~

* 设置一个使用 `@WeekDays` 修饰的变量,那么这个变量只能被 `@IntDef` 中的值所赋值,其他的值都不能赋值给它,我们可以像下面这样定义:

`@WeekDays int currentDay ;`

* 如果现在把其他的值赋值给 `currentDay`,那么编译器就会提示错误。下面的代码演示了如何用 `@WeekDays` 来修饰方法中的参数和返回值:

~~~

public void setCurrentDay(@WeekDays int currentDay) {

this.currentDay = currentDay;

}

@WeekDays

public int getCurrentDay() {

return currentDay;

}

~~~

* **@StringDef** 使用的方式是一样的:

~~~

public class MainActivity extends Activity {

public static final String SUNDAY = "sunday";

public static final String MONDAY = "monday";

public static final String TUESDAY = "tuesday";

public static final String WEDNESDAY = "wednesday";

public static final String THURSDAY = "thursday";

public static final String FRIDAY = "friday";

public static final String SATURDAY = "saturday";

@StringDef({SUNDAY, MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})

@Retention(RetentionPolicy.SOURCE)

public @interface WeekDays {}

@WeekDays String currentDay = SUNDAY;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

setCurrentDay(WEDNESDAY);

@WeekDays String today = getCurrentDay();

switch (today){

case SUNDAY:

break;

case MONDAY:

break;

case TUESDAY:

break;

case WEDNESDAY:

break;

case THURSDAY:

break;

case FRIDAY:

break;

case SATURDAY:

break;

default:

break;

}

}

public void setCurrentDay(@WeekDays String currentDay) {

this.currentDay = currentDay;

}

@WeekDays

public String getCurrentDay() {

return currentDay;

}

}

~~~

为了使用这两个注解,你必须添加 `com.android.support:support-annotations` 这个库到你的项目中,如果你使用 Android Studio 的话,可以在你的 Gradle 中添加依赖:

~~~

dependencies {

compile fileTree(include: ['*.jar'], dir: 'libs')

...

compile 'com.android.support:support-annotations:24.2.0'

}

~~~

> 注:如果您使用 appcompat 库,则无需添加 support-annotations 依赖项。因为 appcompat 库已经依赖注解库,您可以访问相关注解。---来自 [Android 文档:添加支持注解库依赖项]

[Android 文档:添加支持注解库依赖项]:https://developer.android.com/studio/write/annotations.html#adding-library

[简单了解JIT]:http://blog.dontcareabout.us/2013/03/jit-compiler.html

[Java Enum and Android IntDef/StringDef Annotation]:https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值