创建对象类型的
1,静态工厂方法代替构造器
- 静态工厂方法有名称,不容易混乱他的作用
- 不必再每次调用他的时候创建实例,创建实例的代价是高的,可以重复利用缓存的对象
- 静态工厂甚至能返回子类对象,例如在接口上(Java8 )的静态方法上,返回一个直接可以用的类
- 根据参数值,决定不同的返回类型(貌似和上面有点像
- 返回的类型,可以在写静态工厂时候不存在(貌似用在rpc方面)
- 缺点
- 如果不包含公有或包含的构造器,就不能让子类实例化
- javadoc不能很好解释
- ps
- vauleOf,转换方法
- instance或者getInstance,通过方法参数获得实例,但不能说每次实例都是一样的,A a = A.getInstance(option)
- create或者createInstance,通过静态方法获得实例,每次都说新的实例
- getType,在不同类中返回不同的对象,type可以是其他意思,比如getA,getB
- newType,和上面一样,返回新的实例
2,遇到多个构造器参数的时候,使用构建器
- 构建器有同样的参数列表
- 构建器构造函数写必须的参数,后面再添加可选的参数
- build方法返回实例的引用
‘
3,用枚举强化单例模式
4,在一些静态工具类中,将构造方法私有化,不能abstract抽象化,别人还以为你是专门用来继承的
5,不要用单例和静态工具类来实现一个或多个资源的类(他们都只能假设有一种资源)(静态工具类不能用状态),因为资源的行为会影响类的行为,应该将资源交给工厂(spring),通过他们进行依赖注入来创建类
6,避免创建不必要的对象
- string
- 像解析token,正则表达式,这些,缓存创建好的对象
- 自动装箱问题,尽量使用基本类型
7,消除过期的对象引用
- 像栈这种需要自己维护一些数组的需要引用指空来防止内存泄漏
- 缓存也会内存泄漏,当缓存的生命周期由该键的外部引用决定时,可以用weakhashmap
8,-
9,使用try-with-resource 代替try- catch
所有对象通用的方法
10,equal的一些性质,(几个特性,没认真记住
- 重写equal前重写hashcode
- 不要重写时候换了入参对象,因为这样是重载不是重载
11,重写equal前重写hashcode
12,始终覆盖tostring,尽可能输出又用的信息
13,谨慎重写clone(未看)
14,实现comparable接口的时候,比较值避免使用《》,用装箱基本类型的类的compare方法,或者Comparator接口中的比较器
类和接口
15,类和成员的可访问性最小化(未怎么看
16,要在公有类而非公有域使用访问方法(set,get
17,可变性最小,为了成为不可变类的条件
- 不要设置方法
- 类被final修饰,(不可被扩展
- 域都是被final修饰
- 域都是私有的
- 不被其他引用指向
- 缺点
- 每次都要new一个,改进,一些计算的域适当可变
18,复合优于继承
- 继承的时候是否满足is a的关系
- 在使用继承来实现功能的时候,超类方法可能又自己方法的自用性,当你不够了解超类的实现的时候,重写的方法可能在别的地方被调用了,所有一般又组合的方式,写个装饰者模式
19,要么设计继承并提供文档说明,要么禁止继承
- 必须又文档说明可覆盖的方法和自用性
- 比如在一个remove方法里面,说明他调用了equal了方法,那么重写equal这个方法的时候就会得到注意
- 构造器不能调用重写的方法,毕竟超类在构造的时候,重写方法还没实现
- clone和serializable的实现方法也不能调用重写方法
- 必须要用,可以抽象出来一个私有方法调用
20,接口优于抽象类,如果是个很重要的接口,考虑提供骨架类,例如:AbstractList
21,为后代设计接口,虽然Java8又default,但也要慎重设计接口
22,常量不应该定义在接口
23,类层次优于标签结构,很无聊,就是不要写太多具体的东西和模板在同个类中,用继承来层次化他
24,解释了内部类,和外部类没有一一对应的关系的时候可以选择static
25,单个源文件为单个*类,想多个的时候,请使用静态类,防止编译的时候发生错误,少编译了类
泛型
26,不要使用原生态类型,collection这些,用泛型,这样可以尽早检查出错误
27,受检警告很重要,尽量不要删除它,如果要删除,请确定再最小范围,还有注释为什么要删除
28,用list代替数组
29,优先考虑使用泛型
30,优先考虑泛型方法
31,利用限定符提升api的灵活性
- extend 作为生产者
- super 作为消费者
- 当方法中没有用到具体的泛型,入参可以考虑使用?,但方法中需要插入或者删除,封装多一层的泛型
32,谨慎并用泛型和可变参数(没看懂
33,优先考虑类型安全的异构容器(没看懂
枚举和注解
34,优先使用常量对比于枚举
35,不要依赖枚举本来的ordinary值,自己set值
36,用EnumSet代替位域
37,用EnumMap代替序数索引
38,用接口模拟可扩展的枚举
39,注解优于命名模式(看了题目,没深入看
40,坚持使用@Override注解,防止自己写了重载而不是重写这种错误
41,用标记接口来定义类型
lambda和stream
42,lambda代替匿名类
43,方法引用优于lambda
44,写函数接口的时候,看看是否又官方库类,比如predicate,function,consumer,还有基于基本类型的接口
45,慎重使用stream
- 统一转换元素序列
- 过滤元素序列
- 利用单个操作(如添加,连接,计算最小值)合并元素顺序
- 分组
- 搜索满足某些条件
46,优先选择stream无副作用的函数,就是用collectors里面的
47,stream优先使用collectior作为返回类型(看不懂
48,谨慎,少用stream的并发流
方法
49,检查方法入参的有效性
50,必要时进行保护性拷贝,别把需要的引用给暴露出去,要的话给他拷贝一个,如果你觉得这样伤害性能,就建议在安全环境下进行
51,谨慎设计方法签名,名字参考jdk,参数用枚举代替Boolean
52,慎用重载,重载是再编译期的,没有重写的在运行期再决定动作,可以考虑改接口名来,自动装箱也有问题remove(e),remove(int),确定传进去相同参数的时候,行为是一样的
53,慎用可变参数
54,返回数组和集合的时候,返回一个空的比null好,避免客户端代码出错
55,使用optional,当一个方法无法给出返回值的时候,有两种选择,
- null,但会让客户端代码有npe
- 抛出异常,异常栈有代价的
- 返回optional,强迫客户端思考,有点像受检异常
56,为api写javadoc
Java通用编程(一些细枝末节
57,局部变量作用域最小化
58,foreach 代替for
- 除了用remove方法
- 除了不需要全部遍历
- 除了两个集合同时遍历
59,使用官方库类,不然就用第三方
60,要准确数据用bigDecimal,long(不超过18),int(不超过9)代替float,double
61,尽量使用基本类型
- 自动装箱带来的性能问题
- 自动拆箱带来的npe
- 集合和其他容器用装箱
62,如果其他类型更加适合,就不用字符串,(很虚
63,拼接字符串使用stringBuilder
64,通过接口引用对象(面向抽象编程?
65,接口优于反射(不懂
66,谨慎使用本地方法
67,谨慎地进行优化(不要浪费时间搞有的没的
68,改名规范
- 不可实例化的工具类加s结尾,collections,collectors
- 返回Boolean的用isxxxx
- 转换对象类型,tostring,toxxx
69,异常不可以作为控制语句来混用
70,可以回复的异常使用受检异常
71,避免使用受检异常(不太会
72,使用官方异常
73,抛出与抽象对应的异常,高层次的异常吃掉低层次的异常,然后抛出高层次的异常,这就叫异常的转换
74,每个抛出的异常都应该又文档支持
75,细节异常的信息(不太很理解
76,出现异常的时候,保留原子性(原来的状态
- 在改变对象状态前抛出异常
- 在拷贝对象上修改
77,永远不要忽略异常
并发
78,共享变量需要同步(废话?)(不用thread。stop,用Boolean让自己的线程停止自己的线程
79,把同步区域做到最小
80,使用executor,stream,task代替手写线程
81,使用aqs框架的工具代替手写notify,wait
82,为线程安全添加必要的文档
83,慎用延迟初始化,有必要用双重锁检测
84,不要依赖线程调度器(不太理解
序列化
85,用json和protobuf代替Java序列化
86,谨慎实现serilianize接口(不太理解
87,考虑使用自定义的序列化形式(不太理解