进java中了解枚举

 

上网查了一下,发现这篇文章讲的很好,学习学习!!!~~~~

枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字enum来定义一个枚举类。下面就是一个典型枚举类型的定义:

Java代码 复制代码
  1. public enum Color{   
  2.     RED,BLUE,BLACK,YELLOW,GREEN   
  3. }  
public enum Color{
    RED,BLUE,BLACK,YELLOW,GREEN
}

显然,enum很像特殊的class,实际上enum声明定义的类型就是一个类。 而这些类都是类库中Enum类的子类(java.lang.Enum<E>)。它们继承了这个Enum中的许多有用的方法。我们对代码编译之后发现,编译器将enum类型单独编译成了一个字节码文件:Color.class。

Color字节码代码 复制代码
  1. final enum hr.test.Color {   
  2.      
  3.  // 所有的枚举值都是类静态常量   
  4.  public static final enum hr.test.Color RED;   
  5.  public static final enum hr.test.Color BLUE;   
  6.  public static final enum hr.test.Color BLACK;   
  7.  public static final enum hr.test.Color YELLOW;   
  8.  public static final enum hr.test.Color GREEN;   
  9.     
  10. private static final synthetic hr.test.Color[] ENUM$VALUES;   
  11.      
  12.   // 初始化过程,对枚举类的所有枚举值对象进行第一次初始化   
  13.  static {   
  14.        0  new hr.test.Color [1]    
  15.       3  dup   
  16.       4  ldc <String "RED"> [16] //把枚举值字符串"RED"压入操作数栈   
  17.       6  iconst_0  // 把整型值0压入操作数栈   
  18.       7  invokespecial hr.test.Color(java.lang.String, int) [17] //调用Color类的私有构造器创建Color对象RED   
  19.      10  putstatic hr.test.Color.RED : hr.test.Color [21]  //将枚举对象赋给Color的静态常量RED。   
  20.       .........  枚举对象BLUE等与上同   
  21.     102  return   
  22. };   
  23.      
  24.   // 私有构造器,外部不可能动态创建一个枚举类对象(也就是不可能动态创建一个枚举值)。   
  25.  private Color(java.lang.String arg0, int arg1){   
  26.      // 调用父类Enum的受保护构造器创建一个枚举对象   
  27.      3  invokespecial java.lang.Enum(java.lang.String, int) [38]   
  28. };   
  29.     
  30.  public static hr.test.Color[] values();   
  31.      
  32.    // 实现Enum类的抽象方法     
  33.   public static hr.test.Color valueOf(java.lang.String arg0);   
  34. }  
final enum hr.test.Color {
  
 // 所有的枚举值都是类静态常量
 public static final enum hr.test.Color RED;
 public static final enum hr.test.Color BLUE;
 public static final enum hr.test.Color BLACK;
 public static final enum hr.test.Color YELLOW;
 public static final enum hr.test.Color GREEN;
 
private static final synthetic hr.test.Color[] ENUM$VALUES;
  
  // 初始化过程,对枚举类的所有枚举值对象进行第一次初始化
 static {
       0  new hr.test.Color [1] 
      3  dup
      4  ldc <String "RED"> [16] //把枚举值字符串"RED"压入操作数栈
      6  iconst_0  // 把整型值0压入操作数栈
      7  invokespecial hr.test.Color(java.lang.String, int) [17] //调用Color类的私有构造器创建Color对象RED
     10  putstatic hr.test.Color.RED : hr.test.Color [21]  //将枚举对象赋给Color的静态常量RED。
      .........  枚举对象BLUE等与上同
    102  return
};
  
  // 私有构造器,外部不可能动态创建一个枚举类对象(也就是不可能动态创建一个枚举值)。
 private Color(java.lang.String arg0, int arg1){
     // 调用父类Enum的受保护构造器创建一个枚举对象
     3  invokespecial java.lang.Enum(java.lang.String, int) [38]
};
 
 public static hr.test.Color[] values();
  
   // 实现Enum类的抽象方法  
  public static hr.test.Color valueOf(java.lang.String arg0);
}
 

下面我们就详细介绍enum定义的枚举类的特征及其用法。(后面均用Color举例)

1、Color枚举类就是class,而且是一个不可以被继承的final类。其枚举值(RED,BLUE...)都是Color类型的类静态常量, 我们可以通过下面的方式来得到Color枚举类的一个实例:
                                                         Color c=Color.RED;
