• 极客不落🐒
    2019-01-30
    当方法中返回的数组或集合,会有为空的情况,不要直接返回 null(会强迫调用方需要进行判空处理,否则可能出现 NullPointerException),最好返回大小为 0 的数组或集合。

    其实分配一个空数组或集合所花费的时间和空间,性能损坏是很小到基本可以忽略不计的。同时,如果返回的空数组或者集合是 immutable(即不可变的)的话,可以进一步定义成 static final(对于数组而言)或者 Collections.emptyList()/emptyMap()/emptySet(),来公用同一个对象,减少性能影响。

    作者回复: 这个留言必须赞!

     1
     26
  • 木白
    2019-03-28
    “ 对于异常类名,我们要准确地选择异常类。” 老师,我们应该怎么去快速准确地知道需要抛哪个异常呢?因为有时候只是觉得应该做异常检测,但是属于哪种异常自己也描述不清楚。需要把jdk中的异常都记下来吗?我就是那种直接抛Exception异常的。

    作者回复: 坏消息是,即使我们记住了所有的JDK异常类,也仅仅是异常世界的一小部分,不够用的。 好消息是,没有人能记住即便是JDK这么少的异常类,所有我们也不要折磨自己去记住所有的异常。

    首先要记住,异常是一个可以扩展的类,需要时可以自己定义。所以,你的应用可以有自己定义的异常类。

    弄不清楚使用哪种异常,有两种情况比较典型,一种是不了解调用的类;另一种是不了解自己编写的代码的逻辑。这两条清楚了,异常就清楚了。这两条不清楚,代码也很难清楚。

    异常就不正常的状况。不正常的状况是什么,搞清楚了,异常该是什么也就知道了八九分。然后,去找合适的现存异常类,或者定义新的异常类,剩下的一两分工作也就凑齐了。

    比如说,我回复这条信息的时候,总是输错字母。要是用异常表示,这个不正常的状况就是“键盘输入信息错误”。 然后,在你使用的类库中,去寻找有没有表示这个不正常状况的异常,找到了就用。找不到,如果你想精确定义,就自己定义一个KeyboadInputException; 如果你不想定义新异常,就扩大概念,从“键盘输入信息错误"扩大到"输入信息错误"。然后IOException就是大家都常用的异常了,然后你就可以使用new IOException("键盘输入信息错误")来表示“键盘输入信息错误”这个不正常状况了。

    就这样,了解的代码,了解了不正常的状况到底是什么状况。

    
     3
  • 老杨同志
    2019-01-25
    1. 没找到结果应该是正常业务,不用抛出异常
    2. 缺失必要的参数校验

    import java.util.HashMap;
    import java.util.Map;

    class Solution {
        /**
         * Given an array of integers, return indices of the two numbers
         * such that they add up to a specific target.
         * return null if nums==null or nums.length==0 or result not found.
         */
        public int[] twoSum(int[] nums, int target) {
                if(nums==null || nums.length==0){
                        return null;
                }
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < nums.length; i++) {
                int complement = target - nums[i];
                if (map.containsKey(complement)) {
                    return new int[] { map.get(complement), i };
                }
                map.put(nums[i], i);
            }
            return null;
        }
    }
    展开

    作者回复: 改的很赞!

    另外,有一个小技巧和你分享一下。如果返回值是空值(null),如果调用代码没有检查空值就调用,会抛除NullPointerException异常。如果返回空数组(int[0]), 就不会出现这个问题了。 这个小技巧可以减少调用代码的错误,这样设计的接口比较皮实耐用。如果返回值是数组或者集合,我们通常使用这一个技巧。

    
     2
  • Demon.Lee
    2019-03-04
    老师,请教一个问题,在写定时任务的业务时,一开始从表中提取一些记录,然后针对每条记录进行业务处理(业务处理有事务),如果业务处理成功,则更新这条记录状态为A,如果业务处理失败,则更新这条记录状态为B,此时我就感觉违背了“不要用异常处理业务逻辑”这条规则,老师有什么好建议。另外,我想到的是用两个线程处理 ,主线程更新状态,子线程处理业务逻辑,但是需要线程间同步。
    public void execute(){
    List<T> rows = list();
    for(T t:rows){
        try{
          deal(t);
          updateStatus("A");
        }catch(Exception ex){
           updateStatus("B");
        }
    }
    }
    展开

    作者回复: deal()能不能不抛出异常?或者不正常的时候抛出异常,正常的业务不抛出异常?

    使用线程处理更复杂,还不如捕获异常呢。

    
     1
  • 草原上的奔跑
    2019-01-25
    课后习题,1.使用异常处理正常的业务逻辑。2.异常没有在接口规范中标记清楚。3.异常类名感觉用在这里不合适

    作者回复: 找的都对。你想到怎么修改了吗?

    
     1
  • Sisyphus235
    2019-05-22
    异常和错误是必须要分离的部分,错误必须抛出,异常要分清类型处理。
    对于开发异常,应该及时抛出,在开发中解决;
    对于生产中异常,要做好 log,及时报警,比如用 Sentry 处理 500 的服务器异常,用 log 记录核心功能的状态
    
    
  • 北风一叶
    2019-03-08
    异常的使用要符合具体的场景,这一条非常虚,不具备可执行性

    作者回复: 哈哈,看来你喜欢干脆的结论。

    
    
  • 拉格朗日的忧桑
    2019-02-22
    从函数的单一职责规范来看,该方法for循环里面的逻辑可以提取出来,单独称为一个方法
    
    
  • 李星
    2019-02-12
    如果是异常没有被try-catch住的线程呢?

    作者回复: 我们先来看看线程的主方法声明“public void run()”。这个声明没有抛出检查型异常,只能抛出运行时异常。所以,检查型异常一定要在线程的实现中得到处理;否则的话,编译器应该报错的。这个方法可以抛出运行时异常。一个线程,像一个普通的方法一样(run()),抛出运行时异常后,线程就终止了。问题在于,线程通常共享资源,如果线程之间有联系,很多事情就会发生,依赖于线程的具体实现逻辑。比如说,如果一个线程要等待另一个线程的I/O,也许会阻塞。

    
    
  • 李星
    2019-02-12
    想问一下作者,在多线程情况下时,当某一个线程发生运行时异常,并且不处理时,是否真的会阻塞当前线程呢?使得这个线程被废掉。?

    作者回复: 当前线程是发生异常没处理的线程吗? 还是不同的两个线程? 没太明白问题。

    
    
  • pyhhou
    2019-02-09
    思考题:
    1. 对输入数组需进行预判
    2. 方法内如果有异常抛出,需进行标记描述
    3. 异常名称名不副实

    import java.util.HashMap;
    import java.util.Map;

    class Solution {
        /**
         * Given an array of integers, return indices of the two numbers
         * such that they add up to a specific target.
         */
        public int[] twoSum(int[] nums, int target) {
            if (nums == null || nums.length ==0) {
                return new int[0];
            }

            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < nums.length; i++) {
                int complement = target - nums[i];
                if (map.containsKey(complement)) {
                    return new int[] { map.get(complement), i };
                }
                map.put(nums[i], i);
            }
            
            return new int[0];
        }
    }

    最后还想问下,如果说是 return 的不是 null 而是空数组,是不是就不需要在文档描述中标记写明?

    年过了一半了,看看自己拉下的章节还有不少,得抓紧了,祝老师新的一年心想事成,身体健康,工作生活一切顺利~ 今年励志一定要好好和你学写代码,稳扎稳打,快速成长
    展开

    作者回复: 新春快乐!

    JDK的习惯是,不论是null还是空的集合、数组,都在文档描述中标记清楚。这样,调用者能确切地知道该怎么检查。

    
    
  • 天佑
    2019-01-26
    大师,断言呢,使用场景是什么。

    作者回复: 简单的说,就是尽量不要使用断言。断言的设计是为了提高代码质量,可是断言一般有三个状态:断言是否启用;如果启用,断言是否成立。这让编码的逻辑很混乱,阅读的时候我们不一定能够把三个逻辑考虑周全,增加了编码错误的几率,降低了代码质量。

    
    
  • 我来也
    2019-01-25
    看不懂java 看这个异常处理有点吃力 🤦‍♂️

    作者回复: 有问题就留言,我们一起把疑惑的地方解决掉。

    
    
  • 王智
    2019-01-25
    这个小节看着懵懵的,看完之后完全不记得看了个啥,(╥╯^╰╥).还得看第二遍呀.

    后面的题目那个算是正常的业务,不应该用异常处理? 而且就算用异常处理了,方法的注释中也没有提及这个异常,那文档中就不会有这个异常的说明.

    我看了半天就看了这个,能力还是有点弱,得加油呀!!!

    作者回复: 练手题的问题找的都不错啊!

    
    
我们在线,来聊聊吧