emmmm,看了两遍手册,又看了一些前辈的总结,就这样去考试了。。。
考了六次总算考过了。考试90分钟,需要上传身份证正面照。总共50道题,单选题少之又少。
这个考试陷入了死循环,有些选项和手册中提到的是有差别的,那到底是选还是不呢,而且这次选了下次不选,一直都不知道正确的到底是什么。
考证不是目的,重要的是掌握了这样一套规范很大程度上可以规避产品运行时的出错的风险。阿里巴巴的大牛们帮我们总结出的经验能让我们从源头上避免错误,还是很受用的。
考了这么多次,总结一下我遇到的考点吧。
一、编程规约:
1.代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
2.代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
3.类名使用 UpperCamelCase 风格,但以下情形例外:DO / BO / DTO / VO / AO /
PO / UID 等。
4.方法名示例: getHttpMessage()
5.常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚。
6.抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类
命名以它要测试的类的名称开始,以 Test 结尾。
7.类型与中括号紧挨相连来表示数组。
8.POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误
9.包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用
单数形式。(这里的单数在手册中也用蓝色字体表示了,在考试中选项是复数)。
10.杜绝完全不规范的缩写。
11.接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁
性,并加上有效的 Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是
与接口方法相关,并且是整个应用的基础常量。(选项中出现的是接口类中的方法要使用public修饰。并且可以不用javadoc注释)
12.对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部
的实现类用 Impl 的后缀与接口区别。
13.枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
14.领域模型命名规约
1) 数据对象:xxxDO,xxx 即为数据表名。
2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
3) 展示对象:xxxVO,xxx 一般为网页名称。
4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。(选项中是统一命名成POJO)
15.不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。
16.在 long 或者 Long 赋值时,数值后使用大写的 L,不能是小写的 l。
17.不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。
18.常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包
内共享常量、类内共享常量。
1) 跨应用共享常量:放置在二方库中,通常是 client.jar 中的 constant 目录下。
2) 应用内共享常量:放置在一方库中,通常是子模块中的 constant 目录下。
3)子工程内部共享常量:即在当前子工程的 constant 目录下。
4) 包内共享常量:即在当前包下单独的 constant 目录下。
5) 类内共享常量:直接在类内部 private static final 定义。
手册里提到的例子有助于理解,考试的时候想不起来知识点能想起来例子也是有帮助的。
19.如果变量值仅在一个固定范围内变化用 enum 类型来定义。(选项中是一年四季在一定范围内变化,就不要使用枚举了)
20.左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格;而左大
括号前需要空格。
21.if/for/while/switch/do 等保留字与括号之间都必须加空格。(选项中出现while是特殊的,不需要加空格)
22.任何二目、三目运算符的左右两边都需要加一个空格。(选项中是任何运算符)
23.如果使用 tab 缩进,必须设置 1 个 tab 为 4 个空格。
24.
3)方法调用的点符号与下文一起换行。
4) 方法调用中的多个参数需要换行时,在逗号后进行。
5) 在括号前不要换行。
25.IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。
26.没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。(选项中是为了代码美观,需要对齐)
27.所有的覆写方法,必须加@Override 注解。
28.相同参数类型,相同业务含义,才可以使用 Java 的可变参数,避免使用 Object。
29.不能使用过时的类或方法。
30.Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用
equals。
31.所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。(Integer a = 33,Integer b = 33,Integer c = 278,Integer d = 278,选择a==b和c==d是true还是false)
32.关于基本数据类型与包装数据类型的使用标准如下:
1) 【强制】所有的 POJO 类属性必须使用包装数据类型。
2) 【强制】RPC 方法的返回值和参数必须使用包装数据类型。
3) 【推荐】所有的局部变量使用基本数据类型。
(选项中有一个是基本数据类型与其包装类是分场景使用的)
33.定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。
34.serialVersionUID 不一致会抛出序列化运行时异常。(单选)
35.构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。
36.当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,
便于阅读。
37.setter 方法中,参数名称与类成员变量名称一致,this.成员名 = 参数名。在
getter/setter 方法中,不要增加业务逻辑,增加排查问题的难度。
38.慎用 Object 的 clone 方法来拷贝对象。
39.subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList 而是 ArrayList
的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。
40.在 subList 场景中,高度注意对原集合元素的增加或删除,均会导致子列表的遍历、
增加、删除产生 ConcurrentModificationException 异常。(选项中是对原集合的操作不会对字列表产生影响)
41.使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全
一样的数组,大小就是 list.size()。
42.使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方
法。asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList
体现的是适配器模式,只是转换接口,后台的数据仍是数组。
43.remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。(单选)
44.使用 entrySet 遍历 Map 类集合 KV。(单选)
45.Map 类集合 K/V 能不能存储 null 值的情况,那个表格也是重点。(单选和多选都有)
46.TreeSet 是order/sort。(单选)
47.创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
48.线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
49.线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式。FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
50.SimpleDateFormat 是线程不安全的类。注意线程安全,使用 DateUtils。如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat。
51.高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
52.对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
53.多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运。行,使用 ScheduledExecutorService 则没有这个问题。(选项中是推荐使用TimeTask)
54.使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行至 await 方法,直到超时才返回结果。
55.在一个 switch 块内,都必须包含一个 default 语句并且放在最后。在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,避免采用单行的编码方式:if (condition) statements; (选项中是可以使用单行编码)
56.下列情形,需要进行参数校验:
1) 调用频次低的方法。
2) 执行时间开销很大的方法。此情形中,参数校验时间几乎可以忽略不计,但如果因为参
数错误导致中间执行回退,或者错误,那得不偿失。
3) 需要极高稳定性和可用性的方法。
4) 对外提供的开放接口,不管是 RPC/API/HTTP 接口。
5) 敏感权限入口。
下列情形,不需要进行参数校验:
1) 极有可能被循环调用的方法。但在方法说明里必须注明外部参数检查要求。
2) 底层调用频度比较高的方法。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底
层才会暴露问题。一般 DAO 层与 Service 层都在同一个应用中,部署在同一台服务器中,所
以 DAO 的参数校验,可以省略。
3) 被声明成 private 只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参
数已经做过检查或者肯定不会有问题,此时可以不校验参数。
(选项中同时出现)
57.类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用// xxx 方式。
58.所有的类都必须添加创建者和创建日期。(选项中是必须添加创建者信息)
59.方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。
60.所有的枚举类型字段必须要有注释,说明每个数据项的用途。
61.与其“半吊子”英文来注释,不如用中文注释把问题说清楚。
62.特殊注释标记,请注明标记人与标记时间。待办事宜(TODO):( 标记人,标记时间,[预计处理时间])。错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])在注释中用 FIXME 标记某代码是错误的,而且不能工作,需要及时纠正的情况。
63.在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
64.不要在视图模板中加入任何复杂的逻辑。
二、异常日志:
65.正例:if (obj != null) {...}
反例:try { obj.method(); } catch (NullPointerException e) {…}(这个例子要理解一下,选项中出现的是反例,在开发中尽量使用!=null来避免出现空指针的可能性)
66.异常不要用来做流程控制,条件控制。(选项中是推荐使用try-catch来做流程控制和条件控制)
67.catch 时请分清稳定代码和非稳定代码。
68.有 try 块放到了事务代码中,catch 异常后,如果需要回滚事务,一定要注意手动回滚事务。finally 块必须对资源对象、流对象进行关闭。不要在 finally 块中使用 return。finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句。
69.捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。
70.方法的返回值可以为 null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回 null 值。明确防止 NPE 是调用者的责任。
71.,注意 NPE 产生的场景:
1)返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。
反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。
2) 数据库的查询结果可能为 null。
3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。(选项中是只需要保证isNotEmpty不为空,就不会出现null)
4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
5) 对于 Session 中获取的数据,建议 NPE 检查,避免空指针。
6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
72.应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架
SLF4J 中的 API。
73.日志文件至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。
74.对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式。(选项中还会出现使用条件或占位符可以避免字符串拼接)
75.避免重复打印日志,浪费磁盘空间,务必在 log4j.xml 中设置 additivity=false。
76.异常信息应该包括两类信息:案发现场信息和异常堆栈信息。
77.谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用 warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时删除这些观察日志。
三、单元测试:
78.单元测试应该是全自动执行的,并且非交互式的。为了保证单元测试稳定可靠且便于维护,单元测试用例之间决不能互相调用,也不能依赖执行的先后次序。单元测试是可以重复执行的,不能受到外界环境的影响。
79.单元测试代码必须写在如下工程目录:src/test/java。(单选)
80.单元测试的基本目标:语句覆盖率达到 70%;核心模块的语句覆盖率和分支覆盖率都
要达到 100%(选项中是单元测试覆盖率必须100%)
81.B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
C:Correct,正确的输入,并得到预期的结果。
D:Design,与设计文档相结合,来编写单元测试。
E:Error,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得到预期的结果。(选项中是Equals)
82.和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。或者对单元测试产生的数据有明确的前后缀标识。(选项中有一个是数据库的测试要专门建一个测试库)
83.为了更方便地进行单元测试,业务代码应避免以下情况:
构造方法中做的事情过多。
存在过多的全局变量和静态方法。
存在过多的外部依赖。
存在过多的条件语句。
84.不要对单元测试存在如下误解:
那是测试同学干的事情。本文是开发手册,凡是本文内容都是与开发同学强相关的。
单元测试代码是多余的。系统的整体功能与各单元部件的测试正常与否是强相关的。
单元测试代码不需要维护。一年半载后,那么单元测试几乎处于废弃状态。
单元测试与线上故障没有辩证关系。好的单元测试能够最大限度地规避线上故障。
四、安全规约:
85.中国大陆个人手机号码显示为:158****9119,隐藏中间 4 位,防止隐私泄露。(选项中还有一个选项是银行卡号只显示第一位和最后一位,如果满足什么什么验证可以完全显示)
86.用户输入的 SQL 参数严格使用参数绑定或者 METADATA 字段值限定,防止 SQL 注入,禁止字符串拼接 SQL 访问数据库。
87.忽略参数校验可能导致:
page size 过大导致内存溢出
恶意 order by 导致数据库慢查询
任意重定向
SQL 注入
反序列化注入
正则输入源串拒绝服务 ReDoS。
88.表单、AJAX 提交必须执行 CSRF 安全验证。在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放的机制,如数量限制、疲劳度控制、验证码校验,避免被滥刷而导致资损。发贴、评论、发送即时消息等用户生成内容的场景必须实现防刷、文本内容违禁词过滤等风控策略。
五、Mysql数据库
89.表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint(1 表示是,0 表示否)。(选项中有一个是数据类型varchar中,1表示是,0表示否)
90.表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。表名不使用复数名词。禁用保留字,如 desc、range、match、delayed 等。
91.主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。
92.如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
93.表必备三字段:id, gmt_create, gmt_modified。(选项中会把modified改为modify)
94.表的命名最好是加上“业务名称_表的作用”。(选项中是表的方式)
95.冗余字段应遵循:
1)不是频繁修改的字段。
2)不是 varchar 超长字段,更不能是 text 字段。(选项中提到的是varchar(2500))
96.合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
97.业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。(选项中有一个是在join之前,使用一下where)
98.在 varchar 字段上建立索引时,必须指定索引长度。页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
99.如果有 order by 的场景,请注意利用索引的有序性。
100.SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts最好。
101.建组合索引的时候,区分度最高的在最左边。防止因字段类型不同造成的隐式转换,导致索引失效。
102.SQL语句部分的手册前7条都是高频。
103.更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间。不允许直接拿 HashMap 与 Hashtable 作为查询结果集的输出。
104.iBATIS 自带的 queryForList(String statementName,int start,int size)不推荐使用。(超高频)
105.不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义。
106.工程结构中的二方库依赖也是高频。
107.服务器部分出现了TCP协议中的握手等知识。
经过了六次考试,总结的时候才发现,几乎把手册里的规约考了一个遍。。。这样也加深了印象。