第一章、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;坚持编码;编码前思考;坚持重构;
多写文档;保持程序版本的简单性;做好备份;做单元测试;
不要重复发明轮子;不要拷贝;让代码充满灵性;测试自动化;
做压力测试;“剽窃”不可耻;坚持向敏捷学习;重里更重面;
分享;刨根问底;横向扩展;
网友评论