概览

在本文中,我们将看到什么是 Java 枚举,它们解决了哪些问题以及如何在实践中使用 Java 枚举实现一些设计模式。

enum关键字在 java5 中引入,表示一种特殊类型的类,其总是继承java.lang.Enum类,更多内容可以自行查看其官方文档。

枚举在很多时候会和常量拿来对比,可能因为本身我们大量实际使用枚举的地方就是为了替代常量。那么这种方式由什么优势呢?

以这种方式定义的常量使代码更具可读性,允许进行编译时检查,预先记录可接受值的列表,并避免由于传入无效值而引起的意外行为。

下面示例定义一个简单的枚举类型 pizza 订单的状态,共有三种 ORDERED, READY, DELIVERED状态:

  1. package shuang.kou.enumdemo.enumtest;
  2. public enum PizzaStatus {
  3. ORDERED,
  4. READY,
  5. DELIVERED;
  6. }

简单来说,我们通过上面的代码避免了定义常量,我们将所有和 pizza 订单的状态的常量都统一放到了一个枚举类型里面。

  1. System.out.println(PizzaStatus.ORDERED.name());//ORDERED
  2. System.out.println(PizzaStatus.ORDERED);//ORDERED
  3. System.out.println(PizzaStatus.ORDERED.name().getClass());//class java.lang.String
  4. System.out.println(PizzaStatus.ORDERED.getClass());//class shuang.kou.enumdemo.enumtest.PizzaStatus

自定义枚举方法

现在我们对枚举是什么以及如何使用它们有了基本的了解,让我们通过在枚举上定义一些额外的API方法,将上一个示例提升到一个新的水平:

  1. public class Pizza {
  2. private PizzaStatus status;
  3. public enum PizzaStatus {
  4. ORDERED,
  5. READY,
  6. DELIVERED;
  7. }
  8. public boolean isDeliverable() {
  9. if (getStatus() == PizzaStatus.READY) {
  10. return true;
  11. }
  12. return false;
  13. }
  14. // Methods that set and get the status variable.
  15. }

枚举类型中定义属性,方法

我们在上面讲到了,我们可以通过在枚举类型中定义属性,方法和构造函数让它变得更加强大。

下面我通过一个实际的例子展示一下,当我们调用短信验证码的时候可能有几种不同的用途,我们在下面这样定义:

  1. public enum PinType {
  2. REGISTER(100000, "注册使用"),
  3. FORGET_PASSWORD(100001, "忘记密码使用"),
  4. UPDATE_PHONE_NUMBER(100002, "更新手机号码使用");
  5. privatefinalint code;
  6. privatefinal String message;
  7. PinType(int code, String message) {
  8. this.code = code;
  9. this.message = message;
  10. }
  11. public int getCode() {
  12. return code;
  13. }
  14. public String getMessage() {
  15. return message;
  16. }
  17. @Override
  18. public String toString() {
  19. return"PinType{" +
  20. "code=" + code +
  21. ", message='" + message + '\'' +
  22. '}';
  23. }
  24. }

实际使用:

  1. System.out.println(PinType.FORGET_PASSWORD.getCode());
  2. System.out.println(PinType.FORGET_PASSWORD.getMessage());
  3. System.out.println(PinType.FORGET_PASSWORD.toString());

Output:

  1. 100001
  2. 忘记密码使用
  3. PinType{code=100001, message='忘记密码使用'}

这样的话,在实际使用起来就会非常灵活方便!

使用 == 比较枚举类型

由于枚举类型确保JVM中仅存在一个常量实例,因此我们可以安全地使用“ ==”运算符比较两个变量,如上例所示;此外,“ ==”运算符可提供编译时和运行时的安全性。

首先,让我们看一下以下代码段中的运行时安全性,其中“ ==”运算符用于比较状态,并且如果两个值均为null 都不会引发 NullPointerException。相反,如果使用equals方法,将抛出 NullPointerException:

  1. if(testPz.getStatus().equals(Pizza.PizzaStatus.DELIVERED));
  2. if(testPz.getStatus() == Pizza.PizzaStatus.DELIVERED);

对于编译时安全性,我们看另一个示例,两个不同枚举类型进行比较,使用equal方法比较结果确定为true,因为getStatus方法的枚举值与另一个类型枚举值一致,但逻辑上应该为false。这个问题可以使用==操作符避免。因为编译器会表示类型不兼容错误:

  1. if(testPz.getStatus().equals(TestColor.GREEN));
  2. if(testPz.getStatus() == TestColor.GREEN);

