java与enum详解

enum

enum Operator{
    ADD, SUB,MUL,DIV
}

关键字enum可以将一组具名的值的有限集合创建为一种新类型,而这些具名的值可以作为常规的程序组件使用(如在switch语句中的使用).在创建enum时,编译器会自动生成一个相关类,这个类会继承自java.lang.Enum,并且编译器还会为这个类自动添加两个有用的类方法:

方法说明
values()按照enum常量的声明顺序,生成这些常量值构成的数组
valueOf()返回当前枚举类型对应名称的枚举常量

Enum

Enum中的常用方法

Class<E> getDeclaringClass()  
  • 返回当前枚举常量对应的枚举类型的Class对象
String name()
  • 返回当前枚举常量的名称
int ordinal()
  • 返回枚举常量在声明时的排序位置
static <T extends Enum<T>> valueOf(Class<T> enumType,String name)
  • 返回指定枚举类型对应名称的枚举常量.

enum与普通类的区别与联系

除了不能继承一个enum,基本上可以将enum看作一个常规的类.因此我们可以向其内添加方法和字段以及实现其它接口,不过在添加方法和字段之前我们应在enum实例序列后添加分号,且不能在定义enum序列之前进行这些操作.还有一点要注意的是,对于enum的构造函数,我们只能将其声明为private.

enum Operator{
    ADD("add"), SUB("sum"),MUL("mul"),DIV("div");
    
    private String desc;
    
    Operator(String desc){
        this.desc=desc;
    }

    public String getDesc() {
        return desc;
    }
}

enum的类型信息

使用反射打印一下前言中Operator的类型信息

public static void main(String[] args) {
    System.out.println("是否为final类-----------------------------");
    Operator.class.getModifiers();
    System.out.println(Modifier.isFinal(Operator.class.getModifiers()));
    System.out.println("实现接口信息-------------------------------");
    Arrays.stream(Operator.class.getInterfaces()).forEach(System.out::println);
    System.out.println("基类信息----------------------------------");
    System.out.println(Operator.class.getSuperclass());
    System.out.println("构造函数信息-------------------------------");
    Arrays.stream(Operator.class.getDeclaredConstructors()).forEach(System.out::println);
    System.out.println("字段信息----------------------------------");
    Arrays.stream(Operator.class.getDeclaredFields()).forEach(System.out::println);
    System.out.println("方法信息----------------------------------");
    Arrays.stream(Operator.class.getDeclaredMethods()).forEach(System.out::println);
    System.out.println("所有enum常量------------------------------");
    Arrays.stream(Operator.class.getEnumConstants()).forEach(System.out::println);
}

在这里插入图片描述
注意最后一个方法getEnumConstants(),该方法可以获取一个enum Class对象中的所有枚举常量.

Enum常量

public static void main(String[] args) {
    try {
        int add = Operator.class.getDeclaredField("ADD").getModifiers();
        System.out.println(Modifier.isStatic(add));//true
        System.out.println(Modifier.isFinal(add));//true
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}

每个枚举常量使用起来像一个静态内部类实例,且enum像它的父类,不过也仅限于此,我们并不能将枚举常量当类型使用.但我们可以通过在enum定义抽象方法的方式来定制枚举常量的专属行为.以及覆盖某些在enum中的某些方法.

enum Operator{
    ADD{
        @Override
        public void action() {
            System.out.println("加法");
        }
    },
    SUB{
        @Override
        public void action() {
            System.out.println("减法");
        }
    },
    MUL{
        @Override
        public void action() {
            System.out.println("乘法");
        }
    },
    DIV{
        @Override
        public void action() {
            System.out.println("除法");
        }
    };
    public abstract void action();
	public static void main(String[] args) {
    	EnumSet<Operator> operators = EnumSet.noneOf(Operator.class);
    	operators.add(Operator.ADD);
    	operators.add(Operator.SUB);
    	for(Operator operator:operators){
        	operator.action();
    	}
	}
}

EnumSet

EnumSet实现的目的是为了通过enum创建一种代替传统基于int的位标志的替代品,因为传统方法直接操作bit,难以让人理解代码的含义.EnumSet内的元素必须是来自一个enum的enum常量,它是基于long值实现的,一个long值有64位,一个enum常量只需要一个bit来表示它是否存在,如果enum常量多于64个,那么EnumSet会自动扩展.

public static void main(String[] args) {
    EnumSet<Operator> operators = EnumSet.allOf(Operator.class);
    System.out.println(operators);//[ADD, SUB, MUL, DIV]
}

常用方法

static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType)   
  • 创建一个包含指定元素类型中所有元素的枚举集
static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) 
  • 创建一个最初包含指定元素的枚举集