注意:这些枚举值都是public static final的,也就是我们经常所定义的常量方式,因此枚举类中的枚举值最好全部大写。

2、即然枚举类是class,当然在枚举类型中有构造器,方法和数据域。但是,枚举类的构造器有很大的不同:
      (1) 构造器只是在构造枚举值的时候被调用。

Java代码 复制代码
  1. enum Color{   
  2.                 RED(255,0,0),BLUE(0,0,255),BLACK(0,0,0),YELLOW(255,255,0),GREEN(0,255,0);   
  3.                 //构造枚举值,比如RED(255,0,0)   
  4.                 private Color(int rv,int gv,int bv){   
  5.                  this.redValue=rv;   
  6.                  this.greenValue=gv;   
  7.                  this.blueValue=bv;   
  8.                 }   
  9.   
  10.                 public String toString(){  //覆盖了父类Enum的toString()   
  11.                 return super.toString()+"("+redValue+","+greenValue+","+blueValue+")";   
  12.                 }   
  13.       
  14.                 private int redValue;  //自定义数据域,private为了封装。   
  15.                 private int greenValue;   
  16.                 private int blueValue;   
  17.  }  
enum Color{
                RED(255,0,0),BLUE(0,0,255),BLACK(0,0,0),YELLOW(255,255,0),GREEN(0,255,0);
                //构造枚举值,比如RED(255,0,0)
                private Color(int rv,int gv,int bv){
                 this.redValue=rv;
                 this.greenValue=gv;
                 this.blueValue=bv;
                }

                public String toString(){  //覆盖了父类Enum的toString()
                return super.toString()+"("+redValue+","+greenValue+","+blueValue+")";
                }
   
                private int redValue;  //自定义数据域,private为了封装。
                private int greenValue;
                private int blueValue;
 }

      (2) 构造器只能私有private,绝对不允许有public构造器。 这样可以保证外部代码无法新构造枚举类的实例。这也是完全符合情理的,因为我们知道枚举值是public static final的常量而已。 但枚举类的方法和数据域可以允许外部访问。

Java代码 复制代码
  1. public static void main(String args[])   
  2. {   
  3.         // Color colors=new Color(100,200,300);  //wrong   
  4.            Color color=Color.RED;   
  5.            System.out.println(color);  // 调用了toString()方法   
  6. }     
public static void main(String args[])
{
        // Color colors=new Color(100,200,300);  //wrong
           Color color=Color.RED;
           System.out.println(color);  // 调用了toString()方法
}   
 

3、所有枚举类都继承了Enum的方法,下面我们详细介绍这些方法。
       (1)  ordinal()方法: 返回枚举值在枚举类种的顺序。这个顺序根据枚举值声明的顺序而定。
                 Color.RED.ordinal();  //返回结果:0
                 Color.BLUE.ordinal();  //返回结果:1
       (2)  compareTo()方法: Enum实现了java.lang.Comparable接口,因此可以比较象与指定对象的顺序。Enum中的compareTo返回的是两个枚举值的顺序之差。当然,前提是两个枚举值必须属于同一个枚举类,否则会抛出ClassCastException()异常。(具体可见源代码)
                 Color.RED.compareTo(Color.BLUE);  //返回结果 -1
       (3)  values()方法: 静态方法,返回一个包含全部枚举值的数组。
                 Color[] colors=Color.values();
                 for(Color c:colors){
                        System.out.print(c+",");
                 }//返回结果:RED,BLUE,BLACK YELLOW,GREEN,
       (4)  toString()方法: 返回枚举常量的名称。
                 Color c=Color.RED;
                 System.out.println(c);//返回结果: RED
       (5)  valueOf()方法: 这个方法和toString方法是相对应的,返回带指定名称的指定枚举类型的枚举常量。
                 Color.valueOf("BLUE");   //返回结果: Color.BLUE
       (6)  equals()方法: 比较两个枚举类对象的引用。

Java代码 复制代码
  1. //JDK源代码:       
  2. public final boolean equals(Object other) {   
  3.         return this==other;   
  4. }               
//JDK源代码:    
public final boolean equals(Object other) {
        return this==other;
}             


4、枚举类可以在switch语句中使用。

