美文网首页
编写高质量代码 - 改善Java程序的151个建议

编写高质量代码 - 改善Java程序的151个建议

作者: 读书的小二郎 | 来源:发表于2018-02-22 16:42 被阅读0次

    第一章、Java 开发中通用的方法和准则
    建议1:不要在常量和变量中出现易混淆的字母;// long i = 1l;
    建议2:莫让常量蜕变成变量;
    建议3:三元操作符的类型务必一致; //三元操作符转换规则;
    建议4:避免带有可变参数的方法重载;
    建议5:别让null值和空值威胁到变长方法;
    建议6:覆写可变参数方法规则
    // 1不能缩小访问权限;2参数列表必须相同;3返回类型相同或其子类;4异常不能超过父类的范围或不抛异常
    建议7:警惕自增陷阱 //i = i++;
    建议8:不要让旧语法困扰你;//goto 语法
    建议9:少用静态导入;
    //静态导入规则:1不使用通配符,除非导入静态常量类;
    建议10:不要在本类中覆盖静态导入的变量和方法;
    建议11:显示增加serialVersionUID //序列化 反序列化问题
    建议12:避免在序列化类中使用构造函数为不变量赋值;//final修饰的变量;
    //静态变量不会序列化;
    //反序列化时构造函数不会执行;
    建议13:避免未final变量复杂赋值;
    //序列化文件内容:
    1、类描述信息:路径,继承关系,访问权限,变量描述,变量访问权限,变量关联类信息等;
    2、非transient 和非static的实例变量;
    //反序列化 final变量不被赋值的情况:
    1通过构造方法赋值;2通过方法返还赋值;3final修饰的属性不是基本数据类型
    建议14:序列化的私有方法解决部分属性持久化问题 //writeObject readOject
    //transient 不能分布式部署;
    建议15:break万万不能忘
    建议16:易变业务使用脚本语言编写?
    建议17:慎用动态编译 //Java6支持
    建议18:避免instanceof非预期结果 //instanceof只能用于对象类型
    建议19:断言不是鸡肋;//默认不启用;
    不使用断言情况:对外公开方法中;执行逻辑代码的情况下;
    使用assert的情况:私有方法中入参校验;流程控制不可达区域;建立程序探针;
    建议20:不只要替换一个类 //整体war包发布
    对于final修饰的基本类型和String类型,编译器认为是稳定态,直接编译到字节码中,避免运行期引用;

    本章重点:3、4、5、7 、20序列化:11、12、13、14;

    第二章、基本类型
    建议21:用偶判断,不用奇判断 // i %2 == 1 ? “奇数” : “偶数”
    建议22:用整数类型处理货币;
    建议23:不要让类型自动转换;//主动声明 // int long
    建议24:边界,边界 // int 数据类型边界
    建议25:不要让四舍五入亏了一方//Math.round — RoundingMode
    建议26:堤防包装类型的null ;//List.add(null); //
    包装类型参数运算时要校验非null
    建议27:谨慎包装类型的大小比较;// ==基本数据相等,对象类型比较地址,包装类型为对象
    建议28:优先使用整型池;//IntegerCache原理 //对象类型是否相等 使用equals 而非 ==
    建议29:优先选择基本类型;
    //自动装箱的原则:基本类型可以优先加宽,在转变成宽类型的包装类型,不能直接变成宽类型的包装类型;
    建议30:不要随便设置随机种子 //Random(); // System.nanoTime

    第三章、类、对象及方法;
    建议31:不要在接口中写实现代码;
    建议32:静态变量要先声明后实现; //静态代码块
    建议33:不要复写静态方法 //对象调用静态方法 ,通过表面类型找到方法的入口
    建议34:构造函数尽量简化
    建议35:避免在构造函数中初始化其他类
    建议36:使用构造代码块精炼程序 // 构造代码块 先与 构造函数 代码
    //普通代码块 — 方法;静态代码块static{};同步代码块synchronied{};构造函数{};
    //应用场景:初始化实例变量— 每个构造函数都要初始化;初始化实例环境;
    建议37:构造代码块会想你所想 //构造代码块— 构造函数的共同量
    如果构造函数调用构造函数,构造代码只会执行一次;
    建议38:使用静态内部类提高封装性
    //静态内部类和内部类的区别:
    //1静态内部类不持有外部内的引用;2静态内部类不依赖外部类;3普通内部类不能声明static的方法和变量;
    建议39:使用匿名类的构造函数
    // new ArrayList(){}; //new ArrayList(){{}};
    建议40:匿名类的构造函数很特殊 //new A(1,2){{ //….}};
    //调父类同参构造函数,然后调用自己的构造代码块;
    建议41:让多继承成为现实; //继承 实现
    //内部类可以继承一个与外部类无关的类,保证内部类的独立性;
    建议42:让工具类不可实例化 // 构造函数私有化,并抛异常
    建议43:避免对象的浅拷贝;//Clonealbe接口 clone()方法;
    //拷贝规则:基本数据类型 拷贝值;实例对象拷贝地址引用;字符串:修改时会从字符串池中重新生成新的字符串;
    建议44:推荐使用序列化实现对象的拷贝;//只需要Serializable;
    //注意:对象的内部属性都是可序列化的;方法和属性的特殊修饰符;final、static问题,transient
    建议45:覆写equals方法时不要识别不出自己;
    建议46:equals应该考虑null值情景;
    建议47:在equals中使用getClass进行类型判断; // instanceof 类可能被继承的情况??
    建议48:覆写equals方法必须覆写hashCode方法;
    建议49:推荐覆写toString方法
    建议50:使用package-info类为包服务;//??
    建议51:不要主动进行垃圾回收;//System.gc 要停止所有的响应才能检查内存中是否有可回收的对象;

    第四章 字符串
    建议52:推荐使用String直接量赋值;
    建议53:注意方法中的参数要求;//API 不同版本参数不一样;参数一样含义不一样;
    建议54:正确使用String、StringBuffer、StringBuilder;
    建议55:注意字符串的位置;// 字符串连接 +
    建议56:自由选择字符串的拼接方法 // + | concat | StringBuffer
    建议57:复杂字符串操作中使用正则表达式;
    建议58:建议使用UTF编码;
    建议59:字符串排序;如果不是关键算法使用Collator类即可;//汉子转拼音在排序;

    第5章 数组和集合
    建议60:性能考虑,数组首选;//集合会自动装箱拆箱
    建议61:若有必要使用变长数组;//Arrays.copyOf
    建议62:警惕数组的浅拷贝;//Arrays.copyOf
    建议63:在明确的场景下,为集合指定初始容量; //扩展因子
    建议64:最值算法;//集合最简单;数组效率最高;
    建议65:避开基本类型数组转换列表陷阱;//Arrays.asList(..);基本数据类型不能泛型;
    建议66:asList方法产生的List对象不可更改//不能更改长度;
    建议67:不同的列表选择不同的遍历方法;//实现RandomAccess 用下标遍历;有序存取用foreach;//ArrayList
    建议68:频繁插入和删除时使用LinkedList;//大量修改元素,ArrayList效率高;
    建议69:列表相等只需关心元素数据 //AbstractList equals 比较各个元素是否相等;
    建议70:子列表只是原列表的一个视图;//subLi产生的列表只是一个视图;修改动作直接作用于原列表;
    建议71:推荐使用sublist处理局部列表;
    建议72:生成子列表后不要在操作原列表;
    建议73:使用Comparator进行排序;//Comparable接口可作为实现类的默认排序法;Comparator扩展性更强;
    建议74:不推荐使用binarySearch对类别进行检索; //二分查找比indexOf遍历效率高;
    建议75:集合中的元素必须做到compareTo和equals同步;//实现了 compareTo方法就应该覆写equals方法确保两者同步;
    建议76:集合运算时使用更优雅的方式;//并集 addAll retainAll removeAll
    建议77:使用shuffle打乱列表;//Collections.shuffle();
    建议78:减少HashMap中元素的数量//HashMap 比ArrayList进行封装
    建议79:集合中的哈希码不要重复;
    建议80:多线程使用Vector或HashTable;
    建议81:非稳定排序推荐使用List //TreeSet适用于不变量排序;
    建议82:集合大家族;
    List:ArrayList(动态数组),LinkedList(双向链表),Vector(线程安全的动态数组),Stack(对象栈)
    Set:EnumSet(枚举类型)HashSet,TreeSet(自动排序,实现了SortedSet)
    Map:排序Map:TreeMap(根据Key自动排序)非排序Map:HashMap,HashTable,Properties,EnumMap(Key为枚举类型)
    WeakHashMap— 弱键实现Map
    Queue:阻塞队列:ArrayBlockingQueue(数组)PriorityBlockingQueue(优先级)LinkedBlockingQueue(链表)
    非阻塞无边界队列:PriorityQueue;
    工具类:Arrays,Array,Collections;

    第6章 枚举和注解
    建议83:推荐使用枚举定义常量
    //枚举常量更简单;枚举常量属于稳定态;可以自定义方法
    建议84:使用构造函数协助描述枚举
    建议85:小心switch带来的空值异常 //传入值为空
    建议86:在switch的default代码中增加AssertionError错误;//避免枚举类型增加引入问题
    建议87:使用valueOf前必须进行校验 // 如果找不到匹配的值会报异常;
    //try catch //扩展枚举类 重写contains方法
    建议88:用枚举实现共产方法模式更简洁
    //枚举非静态方法实现,switch; //抽象方法生成产品; 枚举实现抽象方法;
    //枚举共产方法的优点:避免错误调用;性能好,使用便捷;减低类间耦合;
    建议89:枚举的数量限制在64个以内;//数量小于64使用RegularEnumSet;对于64使用JumboEnumSet
    建议90:小心注解继承 //@Inherited 标示可以被自动继承;
    //利:注解只要标注到父类所有的子类都会自动具有父类相同的注解;弊:阅读子类代码不能理解逻辑为何会改变;
    建议91:枚举和注解结合使用威力更大;//权限管理
    建议92:注意@Override不同版本的区别;//1.5 父类必须是一个类不能是接口;1.6做了修正;

    第7章 泛型和反射
    建议93:Java的泛型是类型擦除的 //编译时有效;原因:延续到运行期JVM需要大量重构;版本兼容;
    //泛型的class对象时相同的;泛型数组初始化时不能声明泛型类型;instanceof不允许存在泛型参数;
    建议94:不能初始化泛型参数和数组 //初始化前必须有明确的类型;
    建议95:强制声明泛型的实际类型 //无法从代码中推断出泛型类型的情况下,即可强制声明泛型类型;
    建议96:不同场景使用不同的泛型通配符 // ?; ? supper E ; ? extends E
    建议97:警惕泛型是不能协变和逆变的 // 可以使用通配符;
    建议98:建议采用的顺序是List<T>,List<?>,List<Object>
    建议99:严格限定泛型类型采用多重界限 //只有上边界才有此限定
    使用&符号设定多重边界;<T exteds Staff & Passenger >
    建议100:数组的真实类型必须是泛型类型的子类型;
    建议101:注意Class类的特殊性 //无构造函数;可以表述基本类型;其对象都是单例模式;
    建议102:适时选择getDeclaredXxx 和getXxx
    getXxx 获取所有public访问级别的;getDeclaredXxx 获取自身所有的;
    建议103:反射访问属性或方法时将Accessible设置为true //Accessible 是否进行安全检查
    建议104:使用forName动态 //只是加载一个类到内存中,只会初始化static代码
    建议105:动态加载不适合数组 //使用Array反射类来动态加载
    建议106:动态代理可以使代理模式更加灵活 //InvocationHandler接口 Proxy
    建议107:使用反射增加装饰模式的普适性
    建议108:反射让模板方法模式更强大
    建议109:不需要太多关注反射效率 // 不要因为效率低而不用

    第8章 异常
    建议110:提倡异常封装 //一次抛出多个异常
    建议111:采用异常链传递异常
    建议112:受检异常尽可能转化为非受检异常
    建议113:不要在finally中处理返回值
    建议114:不要在构造函数中抛出异常 //错误(Error)抛出;非受检异常(RuntimeException)不要抛出;受检异常(Exception)尽量不要抛出
    建议115:使用Throwable获取栈信息
    建议116:异常只为异常服务
    建议117:多使用异常,把性能问题放一边

    第9章 多线程和并发
    建议118:不推荐覆写start方法
    建议119:启动线程前stop方法不可靠的
    建议120:不使用stop方法停止线程 //stop过时;stop导致代码逻辑不完整;stop方法会破坏原子逻辑;
    //解决办法:自行编码实现 run方法;使用线程池,通过shutdown关闭;
    建议121:线程优先级只使用三个等级 ;//并不是严格按照优先级别来执行;级别差距越大运行机会差别越明显;
    //推荐使用MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY
    建议122:使用线程异常处理器提升系统可靠性 //TcpServerExceptionHandler
    建议123:volatile不能保证数据同步 //只能保证线程获得最新值
    建议124:异步运算考虑使用Callable接口;//优点:尽可能多的占用系统资源;监控线程执行情况;
    建议125:优先选择线程池
    建议126:适时选择不同的线程池来实现 //ThreadPoolExecutor ScheduledThreadPoolExecutor Executores
    建议127:Lock与synchronized是不一样的
    //lock支持更细粒度的锁控制;Lock是无阻塞锁,synchronized是阻塞锁;Lock可实现公平锁;Lock是代码级别的,synchronized是JVM级的
    建议128:预防线程死锁 //避免或减少资源共享;使用自旋锁;
    建议129:适当设置阻塞队列长度 //阻塞队列容量是固定的,非阻塞队列是变长的;
    建议130:使用CountDownLatch协调子线程
    建议131:CyclicBarrier让多线程起步走

    第10章 性能和效率
    建议132:提示Java性能的基本方法
    1、不要在循环条件中计算
    2、尽可能把变量、方法生命为final static类型
    3、缩小变量的作用范围;//能定义在方法内就在方法内定义;循环体,try catch代码块都是如此,加快GC
    4、频繁字符串操作使用StringBuilder或者StringBuffer
    5、使用非线性检索
    6、复写Exception的fillInStatckTrace方法
    7、不建立冗余对象
    建议133:弱非必要,不要克隆对象
    建议134:“望闻问切”方式诊断性能
    建议135:定义性能衡量标准
    建议136:解决首要系统性能问题
    建议137:跳转JVM参数提升性能
    建议138:性能是个大“咕咚”

    第11章 开源世界
    建议139:大胆采用开源工具;
    建议140:推荐使用Guava扩展工具包
    建议141:Apache扩展包 //Lang
    建议142:推荐使用Joda日期时间扩展包
    建议143:选择多种Collections扩展 // fastutil Trove lambdaj

    第12章 思想为源
    建议144:提倡良好的代码风格 //整洁 统一 流行 便捷
    建议145:不要完全依靠单元测试来发现问题
    建议146:让注释正确、清晰、简洁
    建议147:让接口职责保持单一 //单一责任原则
    建议148:增强类的可替换性 //里氏替换原则
    完全实现父类的方法;前置条件可以放大(入参);后置条件可以被缩小(返回值)
    建议149:依赖抽象而不是实现
    建议150:抛弃7条不良的编码习惯
    自由格式的代码;不使用抽象的代码;彰显个性的代码;
    死代码;冗余代码;拒绝变化的代码;自以为是的代码;
    建议151:以技术人员自律而不是工人
    属性工具;使用IDE;坚持编码;编码前思考;坚持重构;
    多写文档;保持程序版本的简单性;做好备份;做单元测试;
    不要重复发明轮子;不要拷贝;让代码充满灵性;测试自动化;
    做压力测试;“剽窃”不可耻;坚持向敏捷学习;重里更重面;
    分享;刨根问底;横向扩展;

    相关文章

      网友评论

          本文标题:编写高质量代码 - 改善Java程序的151个建议

          本文链接:https://www.haomeiwen.com/subject/bpjztftx.html