枚举*似乎*被多次初始化,构造函数被调用不止一次。如果我是对的,那为什么呢?
Enum *seems* to be initialized more than once, the constructor is called more than once. If I’m right, then why?
我正在通读本教程:
它首先 运行s: ClientAllOrders()
,它创建了 5 个订单。然后它 运行s: ClientDeleteById()
,删除订单 2 和 4。然后它 运行s ClientAllOrders()
,并获取除订单 2、4 之外的所有订单。它创建订单这里:
public enum OrderService {
Instance;
private Map<Integer, Order> orders = new HashMap<>();
OrderService() {
Instant instant = OffsetDateTime.now().toInstant();
for (int i = 1; i <= 5; i++) {
Order order = new Order();
order.setId(i);
order.setItem("item " + i);
order.setQty((int) (1 + Math.random() * 100));
long millis = instant.minus(Period.ofDays(i))
.toEpochMilli();
order.setOrderDate(new Date(millis));
orders.put(i, order);
}
}
//---
}
请注意 OrderResource
不是 Singleton
,因此默认情况下会为每个新请求创建资源 class 的新实例,但是 OrderService.constructor
仅被称为 ones 并且 Enum
按预期仅初始化一次。
上述情况导致此输出:
// ClientAllOrders:
Order{id=1, item='item 1', qty=62, orderDate=Fri Jul 24 18:27:51 EDT 2020}
Order{id=2, item='item 2', qty=100, orderDate=Thu Jul 23 18:27:51 EDT 2020}
Order{id=3, item='item 3', qty=29, orderDate=Wed Jul 22 18:27:51 EDT 2020}
Order{id=4, item='item 4', qty=28, orderDate=Tue Jul 21 18:27:51 EDT 2020}
Order{id=5, item='item 5', qty=28, orderDate=Mon Jul 20 18:27:51 EDT 2020}
// ClientDeleteById – deletes orders 2 and 4:
true
true
// Run ClientAllOrders again:
Order{id=1, item='item 1', qty=62, orderDate=Fri Jul 24 18:27:51 EDT 2020}
Order{id=3, item='item 3', qty=29, orderDate=Wed Jul 22 18:27:51 EDT 2020}
Order{id=5, item='item 5', qty=28, orderDate=Mon Jul 20 18:27:51 EDT 2020}
但是,如果我在 ClientAllOrders
中添加这一行:
Collection<Order> c = OrderService.Instance.getAllOrders();
c.forEach(System.out::println);
然后再次调用OrderService.constructor
,地图中现在有5个新订单。为什么不像 REST
请求都共享同一个 Enum
对象,在这里,Enum
被再次初始化并且 constructor()
被再次调用创建 5 个新订单?
public class ClientAllOrders {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
//get all orders
WebTarget allOrderTarget = client.target("http://localhost:8080/jaxrs-delete-example/orders");
Response response = allOrderTarget.request().get();
List<Order> orders = response.readEntity(new GenericType<List<Order>>() {});
System.out.println("Orders by REST call:");
orders.forEach(System.out::println);
// Added this line - Enum is initialized again and constructor called again, creating new orders:
Collection<Order> c = OrderService.Instance.getAllOrders();
System.out.println("Orders created again:");
c.forEach(System.out::println);
}
}
这是我 运行 ClientAllOrders
的输出,请注意创建的订单不同:
Orders by REST call:
Order{id=1, item='item 1', qty=59, orderDate=Fri Jul 24 18:35:24 EDT 2020}
Order{id=2, item='item 2', qty=14, orderDate=Thu Jul 23 18:35:24 EDT 2020}
Order{id=3, item='item 3', qty=78, orderDate=Wed Jul 22 18:35:24 EDT 2020}
Order{id=4, item='item 4', qty=3, orderDate=Tue Jul 21 18:35:24 EDT 2020}
Order{id=5, item='item 5', qty=2, orderDate=Mon Jul 20 18:35:24 EDT 2020}
Orders created again:
Order{id=1, item='item 1', qty=1, orderDate=Fri Jul 24 18:35:24 EDT 2020}
Order{id=2, item='item 2', qty=53, orderDate=Thu Jul 23 18:35:24 EDT 2020}
Order{id=3, item='item 3', qty=76, orderDate=Wed Jul 22 18:35:24 EDT 2020}
Order{id=4, item='item 4', qty=31, orderDate=Tue Jul 21 18:35:24 EDT 2020}
Order{id=5, item='item 5', qty=25, orderDate=Mon Jul 20 18:35:24 EDT 2020}
客户端和服务器 运行 在不同的进程中,在不同的 JVM 中,独立。服务器有一个版本的enum OrderService
,客户端有另一个。没有任何东西将枚举的这两个实例相互联系起来。
在您的例子中,“服务器”是一个应用程序服务器,您在其中部署 Web 应用程序“war”存档。 “客户端”是一个单独的 Java 程序,带有 main
方法。你 运行 从你的 IDE 使用“运行 作为 Java 应用程序”操作。
我正在通读本教程:
它首先 运行s: ClientAllOrders()
,它创建了 5 个订单。然后它 运行s: ClientDeleteById()
,删除订单 2 和 4。然后它 运行s ClientAllOrders()
,并获取除订单 2、4 之外的所有订单。它创建订单这里:
public enum OrderService {
Instance;
private Map<Integer, Order> orders = new HashMap<>();
OrderService() {
Instant instant = OffsetDateTime.now().toInstant();
for (int i = 1; i <= 5; i++) {
Order order = new Order();
order.setId(i);
order.setItem("item " + i);
order.setQty((int) (1 + Math.random() * 100));
long millis = instant.minus(Period.ofDays(i))
.toEpochMilli();
order.setOrderDate(new Date(millis));
orders.put(i, order);
}
}
//---
}
请注意 OrderResource
不是 Singleton
,因此默认情况下会为每个新请求创建资源 class 的新实例,但是 OrderService.constructor
仅被称为 ones 并且 Enum
按预期仅初始化一次。
上述情况导致此输出:
// ClientAllOrders:
Order{id=1, item='item 1', qty=62, orderDate=Fri Jul 24 18:27:51 EDT 2020}
Order{id=2, item='item 2', qty=100, orderDate=Thu Jul 23 18:27:51 EDT 2020}
Order{id=3, item='item 3', qty=29, orderDate=Wed Jul 22 18:27:51 EDT 2020}
Order{id=4, item='item 4', qty=28, orderDate=Tue Jul 21 18:27:51 EDT 2020}
Order{id=5, item='item 5', qty=28, orderDate=Mon Jul 20 18:27:51 EDT 2020}
// ClientDeleteById – deletes orders 2 and 4:
true
true
// Run ClientAllOrders again:
Order{id=1, item='item 1', qty=62, orderDate=Fri Jul 24 18:27:51 EDT 2020}
Order{id=3, item='item 3', qty=29, orderDate=Wed Jul 22 18:27:51 EDT 2020}
Order{id=5, item='item 5', qty=28, orderDate=Mon Jul 20 18:27:51 EDT 2020}
但是,如果我在 ClientAllOrders
中添加这一行:
Collection<Order> c = OrderService.Instance.getAllOrders();
c.forEach(System.out::println);
然后再次调用OrderService.constructor
,地图中现在有5个新订单。为什么不像 REST
请求都共享同一个 Enum
对象,在这里,Enum
被再次初始化并且 constructor()
被再次调用创建 5 个新订单?
public class ClientAllOrders {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
//get all orders
WebTarget allOrderTarget = client.target("http://localhost:8080/jaxrs-delete-example/orders");
Response response = allOrderTarget.request().get();
List<Order> orders = response.readEntity(new GenericType<List<Order>>() {});
System.out.println("Orders by REST call:");
orders.forEach(System.out::println);
// Added this line - Enum is initialized again and constructor called again, creating new orders:
Collection<Order> c = OrderService.Instance.getAllOrders();
System.out.println("Orders created again:");
c.forEach(System.out::println);
}
}
这是我 运行 ClientAllOrders
的输出,请注意创建的订单不同:
Orders by REST call:
Order{id=1, item='item 1', qty=59, orderDate=Fri Jul 24 18:35:24 EDT 2020}
Order{id=2, item='item 2', qty=14, orderDate=Thu Jul 23 18:35:24 EDT 2020}
Order{id=3, item='item 3', qty=78, orderDate=Wed Jul 22 18:35:24 EDT 2020}
Order{id=4, item='item 4', qty=3, orderDate=Tue Jul 21 18:35:24 EDT 2020}
Order{id=5, item='item 5', qty=2, orderDate=Mon Jul 20 18:35:24 EDT 2020}
Orders created again:
Order{id=1, item='item 1', qty=1, orderDate=Fri Jul 24 18:35:24 EDT 2020}
Order{id=2, item='item 2', qty=53, orderDate=Thu Jul 23 18:35:24 EDT 2020}
Order{id=3, item='item 3', qty=76, orderDate=Wed Jul 22 18:35:24 EDT 2020}
Order{id=4, item='item 4', qty=31, orderDate=Tue Jul 21 18:35:24 EDT 2020}
Order{id=5, item='item 5', qty=25, orderDate=Mon Jul 20 18:35:24 EDT 2020}
客户端和服务器 运行 在不同的进程中,在不同的 JVM 中,独立。服务器有一个版本的enum OrderService
,客户端有另一个。没有任何东西将枚举的这两个实例相互联系起来。
在您的例子中,“服务器”是一个应用程序服务器,您在其中部署 Web 应用程序“war”存档。 “客户端”是一个单独的 Java 程序,带有 main
方法。你 运行 从你的 IDE 使用“运行 作为 Java 应用程序”操作。