为什么要代码重构?如何重构?常见重构技巧,2024最新中高阶Java面试题总结

return;

} else {

setHello();

}

}

}

}

//使用卫语句

public void getHello(int type) {

if (type == 1) {

return;

}

if (type == 2) {

return;

}

if (type == 3) {

return;

}

setHello();

}

复制代码

使用多态替代条件判断断

当存在这样一类条件表达式,它根据对象类型的不同选择不同的行为。可以将这种表达式的每个分支放进一个子类内的复写函数中,然后将原始函数声明为抽象函数。

public int calculate(int a, int b, String operator) {

int result = Integer.MIN_VALUE;

if (“add”.equals(operator)) {

result = a + b;

} else if (“multiply”.equals(operator)) {

result = a * b;

} else if (“divide”.equals(operator)) {

result = a / b;

} else if (“subtract”.equals(operator)) {

result = a - b;

}

return result;

}

复制代码

当出现大量类型检查和判断时,if else(或switch)语句的体积会比较臃肿,这无疑降低了代码的可读性。另外,if else(或switch)本身就是一个“变化点”,当需要扩展新的类型时,我们不得不追加if else(或switch)语句块,以及相应的逻辑,这无疑降低了程序的可扩展性,也违反了面向对象的开闭原则。

基于这种场景,我们可以考虑使用“多态”来代替冗长的条件判断,将if else(或switch)中的“变化点”封装到子类中。这样,就不需要使用if else(或switch)语句了,取而代之的是子类多态的实例,从而使得提高代码的可读性和可扩展性。很多设计模式使用都是这种套路,比如策略模式、状态模式。

public interface Operation {

int apply(int a, int b);

}

public class Addition implements Operation {

@Override

public int apply(int a, int b) {

return a + b;

}

}

public class OperatorFactory {

private final static Map<String, Operation> operationMap = new HashMap<>();

static {

operationMap.put(“add”, new Addition());

operationMap.put(“divide”, new Division());

// more operators

}

public static Operation getOperation(String operator) {

return operationMap.get(operator);

}

}

public int calculate(int a, int b, String operator) {

if (OperatorFactory .getOperation == null) {

throw new IllegalArgumentException(“Invalid Operator”);

}

return OperatorFactory .getOperation(operator).apply(a, b);

}

复制代码

使用异常替代返回错误码

非正常业务状态的处理,使用抛出异常的方式代替返回错误码

  • 不要使用异常处理用于正常的业务流程控制

    • 异常处理的性能成本非常高
  • 尽量使用标准异常

  • 避免在finally语句块中抛出异常

    • 如果同时抛出两个异常,则第一个异常的调用栈会丢失
  • finally块中应只做关闭资源这类的事情

//使用错误码

public boolean withdraw(int amount) {

if (balance < amount) {

return false;

} else {

balance -= amount;

return true;

}

}

//使用异常

public void withdraw(int amount) {

if (amount > balance) {

throw new IllegalArgumentException(“amount too large”);

}

balance -= amount;

}

复制代码

引入断言

某一段代码需要对程序状态做出某种假设,以断言明确表现这种假设。

  • 不要滥用断言,不要使用它来检查“应该为真”的条件,只使用它来检查“一定必须为真”的条件

  • 如果断言所指示的约束条件不能满足,代码是否仍能正常运行?如果可以就去掉断言

引入Null对象或特殊对象

当使用一个方法返回的对象时,而这个对象可能为空,这个时候需要对这个对象进行操作前,需要进行判空,否则就会报空指针。当这种判断频繁的出现在各处代码之中,就会影响代码的美观程度和可读性,甚至增加Bug的几率。

空引用的问题在Java中无法避免,但可以通过代码编程技巧(引入空对象)来改善这一问题。

//空对象的例子

public class OperatorFactory {

static Map<String, Operation> operationMap = new HashMap<>();

static {

operationMap.put(“add”, new Addition());

operationMap.put(“divide”, new Division());

// more operators

}

public static Optional getOperation(String operator) {

return Optional.ofNullable(operationMap.get(operator));

}

}

public int calculate(int a, int b, String operator) {

Operation targetOperation = OperatorFactory.getOperation(operator)

.orElseThrow(() -> new IllegalArgumentException(“Invalid Operator”));

return targetOperation.apply(a

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值