static <E extends Enum<E>> EnumSet<E> range(E from, E to) 
  • 创建最初包含由两个指定端点定义的范围内的所有元素的枚举集。
static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)   
  • 使用指定的元素类型创建一个空的枚举集

EnumMap

EnumMap要求其中的键必须来自一个enum.

常用方法

EnumMap(Class<K> keyType) 
构造函数
boolean containsKey(Object key) 
如果此映射包含指定键的映射,则返回 true 
boolean containsValue(Object value) 
如果此映射将一个或多个键映射到指定的值,则返回 true 
V get(Object key) 
返回到指定键所映射的值
V put(K key, V value) 
将指定的值与此映射中的指定键相关联
V remove(Object key) 
从该map中删除此key的映射(如果存在)
int size() 
返回此地图中键值映射的数量。  

使用Enum知识实现一个加减乘除表达式计算器

首先自己写一个栈,也可以使用java自带的

package cn.superstallion.DataStructure;

import java.util.Iterator;

public class Stack<T>implements Iterable <T> {
    private class StackIterator implements Iterator<T> {
        private int temp=sum;
        private Node<T> item=head;
        @Override
        public boolean hasNext() {
            return temp>0;
        }

        @Override
        public T next() {
            temp--;
            Node<T> tempNode=item;
            item=item.next;
            return tempNode.element;
        }
    }

    private class Node<T>{
        private T element;
        private Node<T> next;
    }

    private Node<T> head;
    private int sum;

    public Stack(){

    }

    public void push(T item){
        if (head==null){
            head=new Node<T>();
            head.element=item;
        }else {
            Node oldHead=head;
            head=new Node<T>();
            head.element=item;
            head.next=oldHead;
        }
        sum++;
    }

    public T pop(){
        T temp=head.element;
        head=head.next;
        sum--;
        return temp;
    }

    public boolean isEmpty(){
        return sum==0;
    }

    public int size(){
        return sum;
    }

    @Override
    public Iterator<T> iterator() {
        return new StackIterator();
    }
}

基于栈实现计算器

package cn.superstallion.ClassicalAlgorithm;

import cn.superstallion.DataStructure.Stack;
import java.util.EnumMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Calculator {

    private enum Operator{
        ADD{
            @Override
            Double action(Double operandA, Double operandB) {
                return operandB+operandA;
            }
        },
        SUB{
            @Override
            Double action(Double operandA, Double operandB) {
                return operandB-operandA;
            }
        },
        MUL{
            @Override
            Double action(Double operandA, Double operandB) {
                return operandB*operandA;
            }
        },
        DIV{
            @Override
            Double action(Double operandA, Double operandB) {
                return operandB/operandA;
            }
        };

        abstract Double action(Double operandA,Double operandB);
        public static Operator operatorMapping(String operator){
            switch (operator){
                case "+":
                    return ADD;
                case "-":
                    return SUB;
                case "*":
                    return MUL;
                case "/":
                    return DIV;
                default:
                    return null;
            }
        }

    }

    static final private EnumMap<Operator,Integer> priority;
    static final private String regx = "\\d+|\\D";
    static final private Stack<Double> operandStack;
    static final private Stack<Operator> operatorStack;
    private final String expression;

    static {
        priority = new EnumMap<>(Operator.class);
        operandStack = new Stack<>();
        operatorStack = new Stack<>();
        priority.put(Operator.ADD, 0);
        priority.put(Operator.SUB, 0);
        priority.put(Operator.MUL, 1);
        priority.put(Operator.DIV, 1);
    }

    public Calculator(String expression) {
        this.expression = expression;
    }

    public Double calculate() {
        Pattern compile = Pattern.compile(regx);
        Matcher matcher = compile.matcher(expression);
        while (matcher.find()) {
            if (matcher.group().matches("\\d+")) {
                operandStack.push(Double.valueOf(matcher.group()));
            } else if (operatorStack.size() == 0) {
                operatorStack.push(Operator.operatorMapping(matcher.group()));
            } else {
                Operator top = operatorStack.pop();
                if (priority.get(Operator.operatorMapping(matcher.group())) >= priority.get(top)) {
                    operatorStack.push(top);
                } else {
                    Double operandA = operandStack.pop();
                    Double operandB = operandStack.pop();
                    operandStack.push(top.action(operandA,operandB));
                }
                operatorStack.push(Operator.operatorMapping(matcher.group()));
            }
        }
        while (!operatorStack.isEmpty()) {
            Double operandA = operandStack.pop();
            Double operandB = operandStack.pop();
            operandStack.push(operatorStack.pop().action(operandA,operandB));
        }
        return operandStack.pop();
    }

    public static void main(String[] args) {
        Calculator calculator = new Calculator("1/2+3+2*4");
        System.out.println(calculator.calculate());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亻乍屯页女子白勺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值