• [改善Java代码]异常只为异常服务


    异常原本是正常逻辑的补充,但是有时候会被当做主逻辑使用.看如下代码:

     1 public class Client {
     2     enum Color {
     3         Red, Blue;
     4     }
     5 
     6     public static void main(String[] args) {
     7         System.out.println(Contain(Color.class, "Red"));//true
     8         System.out.println(Contain(Color.class, "Yellow"));//false
     9     }
    10 
    11     // 判断一个枚举是否包含String枚举项
    12     public static <T extends Enum<T>> boolean Contain(Class<T> c, String name) {
    13         boolean result = false;
    14         try {
    15             Enum.valueOf(c, name);
    16             result = true;
    17         } catch (RuntimeException e) {
    18             // 只要是抛出异常,则认为是不包含
    19         }
    20         return result;
    21     }
    22 }

     判断一个枚举是否包含指定的枚举项,这里会根据valueOf方法是否抛出异常来进行判断,如果抛出异常(一般是IllegalArgumentException异常),则认为是不包含,若不抛出异常则可以认为包含该枚举项,看上去这段代码很正常,但是其中却有三个错误:

    1.异常判断降低了系统性能.

    2.降低了代码的可读性,只有详细了解valueOf方法的人才能读懂这样的代码,因为valueOf抛出是一个非受检异常.

    3.隐藏了运行期可能产生的错误,catch异常,但没有做任何的处理.

    上面的代码是用一段异常实现了一个正常的业务逻辑,这导致代码产生了坏味道,我们要在主逻辑中不使用异常.

    代码如下:

    public class Client {
        enum Color {
            Red, Blue;
        }
    
        public static void main(String[] args) {
            System.out.println(Contain(Color.class, "不存在的枚举项"));
            System.out.println(Contain(Color.class, "Blue"));
        }
    
        // 判断一个枚举是否包含String枚举项
        public static <T extends Enum<T>> boolean Contain(Class<T> c, String name) {
            //遍历枚举项
            for(T t:c.getEnumConstants()){
                //枚举项名称是否相等
                if(t.name().equals(name)){
                    return true;
                }
            }
            return false;    
        }
    }

    异常只能用在非正常的情况下,不能成为正常情况的主逻辑,也就是异常只是主场景中的辅助场景,不能喧宾夺主.

    而且异常虽然是描述例外事件的,但能避免尽量避免,例如:

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    
    public class Client {
        public static void main(String[] args) {
            File file = new File("文件.txt");
            try {
                FileInputStream fis = new FileInputStream(file);
                /* 其他业务逻辑处理 */
            } catch (FileNotFoundException e) {
                // 异常处理
            }
        }
    }

    这样一段代码经常在项目中出现,但经常写并不代表不能优化,这里的异常类FileNotFoundException完全可以在它诞生之前就消除掉:先判断文件是否存在,然后再生成FileInputStream对象.

    代码如下:

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    
    public class Client {
        public static void main(String[] args) {
            File file = new File("文件.txt");
            //经常出现的异常情况,可以先做判断
            if (file.exists() && !file.isDirectory()) {
                try {
                    FileInputStream fis = new FileInputStream(file);
                    /* 其他业务逻辑处理 */
                } catch (FileNotFoundException e) {
                    // 异常处理
                }
            }
        }
    }

    虽然增加了If判断,增加了代码量,诞生却会减少FileNotFoundException异常出现的几率,提高了程序的性能和稳定性. 

  • 相关阅读:
    如何在C++中获得完整的类型名称(RTTI的typeid在不同平台下有不同的输出值表达,自建类改进了RTTI丢失的信息)
    对Msn协议的一点点研究
    UTF-8、UTF-16、UTF-32编码的相互转换
    支持引用计数的智能指针类模板
    一个简单的RTTI实现
    js 调用父窗口的方法
    关于内存对齐的那些事
    Delphi 函数指针(三大好处:灵活,委托的本质,回调机制),还可把函数指针当参数传入
    自写的LastPos,寻找字符串里的最后一个字符,RTL里没有提供这个函数——Delphi的String下标是从1开始的
    墨菲定律——别试图教猫唱歌,这样不但不会有结果,还会惹猫不高兴(就是不要把自己的意志强加于别人,无论是好心还是坏心)
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5623097.html
Copyright © 2020-2023  润新知