在 switch 语句中使用枚举类型

  1. public int getDeliveryTimeInDays() {
  2. switch (status) {
  3. case ORDERED: return5;
  4. case READY: return2;
  5. case DELIVERED: return0;
  6. }
  7. return0;
  8. }

枚举类型的属性,方法和构造函数

你可以通过在枚举类型中定义属性,方法和构造函数让它变得更加强大。

如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。

下面,让我们扩展上面的示例,实现从比萨的一个阶段到另一个阶段的过渡,并了解如何摆脱之前使用的if语句和switch语句:

  1. public class Pizza {
  2. private PizzaStatus status;
  3. public enum PizzaStatus {
  4. ORDERED (5){
  5. @Override
  6. public boolean isOrdered() { //每个对象各自重写方法
  7. return true;
  8. }
  9. },
  10. READY (2){
  11. @Override
  12. public boolean isReady() {
  13. return true;
  14. }
  15. },
  16. DELIVERED (0){
  17. @Override
  18. public boolean isDelivered() {
  19. return true;
  20. }
  21. };
  22. private int timeToDelivery;
  23. public boolean isOrdered() {return false;}
  24. public boolean isReady() {return false;}
  25. public boolean isDelivered(){return false;}
  26. public int getTimeToDelivery() {
  27. return timeToDelivery;
  28. }
  29. PizzaStatus (int timeToDelivery) {
  30. this.timeToDelivery = timeToDelivery;
  31. }
  32. }
  33. public boolean isDeliverable() {
  34. returnthis.status.isReady();
  35. }
  36. public void printTimeToDeliver() {
  37. System.out.println("Time to delivery is " +
  38. this.getStatus().getTimeToDelivery());
  39. }
  40. // Methods that set and get the status variable.
  41. }

下面这段代码展示它是如何 work 的:

  1. @Test
  2. public void givenPizaOrder_whenReady_thenDeliverable() {
  3. Pizza testPz = new Pizza();
  4. testPz.setStatus(Pizza.PizzaStatus.READY);
  5. assertTrue(testPz.isDeliverable());
  6. }

使用parenthesis override不同成员变量

  1. public enum Color {  
  2.     RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
  3.     // 成员变量  
  4.     private String name;  
  5.     private int index;  
  6.     // 构造方法  
  7.     private Color(String name, int index) {  
  8.         this.name = name;  
  9.         this.index = index;  
  10.     }  
  11.     // 普通方法  
  12.     public static String getName(int index) {  
  13.         for (Color c : Color.values()) {  //如果需要迭代所有可能的常量则使用Enum.values()
  14.             if (c.getIndex() == index) {  
  15.                 return c.name;  
  16.             }  
  17.         }  
  18.         return null;  
  19.     }  
  20.     // get set 方法  
  21.     public String getName() {  
  22.         return name;  
  23.     }  
  24.     public void setName(String name) {  
  25.         this.name = name;  
  26.     }  
  27.     public int getIndex() {  
  28.         return index;  
  29.     }  
  30.     public void setIndex(int index) {  
  31.         this.index = index;  
  32.     }  
  33. }  

枚举类型请使用EnumSet和EnumMap

EnumSet

EnumSet 是一个专为枚举设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。

EnumSet 是一种专门为枚举类型所设计的 Set 类型。

HashSet相比,由于使用了内部位向量表示,因此它是特定 Enum 常量集的非常有效且紧凑的表示形式。

它提供了类型安全的替代方法,以替代传统的基于int的“位标志”,使我们能够编写更易读和易于维护的简洁代码。

EnumSet 是抽象类,其有两个实现:RegularEnumSetJumboEnumSet,选择哪一个取决于实例化时枚举中常量的数量。

在很多场景中的枚举常量集合操作(如:取子集、增加、删除、containsAllremoveAll批操作)使用EnumSet非常合适;如果需要迭代所有可能的常量则使用Enum.values()

  1. public class Pizza {
  2. private static EnumSet<PizzaStatus> undeliveredPizzaStatuses =
  3. EnumSet.of(PizzaStatus.ORDERED, PizzaStatus.READY);
  4. private PizzaStatus status;
  5. public enum PizzaStatus {
  6. ...
  7. }
  8. public boolean isDeliverable() {
  9. returnthis.status.isReady();
  10. }
  11. public void printTimeToDeliver() {
  12. System.out.println("Time to delivery is " +
  13. this.getStatus().getTimeToDelivery() + " days");
  14. }
  15. public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) {
  16. return input.stream().filter(
  17. (s) -> undeliveredPizzaStatuses.contains(s.getStatus()))
  18. .collect(Collectors.toList());
  19. }
  20. public void deliver() {
  21. if (isDeliverable()) {
  22. PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy()
  23. .deliver(this);
  24. this.setStatus(PizzaStatus.DELIVERED);
  25. }
  26. }
  27. // Methods that set and get the status variable.
  28. }

