- 博客(14)
- 收藏
- 关注
原创 《Effective Java》漫谈:继承带来的equals难题
传递性: 对于任何非空引用值 x、 y 和 z,如果 x.equals (y)返回 true,而 y.equals (z)返回 true,那么 x.equals (z)应该返回 true。对称性: 对于任何非空引用值 x 和 y,当且仅当 y.equals (x)返回 true 时,x.equals (y)应该返回 true。自反性: 对于任何非空引用值 x,x.equals (x)应该返回 true。对于任何非空的引用值 x,x.equals (null)应该返回 false。我们可以考虑这样修改。
2023-10-24 16:12:21 88
原创 《Effective Java》漫谈:被废弃的终结方法
翻开Object源码,其中定义了空方法finalize(),我们看一下文档中的解释当垃圾回收器确定不再有对对象的引用时,由对象上的垃圾回收器调用。子类重写finalize方法以释放系统资源或执行其他清理。finalize方法可以执行任何操作,包括使该对象再次对其他线程可用;然而,finalize的通常目的是在对象被不可撤消地丢弃之前执行清理操作。例如,表示输入/输出连接的对象的finalize方法可能会执行显式的I/O事务,以在永久丢弃该对象之前中断连接。创建一个。
2023-10-22 01:30:04 119 1
原创 《Effective Java》第7条:消除过期的对象引用
来实现删除元素的效果,会发生什么?答案是:从一个表中删除的对象不会被回收,因为实际上表内部依然维护着这些对象的引用,只不过我们通过限制访问,所以无法查看罢了。当然不会忽略这个问题,但是只要是类自己管理内存,我们就应该警惕可能发生的内存泄露问题。为例,想要了解原理的读者可以看一下源码,这里指简单讲一下。假设一开始创建容量为16的数组,初始化之后数组为空,因此。因此如果要从表中删除元素,需要先将它清空,再修改。要从上面这个表中删除最后一个元素,可以直接把。设为2,这样就无法查看最后一个元素了。
2023-10-20 17:45:43 70 1
原创 《Effective Java》第6条:避免创建不必要的对象
运行时常量池和常量池是两个不同的概念,JVM在完成类装载操作时,会将常量池中的内容载入内存,并保存在方法区中的运行时常量池,如果是字符串的话,会先在堆中创建字符串对象实例,然后将该对象的引用放到堆中的字符串常量池中,最后将运行时常量池里的符号引用替换成直接引用。方法时传入的参数范围在-128~127间,会直接返回常量池中数据的引用,否则创建新对象,不多展开,感兴趣的可以看一下源码。“该语句每次被执行的时候都创建一个新的String实例,但是这些创建对象的动作都是不必要的。反汇编后可以发现自动调用了。
2023-10-19 20:53:50 63 1
原创 《Effective Java》第5条:优先考虑依赖注入来引用资源
当一个类的实现需要依赖一个或多个底层资源时,可以利用依赖注入,将这些资源传给构造器、静态工厂或者构建器,通过来们来创建类。通过filed注入的方式不理想,因为它无法支持多资源。3. 通过setter方法注入。1. 通过filed注入。2. 通过构造器注入。先创建Book资源类。
2023-10-18 11:31:39 65 1
原创 《Effective Java》第4条:通过私有构造器强化不可实例化的能力
当类不包含显式的构造器时,编译器会自动生成公有的、无参的缺省构造器,只要让一个类包含一个私有构造器,它就不能被实例化。但是这种类无法子类化,因为所有的构造器必须显式或隐式地调用超类构造器,这种情况下,子类没有可访问的超类构造器可用。即使将类做成抽象类,通过继承的方式仍然可以实现实例化,而且会让用户误以为该类是专门为了继承而设计的。
2023-10-18 09:27:41 56 1
原创 《Effective Java》第3条:用私有构造器或者枚举类型强化Singleton属性
为了将利用上述方法实现的Singleton类变成可序列化的,需要声明所有实例域都是瞬时(tansient)的,并提供一个readResolve方法,否则反序列化后会创建新的实例。1. 自带序列化机制,更加简洁,同时能够防御反序列化攻击。反序列化得到的对象和序列化的对象是同一个。3. 声明一个包含单个元素的枚举类。1. 公有静态成员为final域。为什么枚举是单例模式的最佳方法?2. 公有成员为静态工厂方法。2. 能够阻止反射攻击。
2023-10-17 21:40:19 72 1
原创 《Effective Java》第2条:遇到多个构造器参数时要考虑使用构建器
还有诸如参数可以在调用build方法来创建对象期间进行调整或者随着不同的对象而改变、自动填充某些域等优势,不再赘述。重叠构造器提供的第一个构造器只有必要的参数,第二个构造器有一个可选参数,第三个构造器有两个可选参数,以此类推。先使用无参构造器创建对象,再调用setter方法来设置每个必要的参数。连续调用两次addPress方法,可以将传入的参数集中到press里面。静态工厂和构造器有一个共同的局限性:不能很好地扩展到大量的可选参数。1. 可以将多次调用某一个方法而传入的参数集中到一个域中。
2023-10-16 10:45:04 81 1
原创 链表的操作
如果直接将单链表的反转复用到双链表上,会发现最后每个结点的prev和next链接域指向的都是同一个结点,只需要遍历一遍链表修改prev链接域。链表的排序方法依然是以上两种,只考虑通过调整链接实现插入排序,操作过程就是一个个取下链接结点,将其插入一段元素递增的结点链中的正确位置。对于链接表,改变其中元素顺序的方法有两种:1.在结点之间搬动元素;2.修改结点之间的链接,改变结点的链接顺序。将单链表的排序复用到双链表上,最后遍历一遍链表修改prev链接域即可,不再赘述。
2023-10-15 20:17:56 40 1
原创 《Effective Java》第1条:用静态工厂方法代替构造器
③可以直接通过接口引用被返回的对象。实现一个Book类,对于正在打折的书可以调用getSaledBook方法获取SaledBook实例,①能够实现SaledBook类的隐藏,②不需要知道SaledBook类的存在,通过Book即可调用。2. 不必每次调用的时候都创建一个新对象,可以使用预先构建好的实例,或者复用构建好的实例,能够:①避免创建不必要的重复对象;4. 所返回的对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值,客户端不知道也不需要知道它们从工厂方法中得到的对象的类。
2023-10-15 15:45:17 58 1
原创 链表的变形
双链表可以变形为循环双链表,表尾结点next指向首结点,表首结点prev指向尾结点,与循环单链表需要掌握尾结点tail不同的是,循环双链表无论是掌握首结点head还是尾结点tail,都可以高效实现首尾两端的插入/删除操作,不再赘述。单链表的另一类常见变形是循环单链表,最后一个结点的引用域不为空(null),而是指向首结点,表对象只需要一个数据域rear来引用尾结点,从而高效实现首尾两端的插入/删除操作。简单单链表的实现有一个缺点:尾端插入元素操作的效率很低。为了支持两端的高效操作,可以使用双引用域。
2023-10-14 21:08:24 48 1
原创 单链表的简单实现
n个结点通过链接形成一条链接链,head变量用于保存表首结点的引用,称为表头变量或者表头指针,表尾结点的链接域置为空(null),用于表示链表的结束。表元素域elem保存着作为一个表元素的数据项,链接域next里保存着同一个表里的下一个结点的链接。实现线性表的另一种常用技术是基于链接结构,用链接关系显式地表现元素之间的顺序关联。
2023-10-14 11:22:41 54 1
原创 动态顺序表的简单实现
表中元素顺序存放在一大块连续存储区里,这样实现的表称为顺序表,在这种实现中,元素的顺序关系由存储位置的顺序表示。分离式带来的最大优势:存储区扩容。优点:O(1)时间的查询操作。怎么选择新存储区的容量呢?简单实现一个动态线性表。
2023-10-13 20:51:18 38
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人