
阿里Java开发手册中,值得注意的点
一. 编程规约
1. 命名风格
这些
default
方法提供了通用的操作(删除、查询),对所有实现类都有价值。
2. 常量定义
3. 代码格式(这儿最好全看,这里面是摘一些没注意到的)
4. OOP规约
关于建议
是的,**在大多数情况下,使用集合(如 ListSet
)是一个更好的选择**,而不是使用可变参数。以下是具体原因和详细分析:
---
### **1. 为什么集合比可变参数更好?**
#### **(1)代码可读性更强**
- 使用集合作为参数时,方法签名更加明确。调用者可以清楚地知道需要传入一个集合,而不是任意数量的参数。
- 例如:
```java
public List<User> listUsers(String type, List<Long> ids);
```
调用者一看就知道需要传入一个 List<Long>
,而不是不确定数量的 Long
参数。
#### **(2)避免可变参数的模糊性**
- 可变参数的方法签名无法明确表达需要传入的参数数量,调用者可能误用。
- 例如:
```java
public List<User> listUsers(String type, Long... ids);
```
调用者可能错误地传入 0 个参数,导致方法逻辑需要处理边界情况。
#### **(3)更灵活的集合操作**
- 集合提供了丰富的操作方法(如 addremovecontains
等),可以更方便地处理数据。
- 例如,可以直接对传入的集合进行过滤、排序等操作,而不需要先将可变参数转换为集合。
#### **(4)减少性能开销**
- 可变参数在底层是通过数组实现的,每次调用方法时都会创建一个新的数组对象,可能产生不必要的内存开销。
- 使用集合时,调用者可以复用已有的集合对象,减少内存分配和垃圾回收的开销。
#### **(5)更好的类型安全**
- 可变参数的类型如果是 Object
,调用者可以传入任意类型的参数,可能导致运行时错误。
- 使用集合时,可以通过泛型明确参数类型,避免类型安全问题。
```java
public void process(List<String> values); // 明确要求传入 String 类型的集合
```
#### **(6)更容易测试**
- 集合作为参数时,测试代码更容易编写和维护。可以直接构造一个集合对象作为测试输入,而不需要处理可变参数的边界情况。
---
### **2. 集合的替代方案示例**
#### **(1)使用 List
作为参数**
```java
public List<User> listUsers(String type, List<Long> ids) {
// 方法逻辑
}
```
调用时:
```java
List<Long> ids = Arrays.asList(1L, 2L, 3L);
listUsers("type", ids);
```
#### **(2)使用 Set
作为参数(如果需要去重)**
```java
public List<User> listUsers(String type, Set<Long> ids) {
// 方法逻辑
}
```
调用时:
```java
Set<Long> ids = new HashSet<>(Arrays.asList(1L, 2L, 3L));
listUsers("type", ids);
```
#### **(3)使用 Collection
作为参数(如果需要更通用的集合类型)**
```java
public List<User> listUsers(String type, Collection<Long> ids) {
// 方法逻辑
}
```
调用时:
```java
List<Long> ids = Arrays.asList(1L, 2L, 3L);
listUsers("type", ids);
```
---
### **3. 什么情况下可以使用可变参数?**
尽管集合是更好的选择,但在某些特定情况下,可变参数仍然可以发挥作用:
- **参数数量较少且固定**:例如工具类方法(如 String.format
)。
- **简化调用**:例如日志工具(如 Logger.info
)通常使用可变参数。
- **兼容旧代码**:如果已有代码使用了可变参数,为了保持兼容性,可以继续使用。
---
### **4. 总结**
- **在大多数情况下,使用集合(如 ListSet
)是更好的选择**,因为集合提供了更好的可读性、灵活性和类型安全性。
- **可变参数虽然方便,但容易引入模糊性和潜在问题,建议尽量避免使用**。
- **如果需要简化调用,可以考虑使用集合与可变参数结合的方式**,例如:
```java
public List<User> listUsers(String type, Long... ids) {
return listUsers(type, Arrays.asList(ids));
}
```
通过遵循这些建议,你可以编写出更加健壮、清晰和易于维护的代码。
背景:
Java 中的整型包装类(如
Integer
、Long
等)是对象,而不是基本类型。对象的比较应该使用
equals
方法,而不是==
。对于
Integer
类型,Java 在-128
到127
之间的值会缓存(通过IntegerCache
),因此在这个范围内,==
可能会返回true
,但这并不是通用的行为。
原因:
使用
==
比较的是对象的引用(内存地址),而equals
比较的是对象的值。在
-128
到127
之外的整数值,每次赋值都会创建一个新的对象,==
会返回false
。
背景:货币金额涉及精确计算,使用浮点数(如
float
或double
)可能会导致精度丢失。例如,
0.1
在二进制浮点数中无法精确表示,可能导致计算错误。
原因:
将金额存储为最小货币单位的整数,可以避免浮点数的精度问题。
例如,人民币的最小单位是分,存储时可以将金额转换为分(整数)而不是元(浮点数)。