Java要点笔记

第一章: 创建和销毁对象

类可以通过静态工厂方法来提供客户端,而不是通过构造器

优点:

自定义工厂名称,提高可读性

可以工厂里搞单例

控制实例类是哪种子类

总之是更加灵活,可读性更高

缺点:

有可能会导致类无法子类化,因为一般搞工厂,就把构造器私有或受保护了

有心的使用者会困惑,总是想看看到底是咋实例化的,单例? 多例? 创建时是否有init一些前置过程?

getInstance 约定俗成返回单例

newInstance 约定俗成多例

getType 一般把工厂方法写在其它类(如专门的工厂类) 可根据Type入参来从工厂拿对应单例

newType 一般把工厂方法写在其它类(如专门的工厂类) 可根据Type入参来从工厂拿对应多例

多个构造参数,如果灵活多变,要考虑用构造器

工作中如果构造函数有多个 且 特定 的话,我一般倾向写两三个函数签名不一样构造器。但是如果在构造参数很多且多变,要写一个内部构建器,用builder模式,而不是大量重叠构造器。

优点:

builder 可以一次构建实例对象,而JavaBean的方式虽然比构造器可读性好点,但会使对象状态处于不一致的状态,线程安全维护成本太高了。因为总是要setter方法赋值

builder方式创建的实例是不可变的,无状态的。

builder方式在进行构造时可以加入校验参数的逻辑确保正确的通过builder构建实例

builder 可以在真正创建对象之前进行各种参数修改调整,甚至可以自动设置某些域

builder 因为是变化的,从抽离变化的角度来看,可以将builder设计成接口

publicinterfaceBuilder{publicTbuild(); }

缺点:

静态内部类builder明显代码量增加了

创建实例还得搞个builder 额外的性能开销

总结: 个人感觉构造参数稳定的情况下,即未来不会参数变化频繁 && 参数比较少,还是使用重叠构造器的方式,感觉这也在好多源码中约定俗成的。如果构造类时需要多个参数,特别是当大多数参数都是可选的时候,Builder 不失为一个很好的选择。可读性和安全性都能保障。

再讲单例实现

常见的有三种 枚举 静态属性或静态块 双重检查锁

不需要实例话的类

尽量把构造器私有化,比如一些工具类,避免不必要的对象意外创建

对象如果可重用,就少创建点

但是如果因为多创建了实例而提高了程序的清晰性,间接性和功能性,也是一个好事儿

消除某些过期的对象引用, 因为可能导致内存泄漏

一种情形是 数组, 还有 缓存, 可以用WeakHashMap解决,但是必须保证所有的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap才有意义, LinkedHashMap 可以自定义缓存策略,LRU常用实现。监听器和回调的内存泄漏风险。

关于java的 finalize方法

其实工作中极少用到它,一般都是显示的public关闭资源的方法,让客户端去显示关闭,服务端也可以配合try catch finally 写个确保释放资源的操作(万一客户端脑残不调close方法),子类覆盖finalize方法注意super调用父类的finalize方法。可以搞个private final 内部类 里面有个回收外部类实例资源的方法,外部类私有属性保持对内部类实例的一个引用。内部 外部类现在同生共死了,当外部类死掉的时候,内部类实例也要死,死的时候把外部类资源回收了。

类的每个实例都只与他自身相等

类是私有的或者是包级私有的,那么可以确定它的equals方法永远不会被调用,这时候需要覆盖equals方法,防止被意外调用

如果要判断“逻辑相等“,且父类equals做不到这个功能的时候需要覆写equals

枚举值类,因为是“每个值至多只存在一个对象“ 的类, 搜衣不需要覆写

equals含义的通用约定一定要遵守!!!没有哪个类是孤立的。

equels方法诀窍:

== 判断是否是同一个对象的引用

instanceof 进行类型检查

把参数转换为正确的类型

检查参数的每个域是否一一对应的equals

覆盖equals必须覆盖hashCode,相等的对象必须具有相同的hashCode值~

不要将equals声明中的Object对象替换为其它的类型,应该覆盖Object的 equals方法

要始终覆盖toString方法,打印的信息更加具有可读性

第四章: 类与接口

要区别设计良好的模块与设计不好的模块,最重要的因素在于,这个模块对于外部的其它模块而言,是否隐藏其内部数据和其它实现细节。

尽可能地使每个类或者成员不被外界访问

对于包内顶层地类和接口,要么包级私有要么public, 一旦public开发者有责任永远支持它

如果包级私有地顶层类只被包内的一个类用到,要考虑使它成为那个类的私有嵌套类,使可访问范围更小

实例域和静态域绝不能是公有的

对于final数组域可以这样控制权限

privatestaticfinalThing[] PRIVATE_VALUES = {...};publicstaticfinalList VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