Java代码 复制代码
  1. Color color=Color.RED;   
  2. switch(color){   
  3.         case RED: System.out.println("it's red");break;   
  4.         case BLUE: System.out.println("it's blue");break;   
  5.         case BLACK: System.out.println("it's blue");break;   
  6. }  
<think>我们首先解析用户的需求:用户希望了解Java枚举类型的详细使用方法,并结合之前提供的两个代码片段(@RequiresPermission注解和LocationRequest封装)分析其中的逻辑与实现。步骤:1.详细讲解Java枚举类型(Enum)的使用方法,包括基本语法、常用方法、枚举与接口、枚举集合等。2.结合提供的代码片段,分析其中与枚举相关的部分。注意:在提供的代码片段中并没有直接使用枚举,但用户要求结合这些代码片段分析逻辑与实现。因此,我们需要找到关联点。-第一个代码片段:使用了@RequiresPermission注解,该注解的anyOf属性是一个数组,数组元素是权限字符串(如ACCESS_COARSE_LOCATION)。虽然这些权限字符串不是枚举,但我们可以类比枚举的使用(如定义一组常量)。-第二个代码片段:使用了Settings.Secure中的常量(如LOCATION_MODE_OFF),这些常量是int类型,但我们可以讨论如果使用枚举会如何改。3.如果代码中没有直接使用枚举,我们可以建议如何用枚举或对比常量与枚举的差异。因此,回答将分为两部分:第一部分:Java枚举类型详解第二部分:结合代码片段分析(重点分析如何用枚举思想改常量,或者说明这些常量在Java中通常如何被组织)注意:用户要求解析代码逻辑,所以除了枚举知识,还要回应代码的逻辑。具体结构:I.Java枚举类型详解A.枚举的基本语法B.枚举的常用方法(name(),ordinal(),values(),valueOf())C.枚举的高级特性(构造函数、方法、实现接口等)D.枚举集合(EnumSet和EnumMap)II.结合代码片段分析A.分析第一个代码片段中的@RequiresPermission注解-注解中的权限字符串(ACCESS_COARSE_LOCATION等)通常是定义在Manifest类中的字符串常量。我们可以对比枚举:如果使用枚举,可以如何定义这些权限?-讨论anyOf属性的设计:它是一个字符串数组,如果设计为枚举数组,会有什么好处?B.分析第二个代码片段中的LOCATION_MODE常量-当前代码使用int常量(LOCATION_MODE_OFF,LOCATION_MODE_SENSORS_ONLY等)表示位置模式。这种模式在Java中通常被称为“int枚举模式”,它不如Java枚举类型安全。-我们可以建议使用枚举来改,例如定义一个LocationMode枚举,包含各个模式,并说明这样改的好处(类型安全、避免无效值等)。C.在Android框架中,为何有些地方没有使用枚举?-性能考虑:枚举占用比int更多的内存。-历史原因:早期Android开发指南建议避免使用枚举以减少内存占用(但现在这个建议已不那么严格)。III.相关问题注意:用户提供的代码片段:代码片段1:```553@RequiresPermission(anyOf={ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION})554publicvoidrequestLocationUpdates(Stringprovider,longminTime,floatminDistance,555LocationListenerlistener){556checkProvider(provider);557checkListener(listener);558559LocationRequestrequest=LocationRequest.createFromDeprecatedProvider(--->封装成LocationRequest,作为参数传下去560provider,minTime,minDistance,false);561requestLocationUpdates(request,listener,null,null);562}```代码片段2:```111voidsetLocationEnabled(booleanenabled){//从数据库拿值,看下此刻的LOCATION_MODE112finalintcurrentMode=Settings.Secure.getInt(mContext.getContentResolver(),113Settings.Secure.LOCATION_MODE,Settings.Secure.LOCATION_MODE_OFF);114115if(isRestricted()){--->当前用户是否有权限116//Locationtogglingdisabledbyuserrestriction.Readthecurrentlocationmodeto117//updatethelocationmasterswitch.118if(Log.isLoggable(TAG,Log.INFO)){119Log.i(TAG,"Restricteduser,notsettinglocationmode");120}121if(mListener!=null){122mListener.onLocationModeChanged(currentMode,true);123}124return;125}//主要看下这个地方126updateLocationEnabled(mContext,enabled,UserHandle.myUserId(),127Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);128refreshLocationMode();```在代码片段2中,我们可以看到使用了LOCATION_MODE(int类型)和几个常量(如LOCATION_MODE_OFF)。因此,这里是我们讨论枚举的重点。开始编写答案:</think> ### Java枚举类型详解与代码逻辑分析 #### 一、Java枚举类型核心用法 枚举(Enum)是Java 5引入的特殊类,用于定义一组**命名常量集合**,兼具类型安全性和可读性优势。 ##### 1. 基本语法结构 ```java public enum LocationMode { // 枚举实例(隐含public static final) OFF(0), // 构造函数传参 SENSORS_ONLY(1), BATTERY_SAVING(2), HIGH_ACCURACY(3); private final int value; // 枚举属性 // 枚举构造函数(自动私有) LocationMode(int value) { this.value = value; } // 枚举方法 public int getValue() { return value; } // 静态查找方法 public static LocationMode findByValue(int val) { for (LocationMode mode : values()) { if (mode.value == val) return mode; } return OFF; // 默认值 } } ``` ##### 2. 关键特性 - **类型安全**:杜绝无效值(如`LocationMode mode = LocationMode.OFF`) - **自带方法**: - `name()`:获取枚举名称字符串(如`"OFF"`) - `ordinal()`:获取声明次序(从0开始) - `values()`:获取所有枚举值数组 - **实现接口**:枚举可实现接口统一行为 - **单例特性**:每个枚举实例是唯一对象 ##### 3. 高级用法 ```java // 枚举实现接口 public interface ModeChanger { void applyMode(); } public enum LocationMode implements ModeChanger { OFF { @Override public void applyMode() { disableLocationServices(); // 多态行为 } }, // 其他枚举实例实现... } // EnumSet高效处理 EnumSet<LocationMode> accurateModes = EnumSet.of( LocationMode.HIGH_ACCURACY, LocationMode.SENSORS_ONLY ); ``` #### 二、结合代码片段分析 ##### 1. `@RequiresPermission`注解中的枚举思维 ```java @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) ``` - **设计类比**:虽使用字符串常量,但设计思想与枚举一致 - **优化建议**:可用枚举强化类型安全 ```java public enum LocationPermission { COARSE(Manifest.permission.ACCESS_COARSE_LOCATION), FINE(Manifest.permission.ACCESS_FINE_LOCATION); final String permission; // ... } @RequiresPermission(anyOf = {LocationPermission.COARSE, LocationPermission.FINE}) ``` ##### 2. `LocationMode`常量组的枚举化改造 ```java // 原始代码(使用int常量) final int currentMode = Settings.Secure.getInt(..., LOCATION_MODE_OFF); // 改造为枚举版本 final LocationMode currentMode = LocationMode.findByValue(Settings.Secure.getInt(...)); ``` **优势对比**: | 方式 | 类型安全 | 可读性 | 防错误赋值 | 行为扩展 | |------------|----------|--------|------------|----------| | int常量 | ✗ | △ | ✗ | ✗ | | **枚举** | ✓ | ✓ | ✓ | ✓ | ##### 3. `LocationRequest`封装与枚举协作 ```java LocationRequest request = LocationRequest.createFromDeprecatedProvider( provider, minTime, minDistance, false); ``` - **参数约束**:使用枚举可限定`provider`的有效值 ```java public enum LocationProvider { GPS("gps"), NETWORK("network"), PASSIVE("passive"); // ... } ``` - **状态管理**:请求类型(如`POWER_LOW`/`HIGH_ACCURACY`)适合用枚举表示 #### 三、Android系统中的特殊考量 1. **性能取舍**:早期Android因枚举内存开销(≈2.5倍于int)而慎用 2. **ProGuard优化**:现代构建工具可优化枚举到int的转换 ```gradle android { compileOptions { // 启用枚举缩减优化 buildFeatures { buildConfig = true } } } ``` 3. **系统API兼容**:`Settings.Secure`采用int常量保持跨版本兼容 ### 最佳实践建议 1. **优先枚举场景**: - 状态机(如位置模式) - 有限选项集合(如定位提供商) - 需关联行为的常量组 2. **保留int常量场景**: - 密集内存操作(如图像处理) - 需与C++交互的NDK代码 - 兼容旧Android版本(API<24) 3. **替代方案**: ```java // 注解限定参数范围 void setLocationMode(@IntRange(from = 0, to = 3) int mode) { // ... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值