下面的测试演示了展示了 EnumSet 在某些场景下的强大功能:

  1. @Test
  2. public void givenPizaOrders_whenRetrievingUnDeliveredPzs_thenCorrectlyRetrieved() {
  3. List<Pizza> pzList = new ArrayList<>();
  4. Pizza pz1 = new Pizza();
  5. pz1.setStatus(Pizza.PizzaStatus.DELIVERED);
  6. Pizza pz2 = new Pizza();
  7. pz2.setStatus(Pizza.PizzaStatus.ORDERED);
  8. Pizza pz3 = new Pizza();
  9. pz3.setStatus(Pizza.PizzaStatus.ORDERED);
  10. Pizza pz4 = new Pizza();
  11. pz4.setStatus(Pizza.PizzaStatus.READY);
  12. pzList.add(pz1);
  13. pzList.add(pz2);
  14. pzList.add(pz3);
  15. pzList.add(pz4);
  16. List<Pizza> undeliveredPzs = Pizza.getAllUndeliveredPizzas(pzList);
  17. assertTrue(undeliveredPzs.size() == 3);
  18. }
  1. EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
  2. EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用内存很小,而且运行效率很好。尤其是进行批量操作(如调用containsAll()retainAll()方法)时,如果其参数也是EnumSet集合,则该批量操作的执行速度也非常快。
  3. EnumSet集合不允许加入null元素,如果试图插入null元素,EnumSet将抛出NullPointerException异常。
  4. EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的类方法来创建EnumSet对象。
  5. 如果只是想判断EnumSet是否包含null元素或试图删除null元素都不会抛出异常,只是删除操作将返回false,因为没有任何null元素被删除。

方法介绍:

  • EnumSet allOf(Class elementType): 创建一个包含指定枚举类里所有枚举值的EnumSet集合。
  • EnumSet complementOf(EnumSet e): 创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,新EnumSet集合包含原EnumSet集合所不包含的、此类枚举类剩下的枚举值(即新EnumSet集合和原EnumSet集合的集合元素加起来是该枚举类的所有枚举值)。
  • EnumSet copyOf(Collection c): 使用一个普通集合来创建EnumSet集合。
  • EnumSet copyOf(EnumSet e): 创建一个指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合。
  • EnumSet noneOf(Class elementType): 创建一个元素类型为指定枚举类型的空EnumSet。
  • EnumSet of(E first,E…rest): 创建一个包含一个或多个枚举值的EnumSet集合,传入的多个枚举值必须属于同一个枚举类。
  • EnumSet range(E from,E to): 创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。

示例代码:

  1. package com.collection;
  2. import java.util.EnumSet;
  3. public class EnumSetTest {
  4. public static void main(String[] args) {
  5. //1.创建一个包含Session(枚举类)里所有枚举值的EnumSet集合
  6. EnumSet e1 = EnumSet.allOf(Session.class);
  7. System.out.println(e1);//[SPRING, SUMMER, FAIL, WINTER]
  8. //2.创建一个空EnumSet
  9. EnumSet e2 = EnumSet.noneOf(Session.class);
  10. System.out.println(e2);//[]
  11. //3. add()空EnumSet集合中添加枚举元素
  12. e2.add(Session.SPRING);
  13. e2.add(Session.SUMMER);
  14. System.out.println(e2);//[SPRING, SUMMER]
  15. //4. 以指定枚举值创建EnumSet集合
  16. EnumSet e3 = EnumSet.of(Session.SPRING,Session.FAIL);
  17. System.out.println(e3);//[SPRING, FAIL]
  18. //5.创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。
  19. EnumSet e4 = EnumSet.range(Session.SPRING,Session.FAIL);
  20. System.out.println(e4);//[SPRING, SUMMER, FAIL]
  21. //6.创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,
  22. // 新EnumSet集合包含原EnumSet集合所不包含的枚举值
  23. EnumSet e5 = EnumSet.complementOf(e4);
  24. System.out.println(e5);//[WINTER]
  25. }
  26. }
  27. //创建一个枚举
  28. enum Session{
  29. SPRING,
  30. SUMMER,
  31. FAIL,
  32. WINTER
  33. }