用函数表示策略, 策略抽象成接口,如果实现接口的具体策略只使用一次,用匿名类,否则应该定义一个静态final函数, 返回类型为策略接口

publicstatic> Comparator> comparingByValue() {return(Comparator> & Serializable)                (c1, c2) -> c1.getValue().compareTo(c2.getValue());        }

静态成员类是外围类的一个成员, 常见用法是作为共有类的辅助类, 比如一个类里面有个静态枚举类;

非静态成员类的每个实例都隐含着与外部类一个外部实例相关联(影响外部类的垃圾回收)。当非静态成员类的实例被创建的是时候,它和外围实例之间的关联关系也随之建立起来&不能被修改

第七章: 关于方法

每当编写方法和构造器的时候,应该考虑他它的参数有哪些限制,应该把限制写到文档中,并在方法的开头出加上限制逻辑,私有方法assert断言

我们要保护性的去设计程序,如果API设计的不好,客户端很容易误解,并导致不可预期的行为,所以编写面对客户的不良行为时仍能保持健壮的类,这是非常值得投入时间去做的事情。要注意是否允许调用者修改其内部的组件,

关于方法签名的设计:

方法名称尽量要风格一致,并选择大众认可的名称

类的方法设计太多,会使类难以学习,使用,文档化,测试以及维护

避免过长的参数列表,目标参数个数4个以内,太长不好记,容易乱序

拆分参数子集为多个方法入参

将多个频繁出现的参数序列封装成静态成员类,并考虑使用builder方法构建

对于参数类型,要优先使用接口而不是类

对于boolean参数,要优先使用两个元素的枚举类型,例如在一个静态工厂中newInstance(PayType.WX)

易于阅读和编写

易于扩展

枚举常量内易于增加方法

对于多个具有相同参数数目的方法来说,应该尽量避免重载方法,重载是编译期确定调用哪个重载方法,覆写是在运行时

返回类型为数组或集合的方法应该返回一个零长度的数组或者集合

为了正确地编写API文档,必须在每个被导出的方法,类,接口,构造器和字段声明之前增加文档注释

方法的文档注释应该描述它与客户端的约定,而不是说这个方法是怎么干到的

前置条件 后置条件? 副作用 以及方法的线程安全性

@param@return@throw(if xxx then yyy)@code

@code

文档注释的第一句话,是该注释所属元素的概要描述

要使局部变量的作用域最小化,最佳实践是在第一次使用它的地方声明它

异常

只针对异常的情况才使用异常, 不能利用异常来做其它投机取巧的逻辑

对于可恢复的情况且允许调用者能够进行适当的恢复使用受检异常, 其它异常使用运行时异常

优先使用jdk里的标准的异常,对于这些常见的可重用的异常会降低API的学习成本

.更高层的实现应该捕获低层的异常, 同时抛出可以按照高层抽象进行解释的异常,叫做异常转译, 这样避免了方法抛出的异常与它所执行的任务没有明显的联系, 让人不知所措

try{}catch(LowerLevelException e) {    throw new HigherLevelException(...);}

底层的异常被传到高层的异常, 高层的异常提供访问方法(Throwable.getCause)来获取底层的异常

不过我们应该在底层方法调用的时候尽量确保它们会执行成功,从而避免它们抛出异常,比如通过严格的检查高层传递到底层的参数。次选方案是,让高层悄悄的绕开异常, 将高层方法的调用者与底层问题隔离起来。(底层catch异常打错误日志)

一般而言,失败的方法调用应该使对象保持在被调用之前的状态

异常要打印关键信息,禁止忽略异常

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,504评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,898评论 1 300
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,218评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,322评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,693评论 3 290
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,812评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,010评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,747评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,476评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,700评论 2 251
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,190评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,541评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,206评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,129评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,903评论 0 199
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,894评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,748评论 2 274

推荐阅读更多精彩内容

  • 对象的创建与销毁 Item 1: 使用static工厂方法,而不是构造函数创建对象:仅仅是创建对象的方法,并非Fa...
    孙小磊阅读 1,878评论 0 3
  • 面向对象主要针对面向过程。 面向过程的基本单元是函数。 什么是对象:EVERYTHING IS OBJECT(万物...
    sinpi阅读 1,025评论 0 4
  • 目录 第二章 创建和销毁对象 1 考虑用静态工厂方法替代构造器 对于代码来说, 清晰和简洁是最重要的. 代码应该被...
    高广超阅读 1,396评论 0 12
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,584评论 0 11
  • 关于三月 像奔赴一场隔时再约 我从月明星稀的第二清晨醒来 背好已收拾妥当的行囊 杏色的毛衣和青色的风衣 气温从十度...
    荆柠阅读 195评论 0 1