Java 代碼精簡之道 (上)

1.利用語法

1.1.利用三元表達式

普通:java

String title;
if (isMember(phone)) {
    title = "會員";
else {
    title = "遊客";
}

精簡:
數組

String title = isMember(phone) ? "會員" : "遊客";

注意:對於包裝類型的算術計算,須要注意避免拆包時的空指針問題。
app


1.2.利用 for-each 語句
ide

從 Java 5 起,提供了 for-each 循環,簡化了數組和集合的循環遍歷。for-each  循環容許你無需保持傳統 for 循環中的索引就能夠遍歷數組,或在使用迭代器時無需在 while 循環中調用 hasNext 方法和 next 方法就能夠遍歷集合。函數

普通:ui

double[] values = ...;
for(int i = 0; i < values.length; i++) {
    double value = values[i];
    // TODO: 處理value
}
List<Double> valueList = ...;
Iterator<Double> iterator = valueList.iterator();
while (iterator.hasNext()) {
    Double value = iterator.next();
    // TODO: 處理value
}

精簡:this

double[] values = ...;
for(double value : values) {
    // TODO: 處理value
}

List<Double> valueList = ...;
for(Double value : valueList) {
    // TODO: 處理value
}


1.3.利用 try-with-resource 語句

全部實現 Closeable 接口的「資源」,都可採用 try-with-resource 進行簡化。spa

普通:線程

BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("cities.csv"));
    String line;
    while ((line = reader.readLine()) != null) {
        // TODO: 處理line
    }
catch (IOException e) {
    log.error("讀取文件異常", e);
finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException e) {
            log.error("關閉文件異常", e);
        }
    }
}

精簡:指針

try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        // TODO: 處理line
    }
catch (IOException e) {
    log.error("讀取文件異常", e);
}


1.4.利用 return 關鍵字

利用 return 關鍵字,能夠提早函數返回,避免定義中間變量

普通:

public static boolean hasSuper(@NonNull List<UserDO> userList) {
    boolean hasSuper = false;
    for (UserDO user : userList) {
        if (Boolean.TRUE.equals(user.getIsSuper())) {
            hasSuper = true;
            break;
        }
    }
    return hasSuper;
}

精簡:

public static boolean hasSuper(@NonNull List<UserDO> userList) {
    for (UserDO user : userList) {
        if (Boolean.TRUE.equals(user.getIsSuper())) {
            return true;
        }
    }
    return false;
}


1.5.利用 static 關鍵字

利用 static 關鍵字,能夠把字段變成靜態字段,也能夠把函數變爲靜態函數,調用時就無需初始化類對象。

普通:

public final class GisHelper {
    public double distance(double lng1, double lat1, double lng2, double lat2) {
        // 方法實現代碼
    }
}
GisHelper gisHelper = new GisHelper();
double distance = gisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);

精簡:

public final class GisHelper {
    public static double distance(double lng1, double lat1, double lng2, double lat2) {
        // 方法實現代碼
    }
}

double distance = GisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);


1.6.利用 lambda 表達式

Java 8 發佈之後,lambda 表達式大量替代匿名內部類的使用,在簡化了代碼的同時,更突出了原有匿名內部類中真正有用的那部分代碼。

普通:

new Thread(new Runnable() {
    public void run() {
        // 線程處理代碼
    }
}).start();

精簡:

new Thread(() -> {
    // 線程處理代碼
}).start();


1.7.利用方法引用

方法引用(::),能夠簡化 lambda 表達式,省略變量聲明和函數調用。

普通:

Arrays.sort(nameArray, (a, b) -> a.compareToIgnoreCase(b));
List<Long> userIdList = userList.stream()
    .map(user -> user.getId())
    .collect(Collectors.toList());

精簡:

Arrays.sort(nameArray, String::compareToIgnoreCase);
List<Long> userIdList = userList.stream()
    .map(UserDO::getId)
    .collect(Collectors.toList());


1.8.利用靜態導入

靜態導入(import static),當程序中大量使用同一靜態常量和函數時,能夠簡化靜態常量和函數的引用。

普通:

List<Double> areaList = radiusList.stream().map(r -> Math.PI * Math.pow(r, 2)).collect(Collectors.toList());
...

精簡:

import static java.lang.Math.PI;
import static java.lang.Math.pow;
import static java.util.stream.Collectors.toList;

List<Double> areaList = radiusList.stream().map(r -> PI * pow(r, 2)).collect(toList());
...

注意:靜態引入容易形成代碼閱讀困難,因此在實際項目中應該警慎使用。


1.9.利用 unchecked 異常

Java 的異常分爲兩類:Checked 異常和 Unchecked 異常。Unchecked 異常繼承了RuntimeException ,特色是代碼不須要處理它們也能經過編譯,因此它們稱做  Unchecked 異常。利用 Unchecked 異常,能夠避免沒必要要的 try-catch 和 throws 異常處理。

普通:

@Service
public class UserService {
    public void createUser(UserCreateVO create, OpUserVO user) throws BusinessException {
        checkOperatorUser(user);
        ...
    }
    private void checkOperatorUser(OpUserVO user) throws BusinessException {
        if (!hasPermission(user)) {
            throw new BusinessException("用戶無操做權限");
        }
        ...
    }
    ...
}

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/createUser")
    public Result<Void> createUser(@RequestBody @Valid UserCreateVO create, OpUserVO user) throws BusinessException {
        userService.createUser(create, user);
        return Result.success();
    }
    ...
}

精簡:

@Service
public class UserService {
    public void createUser(UserCreateVO create, OpUserVO user) {
        checkOperatorUser(user);
        ...
    }
    private void checkOperatorUser(OpUserVO user) {
        if (!hasPermission(user)) {
            throw new Busine***untimeException("用戶無操做權限");
        }
        ...
    }
    ...
}

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/createUser")
    public Result<Void> createUser(@RequestBody @Valid UserCreateVO create, OpUserVO user) {
        userService.createUser(create, user);
        return Result.success();
    }
    ...
}


2.利用註解

2.1.利用 Lombok 註解

Lombok 提供了一組有用的註解,能夠用來消除Java類中的大量樣板代碼。

普通:

public class UserVO {
    private Long id;
    private String name;
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    ...
}

普通:

@Getter
@Setter
@ToString
public class UserVO {
    private Long id;
    private String name;
    ...
}


2.2.利用 @NonNull 註解

Spring 的 @NonNull 註解,用於標註參數或返回值非空,適用於項目內部團隊協做。只要實現方和調用方遵循規範,能夠避免沒必要要的空值判斷,這充分體現了阿里的「新六脈神劍」提倡的「由於信任,因此簡單」。

普通:

public List<UserVO> queryCompanyUser(Long companyId) {
    // 檢查公司標識
    if (companyId == null) {
        return null;
    }

    // 查詢返回用戶
    List<UserDO> userList = userDAO.queryByCompanyId(companyId);
    return userList.stream().map(this::transUser).collect(Collectors.toList());
}

Long companyId = 1L;
List<UserVO> userList = queryCompanyUser(companyId);
if (CollectionUtils.isNotEmpty(userList)) {
    for (UserVO user : userList) {
        // TODO: 處理公司用戶
    }
}

精簡:

public @NonNull List<UserVO> queryCompanyUser(@NonNull Long companyId) {
    List<UserDO> userList = userDAO.queryByCompanyId(companyId);
    return userList.stream().map(this::transUser).collect(Collectors.toList());
}

Long companyId = 1L;
List<UserVO> userList = queryCompanyUser(companyId);
for (UserVO user : userList) {
    // TODO: 處理公司用戶
}


2.3.利用註解特性

註解有如下特性可用於精簡註解聲明:


一、當註解屬性值跟默認值一致時,能夠刪除該屬性賦值;二、當註解只有value屬性時,能夠去掉value進行簡寫;三、當註解屬性組合等於另外一個特定註解時,直接採用該特定註解。

普通:


@Lazy(true);
@Service(value = "userService")
@RequestMapping(path = "/getUser", method = RequestMethod.GET)

精簡:

@Lazy
@Service("userService")
@GetMapping("/getUser")




3.利用泛型

3.1.泛型接口

在 Java 沒有引入泛型前,都是採用 Object 表示通用對象,最大的問題就是類型沒法強校驗而且須要強制類型轉換。

普通:

public interface Comparable {
    public int compareTo(Object other);
}

@Getter
@Setter
@ToString
public class UserVO implements Comparable {
    private Long id;

    @Override
    public int compareTo(Object other) {
        UserVO user = (UserVO)other;
        return Long.compare(this.id, user.id);
    }
}

精簡:

public interface Comparable<T{
    public int compareTo(T other);
}

@Getter
@Setter
@ToString
public class UserVO implements Comparable<UserVO{
    private Long id;

    @Override
    public int compareTo(UserVO other) {
        return Long.compare(this.id, other.id);
    }
}


3.2.泛型類

普通:

@Getter
@Setter
@ToString
public class IntPoint {
    private Integer x;
    private Integer y;
}

@Getter
@Setter
@ToString
public class DoublePoint {
    private Double x;
    private Double y;
}

精簡:

@Getter
@Setter
@ToString
public class Point<T extends Number{
    private T x;
    private T y;
}


3.3.泛型方法

普通:

public static Map<String, Integer> newHashMap(String[] keys, Integer[] values) {
    // 檢查參數非空
    if (ArrayUtils.isEmpty(keys) || ArrayUtils.isEmpty(values)) {
        return Collections.emptyMap();
    }

    // 轉化哈希映射
    Map<String, Integer> map = new HashMap<>();
    int length = Math.min(keys.length, values.length);
    for (int i = 0; i < length; i++) {
        map.put(keys[i], values[i]);
    }
    return map;
}
...

精簡:

public static <K, V> Map<K, V> newHashMap(K[] keys, V[] values) {
    // 檢查參數非空
    if (ArrayUtils.isEmpty(keys) || ArrayUtils.isEmpty(values)) {
        return Collections.emptyMap();
    }

    // 轉化哈希映射
    Map<K, V> map = new HashMap<>();
    int length = Math.min(keys.length, values.length);
    for (int i = 0; i < length; i++) {
        map.put(keys[i], values[i]);
    }
    return map;}
相關文章
相關標籤/搜索