注意:

除此之外还可以复制另一个EnumSet集合中的所有元素来创建新的EnumSet集合,或者复制另一个Collection集合中的所有元素来创建新的EnumSet集合。

示例:

  1. Collection c = new HashSet();
  2. c.clear();
  3. c.add(Session.SPRING);
  4. c.add(Session.FAIL);
  5. EnumSet e6 = EnumSet.copyOf(c);
  6. System.out.println(e6);//[SPRING, FAIL]

注意:当复制Collection集合中所有元素来创建新的EnumSet集合时,要求Collection集合中的所有元素必须是同一个枚举类的枚举值。

错误示例:

  1. c.add("Java");
  2. e6 = EnumSet.copyOf(c);//java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum

EnumMap

EnumMap是一个专门化的映射实现,用于将枚举常量用作键。与对应的 HashMap相比,它是一个高效紧凑的实现,并且在内部表示为一个数组:

  1. EnumMap<Pizza.PizzaStatus, Pizza> map;

让我们快速看一个真实的示例,该示例演示如何在实践中使用它:

  1. public static EnumMap<PizzaStatus, List<Pizza>>
  2. groupPizzaByStatus(List<Pizza> pizzaList) {
  3. EnumMap<PizzaStatus, List<Pizza>> pzByStatus =
  4. new EnumMap<PizzaStatus, List<Pizza>>(PizzaStatus.class);
  5. for (Pizza pz : pizzaList) {
  6. PizzaStatus status = pz.getStatus();
  7. if (pzByStatus.containsKey(status)) {
  8. pzByStatus.get(status).add(pz);
  9. } else {
  10. List<Pizza> newPzList = new ArrayList<Pizza>();
  11. newPzList.add(pz);
  12. pzByStatus.put(status, newPzList);
  13. }
  14. }
  15. return pzByStatus;
  16. }

下面的测试演示了展示了 EnumMap 在某些场景下的强大功能:

  1. @Test
  2. public void givenPizaOrders_whenGroupByStatusCalled_thenCorrectlyGrouped() {
  3. List<Pizza> pzList = new ArrayList<>();
  4. Pizza pz1 = new Pizza();
  5. pz1.setStatus(Pizza.PizzaStatus.DELIVERED);
  6. Pizza pz2 = new Pizza();
  7. pz2.setStatus(Pizza.PizzaStatus.ORDERED);
  8. Pizza pz3 = new Pizza();
  9. pz3.setStatus(Pizza.PizzaStatus.ORDERED);
  10. Pizza pz4 = new Pizza();
  11. pz4.setStatus(Pizza.PizzaStatus.READY);
  12. pzList.add(pz1);
  13. pzList.add(pz2);
  14. pzList.add(pz3);
  15. pzList.add(pz4);
  16. EnumMap<Pizza.PizzaStatus,List<Pizza>> map = Pizza.groupPizzaByStatus(pzList);
  17. assertTrue(map.get(Pizza.PizzaStatus.DELIVERED).size() == 1);
  18. assertTrue(map.get(Pizza.PizzaStatus.ORDERED).size() == 2);
  19. assertTrue(map.get(Pizza.PizzaStatus.READY).size() == 1);
  20. }

通过枚举实现一些设计模式

单例模式

通常,使用类实现 Singleton 模式并非易事,枚举提供了一种实现单例的简便方法。

《Effective Java 》和《Java与模式》都非常推荐这种方式,使用这种方式方式实现枚举可以有什么好处呢?

《Effective Java》

这种方法在功能上与公有域方法相近,但是它更加简洁,无偿提供了序列化机制,绝对防止多次实例化,即使是在面对复杂序列化或者反射攻击的时候。虽然这种方法还没有广泛采用,但是单元素的枚举类型已经成为实现 Singleton的最佳方法。—-《Effective Java 中文版 第二版》

《Java与模式》

《Java与模式》中,作者这样写道,使用枚举来实现单实例控制会更加简洁,而且无偿地提供了序列化机制,并由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。

