提出问题

如何处理异常才能使代码更简洁???

解决问题

1)使用异常而非返回码,这里的异常处理就是我们经常写的try catch;

  1. package com.hwy.test;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. public class CodeCleanTest {
  5. private Logger log = LoggerFactory.getLogger(this.getClass());
  6. public boolean eat(){
  7. boolean isCompleted = false;
  8. try{
  9. System.out.println("美味");
  10. isCompleted = true;
  11. }catch (Exception e){
  12. log.info(e.getMessage());
  13. }
  14. return isCompleted;
  15. }
  16. }

2)不要返回null值:这样的话调用者就要处理null,增加工作量;解决:抛出异常或者返回特例对象(利用Collections.emptyList());

错误示例:

  1. package com.hwy.test;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. public class CodeCleanTest {
  7. private Logger log = LoggerFactory.getLogger(this.getClass());
  8. /**
  9. * 约会
  10. */
  11. public void datWithGirl(){
  12. List<String> snacksList = buySnacks();
  13. if(null != snacksList){
  14. List<String> litter = eatSnacks(snacksList);
  15. dropLitter(litter);
  16. }
  17. }
  18. /**
  19. * 买零食(事实这些注释都是不需要,只是为了大家理解)
  20. * @return
  21. */
  22. public List<String> buySnacks(){
  23. List<String> snacksList = new ArrayList<>();
  24. snacksList.add("牛奶");
  25. snacksList.add("巧克力");
  26. snacksList.add("土豆片");
  27. return snacksList;
  28. }
  29. /**
  30. * 吃零食(事实这些注释都是不需要,只是为了大家理解)
  31. * @param snacks
  32. */
  33. public List<String> eatSnacks(List<String> snacks){
  34. if(null != snacks) {
  35. for (String snack : snacks) {
  36. System.out.println("一起吃" + snack);
  37. }
  38. }
  39. return snacks;
  40. }
  41. /**
  42. * 仍垃圾(事实这些注释都是不需要,只是为了大家理解)
  43. * @param litter
  44. */
  45. public void dropLitter(List<String> litter){
  46. if(null != litter){
  47. for(String snack:litter){
  48. System.out.println("一起吃" + snack);
  49. }
  50. }
  51. }
  52. }

正确示例:可看里面详细的注释,要有耐心哦!

package com.hwy.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class CodeCleanTest {
   private Logger log = LoggerFactory.getLogger(this.getClass());
   /**
    * 约会
    */
   public void datWithGirl() throws Exception {
       List<String> snacksList =  buySnacks();
       /** 利用逆向思维,抛出一个业务异常,这里我只是用简单的exception代替 **/
       if(null == snacksList || snacksList.size() ==0){
           throw new Exception("你没买到零食或买到的零食有问题,请检查!");
       }
       /** 代码执行到这一步就说明snacksList不为null,之后的所有
        * 操作都不用判断snacksList是否为空 **/
       List<String> litter =  eatSnacks(snacksList);
       dropLitter(litter);
   }
   /**
    * 买零食(事实这些注释都是不需要,只是为了大家理解)
    * @return
    */
   public List<String> buySnacks(){
       List<String> snacksList = new ArrayList<>();
       snacksList.add("牛奶");
       snacksList.add("巧克力");
       snacksList.add("土豆片");
       /** 在这里如果snacksList为空的话,可以用Collections.emptyList(),就不用
       ** 在上面处理异常了 **/
       //return Collections.emptyList();
       return snacksList;
   }
   /**
    * 吃零食(事实这些注释都是不需要,只是为了大家理解)
    * @param snacks
    */
   public List<String> eatSnacks(List<String> snacks){
       for (String snack : snacks) {
           System.out.println("一起吃" + snack);
       }
       return snacks;
   }
   /**
    * 仍垃圾(事实这些注释都是不需要,只是为了大家理解)
    * @param litter
    */
   public void dropLitter(List<String> litter){
       for(String snack:litter){
           System.out.println("一起吃" + snack);
       }
   }
}

3)在方法中返回null值是很糟糕的,但讲null传递给其他方法就更糟糕了,具体解决方法如下:

package com.hwy.test;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
public class CodeCleanTest {
   private Logger log = LoggerFactory.getLogger(this.getClass());
   public static void main(String[] args) throws Exception {
       datWithGirl();
   }
   /**
    * 约会
    */
   public static void datWithGirl(){
       /** 这里返回为null **/
       List<String> snacksList =  buySnacks();
       /** 在吃零食方法中,需要处理异常 **/
       List<String> litter =  eatSnacks(snacksList);
       dropLitter(litter);
   }
   /**
    * 买零食(事实这些注释都是不需要,只是为了大家理解)
    * @return
    */
   public static List<String> buySnacks(){
       return null;
   }
   /**
    * 吃零食(事实这些注释都是不需要,只是为了大家理解)
    * @param snacks
    */
   public static List<String> eatSnacks(List<String> snacks){
       /** 第一种处理方法 **/
//        if(null == snacks){
//            throw new NullPointerException("没有零食吃!!!");
//        }
       /** 第二种处理方法, **/
       Assert.assertNotNull("没有零食吃!!!",snacks);
       for (String snack : snacks) {
           System.out.println("一起吃" + snack);
       }
       return snacks;
   }
   /**
    * 仍垃圾(事实这些注释都是不需要,只是为了大家理解)
    * @param litter
    */
   public static void dropLitter(List<String> litter){
       for(String snack:litter){
           System.out.println("一起吃" + snack);
       }
   }
}

运行结果:

java.lang.AssertionError: 没有零食吃!!!
at org.junit.Assert.fail(Assert.java:93)
at org.junit.Assert.assertTrue(Assert.java:43)
at org.junit.Assert.assertNotNull(Assert.java:526)
at com.hwy.test.CodeCleanTest.eatSnacks(CodeCleanTest.java:48)
at com.hwy.test.CodeCleanTest.datWithGirl(CodeCleanTest.java:23)
at com.hwy.test.CodeCleanTest.main(CodeCleanTest.java:13)

4)不管做哪种类型的应用,都应该尽可能向用户隐藏异常的发生,除非发生了不可挽救的状况,这才是符合最小惊讶原则的设计

5)异常的信息应该足够充分(包含出错的位置以及原因)

6)避免使用可控异常(checked exception):因为处理它们需要修改函数头(在每个调用该函数的函数添加throw Exception),违反了开放-闭合原则;应该使用不可控异常(runtime exception);