zoukankan      html  css  js  c++  java
  • 改善java程序

    1、用偶判断,不用奇判断。因为负数会出错。

    // 不使用
    String str = i + "->" + (i%2 == 1? "奇数": "偶数");
    // 而使用
    String str = i + "->" + (i%2 == 0? "偶数": "奇数");

    2、使用整数类型处理货币

    (1)使用BigDecimal,与数据库Decimal类型字段映射时。

    (2)货币扩大100倍,使用整形。

    3、不要让类型默默转换。使用主动声明式转换。

    java是先运算,后自动转换类型的。

    long dis = 1L * 60 * 8
    

    4、数字越界使验证条件失效。

        边界测试:0,正最大,负最小。

    5、四舍五入问题。Math.round和银行家算法。

    Math.round(10.5) 结果 10;

    Math.round(-10.5) 结果 -10;

    BigDecimal i = d.multipy(r).setScale(2, RoudingMode.HALF_EVEN); // 银行家算法
    

    6、包装类型参与运算要做null值检验。否则会报错。

    for (Integer i : list) {
        count += (i != null) ? i : 0;
    }
    

    7、优先使用整形池。

    Integer i = Integer.valueOf(27);
    

        节省空间,提高性能。判断相等要用equals方法。

    8、优先使用基本类型。

    9、不要覆写静态方法。

    public class Client {
        public static void main(String[] args) {
            Base base = new Sub();
            base.doStatic(); // 覆写后,会调用父类静态方法
            base.doSomething(); // 覆写后,会调用子类非静态方法
    }    
    

      在子类中构建与父类相同的方法名、输入输出参数、访问权限(可扩大),且父类、子类都是静态方法的行为叫做隐藏。目的是隐藏父类静态方法,实现子类静态方法。

      @Override注解可以用于覆写,不能用于隐藏。

    10、构造函数尽量简化。不抛异常、不做复杂运算。

        做简单的构造函数,并将复杂问题移到start方法中,等待调用。

    11、不要在构造函数中声明初始化其他类。

    12、使用构造函数精炼代码

    public class Client {
        {
            System.out.println("执行构造代码块");
        }
        public Client() {
            System.out.println("执行无参构造");
        }
        public Client(String str) {
            System.out.println("执行有参构造");
        }
    }
    
    // 以上代码等价于:
    
    public class Client {
        public Client() {
            System.out.println("执行构造代码块");
            System.out.println("执行无参构造");
        }
        public Client(String str) {
            System.out.println("执行构造代码块");
            System.out.println("执行有参构造");
        }
    }
    

      编译器会将代码块插入到每个构造函数中,在super()之后;并且构造函数中调用this()时不会再次插入。

    13、内部类模拟实现多重继承。

    class Son extends FatherImpl implements Mother {
        @Override
        public int strong() {
            return super.strong() + 1;
        }
        @Override
        public kind() {
            return new MotherSpecial().kind();
        }
        private class MotherSpecial extends MotherImpl {
            public int kind() {
                return super.kind() - 1;
            }
        }
    }
    
    class Daughter extends MotherImpl implements Father {
        @Override
        public int strong() {
            return new FatherImpl() {
                @Override
                public int strong() {
                    return super.strong() - 2;
                }
            }.strong();
        }
    }
    

    14、让工具类不可实例化

    public final Class Math {
        private Math() {}
    }
    //以上不允许实例化,但利用反射修改构造函数的权限还是可能的。更彻底的方法是:
    public class UtilsClass {
        private UtilsClass() {
            throw new Error("不要实例化我");
        }
    }
    

    15、避免对象的浅拷贝

      拷贝在内存中进行,性能方面比直接new对象快很多,特别是在大对象生成上,提升性能非常显著。

    16、推荐使用序列化实现对象的拷贝

    17、覆写equals时考虑自反性、对称性(考虑null)、传递性。

    18、在equals中使用getClass进行类型判断,而不使用instanceof。

    19、覆写equals方法必须覆写hashCode方法。

    20、推荐覆写toString方法,因为默认方法不友好,打印不出有用信息。

    21、特殊类:package-info类。

    22、不要主动调用垃圾回收。这会停止所有响应,让出资源检查每个对象。

    23、推荐String直接赋值,而不是new String("")赋值。(原因:字符串池)

    24、String, replace和replaceAll的区别:replaceAll传递的第一个参数是正则表达式。

    25、字符串拼接:append最快(数组拷贝),concat次之(数组拷贝后,创建String对象),加号最慢(每次新建StringBuilder,append后,toString转为字符串)。

    26、推荐在复杂字符串操作中使用正则表达式。

    27、Arrays.asList陷阱。

      泛型类型只支持包装类型,不支持基本类型。

    // 避免使用:
    int data[] = {1,2,3}
    List list = Arrays.asList(data);
    //  list.size() : 1
    //应该使用:
    Integer data[] = {1,2,3};
    List list = Arrays.asList(data);
    // list.size : 3

      asList产生的list不可修改。

    28、不同列表的不同遍历方法。

      ArrayList实现了RandomAccess接口,使用下标访问更高效。LinkedList使用迭代访问效率更高。

    public static int average(List<Integer> list) {
        int sum = 0;
        if (list instanceof RandomAccess) {
            for (int i = 0, size = list.size(); i < size; i++) {
                sum += list.get(i);
            }
        } else {
            for (int i : list) {
                sum += i;
            }
        }
        return sum / list.size();
    }
    

    29、频繁插入删除使用LinkedList。

    30、列表相等只关心元素数据。

      ArrayList和Vector只有元素相等,则equals为true。其他集合类型相似。

    31、subList是原List的视图,subList的修改会反映到原List上。生成子列表后不要再操作原列表,子列表会报错。

    32、compareTo与equals要同步。

    33、Collections.shuffle(lists)打乱顺序。

    34、非稳定性排序用List。

        SortedSet接口只定义了集合加入元素时的排序,不保证修改元素后的排序结果,因此TreeSet适应于不变量的集合排序。建议使用List和Collection.sort()解决。

    35、switch枚举值可能会出现空指针异常。

        原因是switch通过枚举值的排序值判断。如Season.Spring.ordinal()。

    36、枚举类型switch的default代码中加AssertionError报错,方便排查新增枚举值而逻辑没有同步改动的错误。

    37、枚举使用valueOf要校验,加try-catch。

    38、枚举实现工厂方法模式更简洁、高效、不易出错。

    enum CarFactory {
        FordCar {
            public Car create() {
                return new FordCar();
            }
        },
        BuickCar {
            public Car create() {
                return new BuickCar();
            }
        };
        public abstract Car create();
    }
    
    public static void main(String[] args) {
        Car car = CarFactory.BuickCar.create();
    }
    

    39、枚举类型使用EnumSet和EnumMap提高效率。

    40、不要在finally块中处理返回值。

        无论是在finally块中加入return语句,还是在修改return的值或引用值、再返回,都不可以。会覆盖try块中的return值,屏蔽异常,造成假象,增加代码复杂性。

    41、不要在构造函数中抛出异常。

    42、使用Throwable获得栈信息。

    43、多线程继承Thread不要覆写start方法。

    44、启动线程前的stop方法不可靠。

        start之前调用stop方法会将线程置为不可启用状态,但start方法本身的缺陷导致会先启动后停止,因此应该自己判断线程是否启用。

    45、不使用stop方法停止线程。

        stop方法是一个过时的方法。无法保证完整性,会破坏原子逻辑。

        此外,interrupt方法不能终止正在执行的线程,只改变终端标识。

        应该自己编码实现,比如修改终止判断条件。或者使用线程池ThreadPoolExecutor的shutdown方法。

    46、线程优先级只使用三个。

        Java线程支持10个优先级(另外有一个不可设的只供jvm使用的优先级)。

        但不同机器对优先级的支持不同,所以只推荐使用MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY三个优先级,但也不一定完全保证顺序。

    47、volatile不能保证数据同步,只能保证线程获取到最新值。

    48、异步运算考虑使用Callable接口。

        Runnable接口和继承Thread类的run方法都没有返回值,不能跑出异常。Executor可以解决该问题。

    49、克隆对象不比直接生成对象效率高。

        因为java对new对象进行了优化,所以不要轻易使用clone。

  • 相关阅读:
    Python解释器安装
    有钱就放余额宝的人,这个习惯恐怕要改一改!
    这么详细的存储基础知识,你不看看? 会后悔的!
    超全!华为交换机端口vlan详解~
    华为:鸿蒙绝不是安卓换皮!!!
    VS Code 真的会一统江湖吗?
    用户与安全 -(1)Linux用户及组管理
    运维必看!这个技能薪水28.8万,工资竟然还只是零花钱....
    原来 Linux 日志文件系统是这样工作的~
    干货长文:Linux 文件系统与持久性内存介绍
  • 原文地址:https://www.cnblogs.com/ylty/p/6145951.html
Copyright © 2011-2022 走看看