下面的代码段显示了如何使用枚举实现单例模式:

  1. public enum PizzaDeliverySystemConfiguration {
  2. INSTANCE; //也可以理解为enum的一个实例对象
  3. PizzaDeliverySystemConfiguration() {
  4. // Initialization configuration which involves
  5. // overriding defaults like delivery strategy
  6. }
  7. private PizzaDeliveryStrategy deliveryStrategy = PizzaDeliveryStrategy.NORMAL;
  8. public static PizzaDeliverySystemConfiguration getInstance() {
  9. return INSTANCE;
  10. }
  11. public PizzaDeliveryStrategy getDeliveryStrategy() {
  12. return deliveryStrategy;
  13. }
  14. }

如何使用呢?请看下面的代码:

  1. PizzaDeliveryStrategy deliveryStrategy = PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy();

通过

  1. PizzaDeliverySystemConfiguration.getInstance()

获取的就是单例的

  1. PizzaDeliverySystemConfiguration

策略模式

通常,策略模式由不同类实现同一个接口来实现的。

这也就意味着添加新策略意味着添加新的实现类。使用枚举,可以轻松完成此任务,添加新的实现意味着只定义具有某个实现的另一个实例。

下面的代码段显示了如何使用枚举实现策略模式:

  1. public enum PizzaDeliveryStrategy {
  2. EXPRESS {
  3. @Override
  4. public void deliver(Pizza pz) {
  5. System.out.println("Pizza will be delivered in express mode");
  6. }
  7. },
  8. NORMAL {
  9. @Override
  10. public void deliver(Pizza pz) {
  11. System.out.println("Pizza will be delivered in normal mode");
  12. }
  13. };
  14. public abstract void deliver(Pizza pz);
  15. }

Pizza增加下面的方法:

  1. public void deliver() {
  2. if (isDeliverable()) {
  3. PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy()
  4. .deliver(this);
  5. this.setStatus(PizzaStatus.DELIVERED);
  6. }
  7. }

如何使用呢?请看下面的代码:

  1. @Test
  2. public void givenPizaOrder_whenDelivered_thenPizzaGetsDeliveredAndStatusChanges() {
  3. Pizza pz = new Pizza();
  4. pz.setStatus(Pizza.PizzaStatus.READY);
  5. pz.deliver();
  6. assertTrue(pz.getStatus() == Pizza.PizzaStatus.DELIVERED);
  7. }

Java 8 与枚举

Pizza 类可以用Java 8重写,您可以看到方法 lambda 和Stream API如何使getAllUndeliveredPizzas()groupPizzaByStatus()方法变得如此简洁:

getAllUndeliveredPizzas():

  1. public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) {
  2. return input.stream().filter(
  3. (s) -> !deliveredPizzaStatuses.contains(s.getStatus()))
  4. .collect(Collectors.toList());
  5. }

groupPizzaByStatus() :

  1. public static EnumMap<PizzaStatus, List<Pizza>>
  2. groupPizzaByStatus(List<Pizza> pzList) {
  3. EnumMap<PizzaStatus, List<Pizza>> map = pzList.stream().collect(
  4. Collectors.groupingBy(Pizza::getStatus,
  5. () -> new EnumMap<>(PizzaStatus.class), Collectors.toList()));
  6. return map;
  7. }

Enum 类型的 JSON 表现形式

使用Jackson库,可以将枚举类型的JSON表示为POJO。下面的代码段显示了可以用于同一目的的Jackson批注:

  1. @JsonFormat(shape = JsonFormat.Shape.OBJECT)
  2. public enum PizzaStatus {
  3. ORDERED (5){
  4. @Override
  5. public boolean isOrdered() {
  6. returntrue;
  7. }
  8. },
  9. READY (2){
  10. @Override
  11. public boolean isReady() {
  12. returntrue;
  13. }
  14. },
  15. DELIVERED (0){
  16. @Override
  17. public boolean isDelivered() {
  18. returntrue;
  19. }
  20. };
  21. privateint timeToDelivery;
  22. public boolean isOrdered() {returnfalse;}
  23. public boolean isReady() {returnfalse;}
  24. public boolean isDelivered(){returnfalse;}
  25. @JsonProperty("timeToDelivery")
  26. public int getTimeToDelivery() {
  27. return timeToDelivery;
  28. }
  29. private PizzaStatus (int timeToDelivery) {
  30. this.timeToDelivery = timeToDelivery;
  31. }
  32. }

我们可以按如下方式使用 PizzaPizzaStatus

  1. Pizza pz = new Pizza();
  2. pz.setStatus(Pizza.PizzaStatus.READY);
  3. System.out.println(Pizza.getJsonString(pz));

