精华内容
下载资源
问答
  • 我写了几行很短的代码: enum e : int { abc=10, ...出错的那行显示:error CS0266: Cannot implicitly convert type '...既然我的enum e已经都是从int继承而来的,为何仍然不能直接给一个int ei赋值呢? 谢谢。
  • java enum关键字

    2019-12-06 19:36:25
    Written with StackEdit. ...enum 类是不能继承的,我记得enum 类是final语义的 vo里最好不要存在enum,或者说接口层面不要有enum直接序列化和反序列化,这个会涉及到扩展问题,如果是vo的话,...

    Written with StackEdit.

    为什么思考enum关键字

    在思考enum之前,同事问了我关于enum的两个问题:

    1. enum 类可以继承吗?
    2. vo里使用了enum,怎么改造呢?

    回答这两个问题

    1. enum 类是不能继承的,我记得enum 类是final语义的
    2. vo里最好不要存在enum,或者说接口层面不要有enum的直接序列化和反序列化,这个会涉及到扩展问题,如果是vo的话,恐怕没法保证接口透明下去改造了

    思考

    1. enum的final的语义是怎么实现的呢?
    2. enum是怎么实现线程安全的单例模式?
    3. enum作为接口定义会出现的扩展问题?
    4. enum的set和map为什么特殊化?
    5. enum的特殊需要注意的地方?

    调查和研究

    enum的final的语义是怎么实现的呢?

    说实话,最初找网上资料都是看反编译的Season enum类,代码如下:

    public enum Season {
    	SPRING("春天"), SUMMER("夏天"), AUTUMN("秋天"), WINTER("冬天");
    	
    	private final String chinese;
    	
    	private Season(String chinese) {
    		this.chinese = chinese;
    	}
    
    	public String getChinese() {
    		return chinese;
    	}
    }
    

    然后他们进行编译和反编译的结果如下:

    public final class Season extends Enum<Season> {
    	public static final Season SPRING;
    	public static final Season SUMMER;
    	public static final Season AUTUMN;
    	public static final Season WINTER;
    	private static final Season[] ENUM$VALUES;
    	
    	static {
    		SPRING = new Season("SPRING", 0, "春天");
    		SUMMER = new Season("SUMMER", 1, "夏天");
    		AUTUMN = new Season("AUTUMN", 2, "秋天");
    		WINTER = new Season("WINTER", 3, "冬天");
    		ENUM$VALUES = new Season[]{SPRING, SUMMER, AUTUMN, WINTER}
    	}
    	
    	private final String chinese;
    	
    	private Season(String name, int ordinal, String chinese) {
    		super(name, ordinal);
    		this.chinese = chinese;
    	}
    
    	public String getChinese() {
    		return chinese;
    	}
    	
    	public static Season[] values() {
    		Season[] arr = new Session[ENUM$VALUES.length];
    		System.arraycopy(ENUM$VALUES, 0, arr, 0, arr.length);
    		return arr;
    	}
    	
    	public static Season valueOf(String name) {
    		return Enum.valueOf(Season.class, name);
    	}
    }
    

    大量的case都是这么一个model,我也不知道从哪抄过来的。。。
    然后我自己进行了调研,返现反编译的结果如下(jdk1.8):

    public enum Season {  
      SPRING("春天"),  
      SUMMER("夏天"),  
      AUTUMN("秋天"),  
      WINTER("冬天");  
      
     private final String chinese;  
      
     private Season(String chinese) {  
            this.chinese = chinese;  
      }  
      
        public String getChinese() {  
            return this.chinese;  
      }  
    }
    

    很明显,对于我的反编译版本,已经对enum进行了关键字处理和优化
    然后我就需要印证网上的资料正确性,首先我去了Stack Overflow里调查,发现确实是这样的回答,在一定程度上说明,这样的答案并不是空穴来风
    然后我去看类依赖,发现Season虽然并没有写extends,但是确实继承了Enum类,也就是说,编译器会对我们enum关键字定义的class进行特定化的改造。
    然后就需要查看Enum类,发现Enum是个abstract类,里面对enum进行了域定义和存储定义,从Enum类看出确实符合网友给的的结果
    结论:enum是有final语义的关键字

    enum是怎么实现线程安全的单例模式?

    从反编译的代码可以看出,enum类使用了类加载保证了线程安全,使用static代码块对每个枚举进行了初始化,保证单例。这也是最推荐的单例写法之一

    enum作为接口定义会出现的扩展问题?

    根据alibaba的java代码规范里可以看到有这么一条:

    【强制】 二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用
    枚举类型或者包含枚举类型的 POJO 对象

    对于enum类确实不适合作为序列化和反序列化的对象定义,大致思考能够想到:扩展性极差,如果约定了enum为借口对象,那当我们想对enum进行对象扩展的时候,发现很有可能出现不兼容的问题,比如有一个server端的枚举类:

    @AllArgsConstructor  
    @Getter  
    public enum HttpRequestMethodEnum {  
      
      GET(1, "GET", "get请求"),  
      HEAD(3, "HEAD", "HEAD请求"),  
      POST(2, "POST", "post请求");  
      
      
      /**  
     * code,标识,没有含义  
      */  
      private final int code;  
      
      /**  
     * http的请求方式名称,RequestBuilder 使用name的方式进行识别request method  
     */  private final String name;  
      
      /**  
     * desc */  private final String desc;  
      
    }
    

    接口传输使用的json序列化的字符串,client将对字符串进行发序列化,反序列化的对象类如下:

    @AllArgsConstructor  
    @Getter  
    public enum HttpRequestMethodEnum2 {  
      
        GET(1, "GET", "get请求"),  
      POST(2, "POST", "post请求");  
      
      /**  
     * code,标识,没有含义  
      */  
      private final int code;  
      
      
      /**  
     * http的请求方式名称,RequestBuilder 使用name的方式进行识别request method  
     */  private final String name;  
      
      /**  
     * desc */  private final String desc;  
      
    }
    

    很明显,这就是常见的二方包升级导致的版本不一致的情况,测试:

    public class HttpRequestMethodEnumTest {  
      
        @Test  
    	public void test1() {  
    	final HttpRequestMethodEnum post = HttpRequestMethodEnum.POST;  
        final String s = JacksonUtils.encode2String(post);  
        System.out.println(s);  
        HttpRequestMethodEnum2 post2 = JacksonUtils.decodeFromString(s, HttpRequestMethodEnum2.class);  
        System.out.println(post2);  
      }  
      
        @Test  
        public void test2() {  
        final HttpRequestMethodEnum head = HttpRequestMethodEnum.HEAD;  
        final String s = JacksonUtils.encode2String(head);  
        System.out.println(s);  
        HttpRequestMethodEnum2 head2 = JacksonUtils.decodeFromString(s, HttpRequestMethodEnum2.class);  
        System.out.println(head2);  
      }  
     
    }
    

    发现test1是没有问题的,但是test2就会抛出异常来,解析jackson的反序列流程:

    1. 首先创建反序列化器,从BasicDeserializerFactory中选择构造Enum的反序列化器
    public JsonDeserializer<?> createEnumDeserializer(DeserializationContext ctxt,  
      JavaType type, BeanDescription beanDesc)  
        throws JsonMappingException  
    {  
        final DeserializationConfig config = ctxt.getConfig();  
     final Class<?> enumClass = type.getRawClass();  
      // 23-Nov-2010, tatu: Custom deserializer?  
      JsonDeserializer<?> deser = _findCustomEnumDeserializer(enumClass, config, beanDesc);  
      
     if (deser == null) {  
            ValueInstantiator valueInstantiator = _constructDefaultValueInstantiator(ctxt, beanDesc);  
      SettableBeanProperty[] creatorProps = (valueInstantiator == null) ? null  
      : valueInstantiator.getFromObjectArguments(ctxt.getConfig());  
      // May have @JsonCreator for static factory method:  
      for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {  
                if (_hasCreatorAnnotation(ctxt, factory)) {  
                    if (factory.getParameterCount() == 0) { // [databind#960]  
      deser = EnumDeserializer.deserializerForNoArgsCreator(config, enumClass, factory);  
     break;  }  
                    Class<?> returnType = factory.getRawReturnType();  
      // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)  
      if (returnType.isAssignableFrom(enumClass)) {  
                        deser = EnumDeserializer.deserializerForCreator(config, enumClass, factory, valueInstantiator, creatorProps);  
     break;  }  
                }  
            }  
             
            // Need to consider @JsonValue if one found  
            // 将会在这个地方构造EnumDeserializer,这个构造器我们会发现传入了一个EnumResolver,而在后面的反序列化过程中发现将会先由该EnumResolver将枚举class的基本信息进行解析存储
      if (deser == null) {  
                deser = new EnumDeserializer(constructEnumResolver(enumClass,  
      config, beanDesc.findJsonValueAccessor()),  
      config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS));  
      }  
        }  
      
        // and then post-process it too  
      if (_factoryConfig.hasDeserializerModifiers()) {  
            for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {  
                deser = mod.modifyEnumDeserializer(config, type, beanDesc, deser);  
      }  
        }  
        return deser;  
    }
    
    1. 接着我们看下EnumResolver的构造过程会发现在调用 constructFor 方法的时候进行了enumValues的解析和存储:
    public static EnumResolver constructFor(Class<Enum<?>> enumCls, AnnotationIntrospector ai)  
    {  
    	// 这里会调用Class类的getEnumConstantsShared方法,这个方法会invoke方法Values(),Values()方法会返回所有的枚举实例,所以在这里就拿到所有的枚举实例
        Enum<?>[] enumValues = enumCls.getEnumConstants();  
     if (enumValues == null) {  
            throw new IllegalArgumentException("No enum constants for class "+enumCls.getName());  
      }  
        String[] names = ai.findEnumValues(enumCls, enumValues, new String[enumValues.length]);  
      HashMap<String, Enum<?>> map = new HashMap<String, Enum<?>>();  
     for (int i = 0, len = enumValues.length; i < len; ++i) {  
            String name = names[i];  
     if (name == null) {  
                name = enumValues[i].name();  
      }  
            map.put(name, enumValues[i]);  
      }  
      
        Enum<?> defaultEnum = ai.findDefaultEnumValue(enumCls);  
     // 这里已经把enumValues 转成了map,map的key是抽象类Enum中的name,也就是我们enum类中的实例名字,value就是我们的实例对象
     return new EnumResolver(enumCls, enumValues, map, defaultEnum);  
    }
    
    1. 然后我们再看EnumDeserializer的构造方法:
    public EnumDeserializer(EnumResolver byNameResolver, Boolean caseInsensitive)  
    {  
        super(byNameResolver.getEnumClass());  
      _lookupByName = byNameResolver.constructLookup();  
      _enumsByIndex = byNameResolver.getRawEnums();  
      _enumDefaultValue = byNameResolver.getDefaultValue();  
      _caseInsensitive = caseInsensitive;  
    }
    

    byNameResolver.constructLookup()方法其实就是把枚举的values内容重新封装返回,放到了 EnumDeserializer 的 _lookupByName 域中

    1. 以上是对 EnumDeserializer 的构造过程算是完成了,DeserializerFactory构造出了EnumDeserializer之后,不用说,肯定是要用这个反序列化器反序列化了,也就是在ObjectMapper中的:
    protected Object _readMapAndClose(JsonParser p0, JavaType valueType)  
        throws IOException  
    {  
        try (JsonParser p = p0) {  
            Object result;  
      JsonToken t = _initForReading(p, valueType);  
     final DeserializationConfig cfg = getDeserializationConfig();  
     final DeserializationContext ctxt = createDeserializationContext(p, cfg);  
     if (t == JsonToken.VALUE_NULL) {  
                // Ask JsonDeserializer what 'null value' to use:  
      result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt);  
      } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {  
                result = null;  
      } else {  
    			// 寻找RootDeserializer并构造Deserializer
                JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);  
     if (cfg.useRootWrapping()) {  
                    result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);  
      } else {  
    				// 调用反序列的反序列方法
                    result = deser.deserialize(p, ctxt);  
      }  
                ctxt.checkUnresolvedObjectId();  
      }  
            if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {  
                _verifyNoTrailingTokens(p, ctxt, valueType);  
      }  
            return result;  
      }  
    }
    
    1. 紧接着肯定要看EnumDeserializer.deserialize方法:
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException  
    {  
        JsonToken curr = p.getCurrentToken();  
      // Usually should just get string value:  
      if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {  
    		// 获取lookup,也就是 _lookupByName
            CompactStringObjectMap lookup = ctxt.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING)  
                    ? _getToStringLookup(ctxt) : _lookupByName;  
     final String name = p.getText();  
      //根据name进行查询实例
      Object result = lookup.find(name);  
     if (result == null) {  
                return _deserializeAltString(p, ctxt, lookup, name);  
      }  
            return result;  
      }  
        // But let's consider int acceptable as well (if within ordinal range)  
      if (curr == JsonToken.VALUE_NUMBER_INT) {  
            // ... unless told not to do that  
      int index = p.getIntValue();  
     if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {  
                return ctxt.handleWeirdNumberValue(_enumClass(), index,  
      "not allowed to deserialize Enum value out of number: disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow"  
      );  
      }  
            if (index >= 0 && index < _enumsByIndex.length) {  
                return _enumsByIndex[index];  
      }  
            if ((_enumDefaultValue != null)  
                    && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) {  
                return _enumDefaultValue;  
      }  
            if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {  
                return ctxt.handleWeirdNumberValue(_enumClass(), index,  
      "index value outside legal index range [0..%s]",  
      _enumsByIndex.length-1);  
      }  
            return null;  
      }  
        return _deserializeOther(p, ctxt);  
    }
    

    通过这个地方不难看出我们可以通过name进行获取出Enum实例来了,如果我们方序列的Enum中没有改name,就会失败。

    enum的set和map为什么特殊化?

    这里我们只研究EnumMap

    1. 首先来看EnumMap的根据类型的构造函数:
    public EnumMap(Class<K> keyType) {  
      this.keyType = keyType;  
      keyUniverse = getKeyUniverse(keyType);  
      vals = new Object[keyUniverse.length];  
    }
    

    通过这三个参数也可以看到,首先会约定我们的枚举类型(keyType ),然后会把该枚举的values存起来(keyUniverse ),然后创建了一个存放values的数据vals,这个数组大小和枚举values的长度是一样的,不难想到,最终是要通过下标来做映射关系

    1. 然后我们看下put方法:
    public V put(K key, V value) {  
      // check key的类型是否是我们的枚举类型
      typeCheck(key);  
      //取出下标
     int index = key.ordinal();  
      Object oldValue = vals[index];  
      //把我们的值塞入到vals数组的指定位置
      vals[index] = maskNull(value);  
      //如果之前没有值,就说明我们的map元素增加了一个,size++
     if (oldValue == null)  
            size++;  
     // 将值返回回去
     return unmaskNull(oldValue);  
    }
    
    1. 紧接着我们看看get方法
    public V get(Object key) {  
        return (isValidKey(key) ?  
                unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);  
    }
    

    首先校验key的类型是不是我们限定的枚举类型,然后找到对应下标的vals[]的值

    enum的特殊需要注意的地方

    1. 上面介绍了EnumMap,肯定会对Enum的ordinal感兴趣,接口文档明确表示,这个字段不会被使用,主要的使用地方实在设计师对EnumSet和EnumMap的设计,言外之意如果大家对自己的设计没有想明白的时候,还是不要使用这个字段为好
    2. Enum类并没有Values() 和 valueOf(String) 方法,这两个方法时编译的时候生成的,这个感觉还是挺烦人的
    3. Enum虽然实现了 Serializable 接口,但是却不可以使用默认的反序列化方式
    /**  
     * prevent default deserialization */
    private void readObject(ObjectInputStream in) throws IOException,  
      ClassNotFoundException {  
        throw new InvalidObjectException("can't deserialize enum");  
    }  
      
    private void readObjectNoData() throws ObjectStreamException {  
        throw new InvalidObjectException("can't deserialize enum");  
    }
    

    这是因为Enum类是单例的,反序列化会实例化一个对象,这违反单例的设计,所以Enum虽然可以被java 序列化,但是却不可以反序列化。

    总结

    1. enum是一种很好的单例模式,也是一种很好的类型列举方式,不过并不是所有的地方都适用
    2. enum有很多的内容是编译器补充的,比如values()方法和valueOf(String name)方法
    3. enum尽量在自己系统内部做定义,尽量不要在接口层交互直接对enum类进行序列化和反序列化
    展开全文
  • java之枚举类型enum

    2017-03-21 13:59:16
    一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决 JDK 5新增的 enum 关键字用于定义一个枚举类 枚举...

    为什么需要枚举?

    • 一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决

    • JDK 5新增的 enum 关键字用于定义一个枚举类

    枚举API

    Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。常用方法:
    • name()
    • ordinal()
    • valueof(Class enumClass, String name)
    自定义的枚举类
    • valueof(String name)
    • values() 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便


    默认构造函数枚举

    // 1. 枚举类定义
    enum Grade{
        A,B,C,D,E;
    }
    class Student{
        private String name;
    
        // 2. 使用枚举类型
        private Grade grade; //ABCDE
        public Grade getGrade() {
            return grade;
        }
        public void setGrade(Grade grade) {
            this.grade = grade;
        }
    }
    public class Demo1 {
        public static void main(String[] args) {
            Student stu = new Student();
            // 3. 给枚举类型赋值,只能是枚举类定义的值(第1步中所定义)
            stu.setGrade(Grade.A);
    
            System.out.println(stu.getGrade());
        }
    }
    

    定义的枚举为默认构造函数枚举, 也可以这样写

    // 1. 枚举类定义
    enum Grade{
        A(),B(),C(),D(),E();
        // 必须为私有
        private Grade(){
        }
    }
    

    有参构造函数枚举定义

    // 1. 带参数构造函数的枚举定义
    enum Grade{
        A("100-90"),B("90-80"),C("80-70"),D("70-60"),E("60-0");
    
        private String value;
        // 定义get方法返回数据
        public String getValue() {
            return value;
        }
    
        private Grade(String value) {
            this.value = value;
        }
    }
    class Student{
        // 2. 使用枚举类型
        private Grade grade; //ABCDE
        public Grade getGrade() {
            return grade;
        }
        public void setGrade(Grade grade) {
            this.grade = grade;
        }
    }
    public class Demo1 {
        public static void main(String[] args) {
            Student stu = new Student();
            // 3. 给枚举类型赋值
            stu.setGrade(Grade.A);
            // 输出对应的“分数”
            System.out.println(stu.getGrade().getValue());
        }
    }
    

    枚举类中定义抽象方法,返回更多信息

    // 1. 带参数构造函数的枚举定义
    // 并且需要返回更多的信息, 优秀,良好,好,一般,差
    enum Grade{
        A("100-90"){
            public String getLocalStr() {
                return "优秀";
            }
        }
    
        ,B("90-80"){
            public String getLocalStr() {
                return "良好";
            }
        }
    
        ,C("80-70"){
            public String getLocalStr() {
                return "好";
            }
        }
    
        ,D("70-60"){
            public String getLocalStr() {
                return "一般";
            }
        }
    
        ,E("60-0"){
            public String getLocalStr() {
                return "差";
            }
        };
    
        private String value;
        // 定义get方法返回数据
        public String getValue() {
            return value;
        }
    
        private Grade(String value) {
            this.value = value;
        }
    
        // 返回成绩段对应的“描述”, 需要每个对象重新实现次方法
        public abstract String getLocalStr();
    }
    class Student{
        // 2. 使用枚举类型
        private Grade grade; //ABCDE
        public Grade getGrade() {
            return grade;
        }
        public void setGrade(Grade grade) {
            this.grade = grade;
        }
    }
    public class Demo1 {
        public static void main(String[] args) {
            Student stu = new Student();
            // 3. 给枚举类型赋值
            stu.setGrade(Grade.A);
            // 输出对应的“分数”
            System.out.println(stu.getGrade().getValue());
    
            // 输出描述
            System.out.println(stu.getGrade().getLocalStr());
        }
    }
    

    总结

    枚举类具有如下特性:
    1) 枚举类是一种特殊形式的Java类。
    2) 使用 enum 定义的枚举类默认继承了 java.lang.Enum 类。
    3) 枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
    4) 与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的。
    5) 枚举类的所有实例必须在枚举类中显式列出(, 分隔 ; 结尾). 列出的实例系统会自动添加 public static final 修饰。
    6) 枚举类也可以实现接口、或继承抽象类。
    7) JDK5中扩展了swith语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型。

    展开全文
  • Java枚举的使用-Enum

    2020-08-05 13:21:13
    什么 1、java枚举类是一组预定义常量的集合,使用enum关键字声明这个类,常量名称官方建议大写;...6、它的构造方法默认private ,因此不能添加其他的类型修饰符; 7、可直接用==判断两枚举值 8、v

    是什么

    1、java枚举类是一组预定义常量的集合,使用enum关键字声明这个类,常量名称官方建议大写;

    2、所有枚举值都是public , static , final的;

    3、枚举类默认继承了java.lang.Enum,并且enum类会被final修饰;

    4、枚举类默认实现了java.lang.Comparable接口;

    5、枚举类覆载了toString方法,当我们调用时直接会返回对应的枚举值;

    6、它的构造方法默认为private ,因此不能添加其他的类型修饰符;

    7、可直接用==判断两枚举值

    8、values()方法返回所有的枚举值

    和final static修饰的常量的区别

    1、enum可以自定义属性,它可以拓展许多的属性值
    2、它还可以拥有各自内部的方法

    使用

    基本使用

    public enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,THURSDAY, FRIDAY, SATURDAY 
    }
    
    直接通过  Day.SUNDAY .....进行调用
    

    自定义属性使用

    public enum AccruedCleanEnum {
    
      SPREAD("1","发票"),OTHER("0","收入"),NON_BUSINESS("2","支出");
    
        private String index;
        private String name;
        
        //给自定义属性赋值 有自定义属性后必需有带参构造为其赋值
        AccruedCleanEnum(String index, String name) {
            this.index = index;
            this.name = name;
        }
    
        /**
         * 根据属性值index获取enume类型
         * values()是enum自带的一个方法,该方法返回所有的枚举类型
         */
        public static AccruedCleanEnum getType(String index){
            for(AccruedCleanEnum accruedCleanEnum : AccruedCleanEnum.values()){
                if(accruedCleanEnum.index == index){
                    return accruedCleanEnum;
                }
            }
            return OTHER;
        }
        //通过index获取name
        public static String getName(String index){
            for(AccruedCleanEnum accruedCleanEnum : AccruedCleanEnum.values()){
                if(accruedCleanEnum.getIndex().equals(index)){
                    return accruedCleanEnum.name;
                }
            }
            return "";
        }
    
        public String getIndex() {
            return index;
        }
    
        public String getName() {
            return name;
        }
    
        public static void main(String[] args) {
            String name = AccruedCleanEnum.getName("1");
            System.out.println("name:"+ name);
            System.out.println(AccruedCleanEnum.getType("1"));
            System.out.println(AccruedCleanEnum.valueOf("SPREAD"));
        }
    }
    

    自定义方法使用

    通过声明抽象方法来实现来定义方法 public abstract Day getNext();

    public enum Day {
        MONDAY(1, "星期一", "各种不在状态"){
            @Override
            public Day getNext() {
                return TUESDAY;
            }
        },
        TUESDAY(2, "星期二", "依旧犯困"){
            @Override
            public Day getNext() {
                return WEDNESDAY;
            }
        },
        WEDNESDAY(3, "星期三", "感觉半周终于过去了"){
            @Override
            public Day getNext() {
                return THURSDAY;
            }
        },
        THURSDAY(4, "星期四", "期待这星期五"){
            @Override
            public Day getNext() {
                return FRIDAY;
            }
        },
        FRIDAY(5, "星期五", "感觉还不错"){
            @Override
            public Day getNext() {
                return SATURDAY;
            }
        },
        SATURDAY(6, "星期六", "感觉非常好"){
            @Override
            public Day getNext() {
                return SUNDAY;
            }
        },
        SUNDAY(7, "星期日", "感觉周末还没过够。。。"){
            @Override
            public Day getNext() {
                return MONDAY;
            }
        };
    
        Day(int index, String name, String value) {
            this.index = index;
            this.name = name;
            this.value = value;
        }
    
        private int index;
        private String name;
        private String value;
        
        //通过声明抽象方法来实现定义方法
        public abstract Day getNext();
    
        public int getIndex() {
            return index;
        }
    
        public void setIndex(int index) {
            this.index = index;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
    /**
    *    测试方法的调用
    *    
    */
    	public static void main(String[] args) {
            Day next = Day.MONDAY.getNext();
            System.out.println("next:"+ next);
        }
    
    }
    
    展开全文
  • 所以 允许直接通过引用进行操作。 2. 拓展类加载器(Extension classLoader): 扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader) 实现的,它负责将 ...
  • 枚举 基础增强篇

    2017-07-10 01:41:59
    一些方法在运行时,他需要的数据不能是任意的,而必须是一定范围内的值,java5以后可以直接使用枚举予以解决。 JDK5新增的enum关键字用于定义一个枚举类 枚举类是什么? 枚举类也是一种特殊形式的类 枚举类...

    为什么需要枚举
    一些方法在运行时,他需要的数据不能是任意的,而必须是一定范围内的值,java5以后可以直接使用枚举予以解决。
    JDK5新增的enum关键字用于定义一个枚举类
    枚举类是什么?
    枚举类也是一种特殊形式的类
    枚举类和普通类的区别
    1.使用enum定义的枚举类默认的继承了java.lang.Enum类
    2.枚举类的构造器只能使用private 访问控制符
    3.枚举类的所有实例必须在枚举类中显示列出(,分割 ;结尾)列出的实例系统会自动添加public static final 修饰
    4.jdk中扩展了switch语句,它除了可以接受int short byte char外,还可以一个枚举类型
    5.若枚举只有一个成员,则可以作为一种单例模式的实现方法

    java 的基础增强
    myeclipse的介绍
    myeclipse是eclipse 的插件
    安装 破解
    选择工作空间,不能有中文和空格
    编码 设置
    创建web项目 项目名称不要使用中文

    debug断点调试
    跟踪程序的运行状态
    方便查询程序的源代码

    打断点
    右键 debug As
    断点的那一行 还没有执行
    step over 跳过 执行下一行 f6
    resume 跳入到 下一个断点,如果没有,执行完成 f8
    step into 跳入 f5
    Drop to Frame 返回刚开始的位置
    step return 跳出 f7

    单元测试
    单元的最小单位,就是方法

    泛型
    泛型应用在集合上
    泛型应用在一些通用性较高的代码上
    泛型擦除:泛型存在你源代码的阶段,编译成class文件后,泛型信息被擦除

    枚举
    反射
    可变参数
    增强for
    静态导入

    展开全文
  • 一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。JDK5新增的enum关键字用于定义一个枚举类。枚举类...
  • 聊一聊枚举

    2017-04-09 16:25:12
    一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,在jdk5之前是采用自定义带有枚举的功能的类解决问题,jdk5之后可以用枚举直接解决, 每一个枚举值都是这个枚举类的一个实例。java中声明的...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    1.19 为什么不能像下面这样在初始式和数组维度值中使用const值?constintn=5;inta[n]; 1.20 constchar*p、charconst*p和char*constp有什么区别? 复杂的声明 1.21 怎样建立和理解非常复杂的声明?例如定义一个...
  • 1.19 为什么不能像下面这样在初始式和数组维度值中使用const值?constintn=5;inta[n];  1.20 constchar*p、charconst*p和char*constp有什么区别?  复杂的声明  1.21 怎样建立和理解非常复杂的声明?例如定义...
  •  1.19 为什么不能像下面这样在初始式和数组维度值中使用const值?constintn=5;inta[n]; 1.20 constchar*p、charconst*p和char*constp有什么区别? 复杂的声明 1.21 怎样建立和理解非常复杂的声明?例如定义一...
  • 1.19 为什么不能像下面这样在初始式和数组维度值中使用const值?const int n=5; int a[n]; 39 1.20 const char *p、char const *p和char *const p有什么区别? 39 复杂的声明 40 1.21 怎样建立和理解非常复杂的...
  • 1.19 为什么不能像下面这样在初始式和数组维度值中使用const值?const int n=5; int a[n]; 39 1.20 const char *p、char const *p和char *const p有什么区别? 39 复杂的声明 40 1.21 怎样建立和理解非常复杂的...
  • 1.19 为什么不能像下面这样在初始式和数组维度值中使用const值?const int n=5; int a[n]; 10 1.20 const char *p、char const *p和char *const p有什么区别? 10 复杂的声明 11 1.21 怎样建立和理解非常复杂...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    1.19 为什么不能像下面这样在初始式和数组维度值中使用const值?const int n=5; int a[n]; 10 1.20 const char *p、char const *p和char *const p有什么区别? 10 复杂的声明 11 1.21 怎样建立和理解非常复杂...
  • 泛型类不能是异常类,也就是该泛型类不能继承自Throwable以及其子类 public class MyExpection<T> extends Exception{ } //编译错误 可以抛出(throws)泛型类,但catch的参数不能是泛型类。 注意:...
  • o 7.18 当数组是函数的参数时, 为什么 sizeof 不能正确报告数组的大小 ? * 8. 内存分配 o 8.1 为什么这段代码不行?char *answer; printf("Type something:\n"); gets(answer); printf("You typed \"%s\"\n", ...
  • 面向对象的编程语言与以往各种编程语言有根本的不同,它设计的出发点就是为了直接的描述客观世界中存在的事物以及它们之间的关系。面向对象的编程语言将客观事物看作具有属性和行为的对象,通过抽象找出同一类...
  • 你必须知道的495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    2.2 为什么struct x f . . . g; x thestruct; 不对? . . . . . . . . . . . . . 7 2.3 一个结构可以包含指向自己的指针吗? . . . . . . . . . . . . . . . 7 2.4 在C 语言中实现抽象数据类型什么方法最好? . . . ....
  • 在一小时内学会 C#(txt版本)

    热门讨论 2009-08-19 18:09:37
    2. 你不能在 C# 中访问一个“挂起”指针。 3. 超出数组边界的表达式索引值同样不可访问。 4. C# 中没有全局变量或全局函数,取而代之的是通过静态函数和静态变量完成的。 数据类型 所有 C# 的类型都是从 object 类...
  • 为了使用Lua协程,你必须调用 lua_resume(),这就意味着你不能用先前介绍的函数 call_function()来开始一个协程.你必须用这个: template Ret resume_function(lua_State* L, const char* name, ...) template Ret ...
  • asp.net面试题

    2011-05-27 17:56:26
    密封类不能同时抽象类。 sealed 修饰符主要用于防止非有意的派生,但是它还能促使某些运行时优化。具体说来,由于密封类永远不会有任何派生类,所以对密封类的实例的虚拟函数成员的调用可以转换非虚拟调用来...
  • 相关知识你可以看看我的这两篇文章:【Android内存基础——内存抖动http://www.jianshu.com/p/69e6f894c698】【用两张图告诉你,为什么你的App会卡顿?http://www.jianshu.com/p/df4d5ec779c8】响应触摸事件如果你...
  • react-native 之布局篇

    2021-01-10 04:06:31
    <p>react的宽度支持百分比,设置宽度时需要带单位 <code>{width: 10}</code>, 那么10代表的具体宽度是多少呢? 知道是官网文档全还是我眼瞎,反正是没找到,那做一个实验...

空空如也

空空如也

1 2
收藏数 27
精华内容 10
关键字:

为什么不能直接继承enum