Algorithm

Convert Sorted List to Binary Search Tree

采用递归的方式将有序链表转化为二叉树

Review

本周阅读:Java tip: When to use composition vs inheritance

文章的内容是一个老生常谈的话题:JAVA什么时候使用封装,什么时候使用继承。

作者通过一个简单的例子说明了继承的风险性:JAVA语言的动态绑定可能会导致父类的方法错误地调用子类方法,破坏了父类的封装,导致代码未按照预期的方式执行。

在实际的使用过程中,个人认为继承还有另一个方面的风险:即对于通用方法的不确定性,例如父类覆盖了默认的equals()方法,继承的子类如果不重写该方法的话可能会导致严重的后果。

继承相比封装最大的好处在于子类可以完美地替代父类,继承所得的子类可以放在任何需要父类实例运行的地方,不需要额外添加包装类的逻辑。因此,继承更适用于对于原有逻辑的加强。

关于继承与封装各自的优缺点与适用环境,大家可以多多思考一下AOP的两种实现方式:Proxy属于封装,而CGLib属于继承。

Tip

今天在开发的过程中遇到一个很2的问题:使用String.format()对一个字符串进行处理时,程序报错如下:

Exception in thread "main" java.util.UnknownFormatConversionException: Conversion = '''
	at java.util.Formatter.checkText(Formatter.java:2579)
	at java.util.Formatter.parse(Formatter.java:2555)
	at java.util.Formatter.format(Formatter.java:2501)
	at java.util.Formatter.format(Formatter.java:2455)
	at java.lang.String.format(String.java:2940)
	at com.sdww8591.tools.tmp.FormatTest.main(FormatTest.java:13)

其中字符串为:”SET PASSWORD FOR ‘admin’@’%’ = PASSWORD(‘%s’);”,一个设置Mysql用户密码的标准String模板。

设置断点进入Formatter.java:2579,发现此时cursor位于字符数组的26位置处,指向@字符后面的那个%字符。异常抛出的根本原因是程序遇到%字符后,发现后面并未接数字、-+、tsd等规范化字符,所以程序直接抛出了UnknownFormatConversionException。

代码如下:

private static void checkText(String s, int start, int end) {
    for (int i = start; i < end; i++) {
        // Any '%' found in the region starts an invalid format specifier.
        // 对于任何单独出现的%或者位于字符串末尾的%都会抛出UnknownFormatConversionException
        if (s.charAt(i) == '%') {
            char c = (i == end - 1) ? '%' : s.charAt(i + 1);
            throw new UnknownFormatConversionException(String.valueOf(c));
        }
    }
}

外层代码:

    Matcher m = fsPattern.matcher(s);
    for (int i = 0, len = s.length(); i < len; ) {
        if (m.find(i)) {
            // Anything between the start of the string and the beginning
            // of the format specifier is either fixed text or contains
            // an invalid format string.
            if (m.start() != i) {
                // Make sure we didn't miss any invalid format specifiers
                checkText(s, i, m.start());
                // Assume previous characters were fixed text
                al.add(new FixedString(s.substring(i, m.start())));
            }

            al.add(new FormatSpecifier(m));
            i = m.end();
        } else {
        、、、
        }
    }

这里仅截取了源代码的一部分,其中fsPattern的正则表达式为:

”%(\d+\$)?([-#+ 0,(\<]*)?(\d+)?(\.\d+)?([tT])?([a-zA-Z%])”

包含了所有的格式化表达式,因此上面代码的逻辑为:

  1. 找到所有匹配格式化表达式的关键字符串组合,将字符串切分为数段
  2. 对于每一个不包含格式化表达式的字符段,采用checkText方法验证其是否含有单独的%,如果含有,则抛出UnknownFormatConversionException异常。

通过阅读源码,可以发现当需要format的字符串中含有%字符时,可通过字符%%代替

Share

Quartz介绍