生成 Pizza 状态以以下JSON展示:

  1. {
  2. "status" : {
  3. "timeToDelivery" : 2,
  4. "ready" : true,
  5. "ordered" : false,
  6. "delivered" : false
  7. },
  8. "deliverable" : true
  9. }

有关枚举类型的JSON序列化/反序列化(包括自定义)的更多信息,请参阅Jackson-将枚举序列化为JSON对象。

总结

本文我们讨论了Java枚举类型,从基础知识到高级应用以及实际应用场景,让我们感受到枚举的强大功能。

Reference:Java 枚举(enum) 详解7种常见的用法

【Java 基础】Java Enum的更多相关文章

  1. java基础---->java中正则表达式二

    跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...

  2. Java基础-Java中的堆内存和离堆内存机制

    Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  3. Java基础-Java中的内存分配与回收机制

    Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.

  4. Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)

    Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...

  5. Java基础-Java中的并法库之线程池技术

    Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.

  6. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  7. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  8. Java基础-Java数据类型

    Java基础-Java数据类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据类型的作用 数据类型就是一组值,以及这一组值上的操作,数据类型可以决定数据的存储方式,取值范围 ...

  9. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  10. 转载:[Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    原文:http://www.cnblogs.com/wang-meng/p/5898837.html 一:继承.抽象类与接口区别.访问控制(private, public, protected,默认) ...

随机推荐

  1. C#疑问

    在Microsoft.NET里面int=Int32Int64=long但是在其他.NET环境下面可能不是这样的.C#是一门计算机编程语言,是经过标准化,也就是说其他的人也可以根据它的语法去实现它的编译 ...

  2. Semaphore信号量的使用

    package ThreadTest; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; pub ...

  3. javascript-初级-day01-属性操作、图片切换、短信发送模拟

    大多数js就是操作一些css和html的技巧,如果你会html和css学习js更加轻松哦! js中如何获取元素: 通过id名称来获取元素; document get element by id 'li ...

  4. JdbcTemplate 、Mybatis、ORM 、Druid 、HikariCP 、Hibernate是什么?它们有什么关系?

    JdbcTemplate .Mybatis.ORM .Druid .HikariCP .Hibernate是什么?它们有什么关系? 学完Spring和SpringMVC之后,就急于求成的开始学习起Sp ...

  5. C/C++ Qt MdiArea 多窗体组件应用

    MDI多窗体组件,主要用于设计多文档界面应用程序,该组件具备有多种窗体展示风格,其实现了在父窗体中内嵌多种子窗体的功能,使用MDI组件需要在UI界面中增加mdiArea控件容器,我们所有的窗体创建与操 ...

  6. ARC 119 补题记录

    这把感觉质量很高. \(E\) \(E\)比较简单所以先写个\(E\),考虑就一个置换操作来说改变的只有两端的值. 考虑\(|a_i - a_{i - 1}|\)变成区间,则我们考虑分类讨论,发现只有 ...

  7. 洛谷 P6672 - [清华集训2016] 你的生命已如风中残烛(组合数学)

    洛谷题面传送门 题解里一堆密密麻麻的 Raney 引理--蒟蒻表示看不懂,因此决定写一篇题解提供一个像我这样的蒟蒻能理解的思路,或者说,理解方式. 首先我们考虑什么样的牌堆顺序符合条件.显然,在摸牌任 ...

  8. Codeforces 1010F - Tree(分治 NTT+树剖)

    Codeforces 题面传送门 & 洛谷题面传送门 神仙题. 首先我们考虑按照这题的套路,记 \(t_i\) 表示 \(i\) 上的果子数量减去其儿子果子数量之和,那么对于一个合法的放置果子 ...

  9. Atcoder Grand Contest 033 D - Complexity(dp)

    Atcoder 题面传送门 & 洛谷题面传送门 首先 \(n^5\) 的暴力非常容易想,设 \(dp_{a,b,c,d}\) 表示以 \((a,b)\) 为左上角,\((c,d)\) 为右下角 ...

  10. 洛谷 P5401 - [CTS2019]珍珠(NTT+二项式反演)

    题面传送门 一道多项式的 hot tea 首先考虑将题目的限制翻译成人话,我们记 \(c_i\) 为 \(i\) 的出现次数,那么题目的限制等价于 \(\sum\limits_{i=1}^D\lflo ...