effective

《Effective Java》读书笔记--创建和销毁对象

白昼怎懂夜的黑 提交于 2020-03-01 22:46:06
考虑用静态工厂方法代替构造函数。 当我们在写一个工具类时,是不希望用户将该类实例化的,所以应该定义一个private的构造函数,而不 是将类声明成abstract,因为这样用户可以继承该类,子类可以被实例化。 String类型是非可变对象,如下代码中,s指向的String的值是不能被更改的,当s重新赋值时,s就指向另一个String对象。 String s = new String("silly"); 上句代码每次执行都会创建一个新的String实例,建议用 String s = "silly";代替上一句,这样的话,对于同一个虚拟机中运行的代码,每次执行该句时,因为它们包含相同的字符串字面常量"silly",该对象就会重用,避免创建重复对象。 过期的引用应该手动将它赋值成null,这有两个好处: 让垃圾回收机制及早清理掉这些“垃圾”,提高程序的性能。 如果它们在以后又被错误地解引用,则程序会立即抛出NullPointerException异常,而不是悄悄的错误运行。 不要把JAVA的finalizer当成C++的构造函数。因为JAVA的对象不可达时,finalizer函数不确定何时才能执行。不建议把释放资源的操作写在finalizer中,应该显式的提供一个close()函数给用户手动释放资源。 来源: oschina 链接: https://my.oschina.net/u

《Effective JAVA学习笔记》之 compareTo()

南楼画角 提交于 2020-02-29 11:13:48
class Person implements Comparable<Person> { String firstName; String lastName; int birthdate; // Compare by firstName, break ties by lastName, finally break ties by birthdate public int compareTo(Person other) { if (firstName.compareTo(other.firstName) != 0) return firstName.compareTo(other.firstName); else if (lastName.compareTo(other.lastName) != 0) return lastName.compareTo(other.lastName); else if (birthdate < other.birthdate) return -1; else if (birthdate > other.birthdate) return 1; else return 0; } } 总是实现泛型版本 Comparable 而不是实现原始类型 Comparable 。因为这样可以节省代码量和减少不必要的麻烦。 只关心返回结果的正负号(负/零/正)

《Effective Java读书笔记》--类和接口

Deadly 提交于 2020-02-28 11:42:57
使类和成员的可访问能力最小化 应该尽可能使每一个类或成员不被外界访问。 如果一个包级私有的顶层类或者接口只是在某一个类的内部被调用到,应该考虑使用嵌套类实现。 确保public staitc final所引用的对象是不可变的。 public static final的数组几乎总是错误的: import java.util.Arrays; import java.util.Collections; import java.util.List; public class Test { public static void main(String[] args) { for (int i = 0; i < foo.VALUES.length; i++) { foo.VALUES[i] = new Integer(0); } for (int i = 0; i < foo.VALUES.length; i++) { System.out.println(foo.VALUES[i]); } } } class foo { public static final Integer[] VALUES = { new Integer(0), new Integer(1), new Integer(2), new Integer(3) }; } 虽然VALUES被定义成final

《Effective Java读书笔记》--序列化

狂风中的少年 提交于 2019-12-20 10:33:35
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 谨慎地实现Serializable 实现Serializable有以下几点风险 实现Serializable的类一旦发布,则“改变这个类的实现”的灵活性将大大降低。 增加了错误和安全漏洞的可能性。 测试负担会增加。 为了继承而设计的类应该很少实现Serializable,接口也应该很少会扩展它。 保护性地编写readObject方法 不严格的说,readObject是一个“用字节流作为唯一参数”的构造函数"。所以在写readObject时,就想象自己正在编写一个构造函数。 例如,在一个类的构造函数中,对参数的有效性做了检查,并且也做了保护性拷贝的话,readObject中也应该实现该逻辑。Period类(参考 http://my.oschina.net/u/1453800/blog/263037#OSC_h3_2 )的readObject可以写成这样: private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); start = new Date(start.getTime()); end = new Date(end.getTime()); if

C++ 备忘录 ( 持续更新中... )

余生颓废 提交于 2019-12-10 06:57:01
Tip 1: #include 包含头文件的问题 新的编译器格式: #include <iostream> using namespace std; 旧的编译器格式: #include <iostream.h> 注:旧的编译器格式中,包含头文件后,不添加 “using namespace std” Tip 2 : Windows 环境中 ,程序运行时界面自动关闭、一闪而过的问题 解决方法:在 main() 的 return 语句前添加 cin.get() 语句 ; 有时需添加两行这样的代码。 注:cin.get() , 可以读取空格、制表符和换行符。 Tip 3 : C++ 程序 中也可以使用 C 语言中的输入输出函数 , 只需包含头文件 ”stdio.h” Tip 4 :访问命名空间 std 的方法 : M1 :将 using std namespace; 放在函数定义之前,让文件中所有的函数都能够使用名称空间 std 中所有的元素 M2 :将 using std namespace; 放在函数定义中,这样该函数能使用命名空间中所有的元素 M3 :在特定的函数中使用 using std::cout; 这样的命令而不是 using std namespace; 让该函数能够使用指定的元素,如 cout M4 :完全不使用变异命令 using , 在需要使用名称空间 std

Effective C++ Notes(读书笔记)

限于喜欢 提交于 2019-12-09 12:05:57
1,视C++为一种语言联邦,大致分为4个部分: A)C。说到底C++仍是以C为基础。区块、语句、预处理器、内置数据类型、数组、指针等等统统来自C。 B)Object-Oriented C++。这部分也就是C with Classes所诉求的:classes(包括构造函数和虚构函数)、封装、继承、多态,虚函数等等。 C)Template C++。这是C++的范型编程部分,tamplates威力强大,它给我们带来了崭新的编程范型,也就是所谓的TMP模板元编程。 D)STL。STL是个template程序库,它对容器、迭代器、算法以及函数对象的规范有极佳的紧密配合与协调,然后template及程序库也可以其他想法建置出来。 2,尽量使用const,enum,inline代替#define A)#define不被视为语言的一部分,属于预处理指令,编译不会计入符号表无法调试。 B)#define在预处理器处理阶段只做简单的替换,这将带来很多预期意外的行为。如 #define MAX(a, b) ((a)>(b)?(a):(b)) 尽管上述宏定义已将变量用括号括起来了,但是还是不能避免MAX(++a, b+10)这样给a所带来的两次不是预期内的自增行为。以为替换为: template<typename T> inline T Max(const T& a, const T& b) {

《Effective Java读书笔记》--通用程序设计

久未见 提交于 2019-11-30 02:57:48
将局部变量作用域最小化 最有力的技术是在第一次使用它时声明,并把它初始化。 如下代码分别用for和while对lst数组做了两次遍历。大家可以想想, for和while哪种写法更优呢? public class Test { public static void main(String[] args) { int[] lst = { 1, 2, 3, 4 }; for (int i = 0; i < lst.length; i++) { System.out.println(lst[i]); } for (int i = 0; i < lst.length; i++) { System.out.println(lst[i]); } int i = 0; while (i < lst.length) { System.out.println(lst[i]); i++; } i = 0; // 如果漏了这句,将导致一个bug。 while (i < lst.length) { System.out.println(lst[i]); i++; } } } for比while更好,原因如下: for的变量i只在for循环内有效,而while采用的i作用域更大。 正由于while语句中的计数变量i的作用域更大,所以写第二个while循环,漏掉了i的初始化,也能编译通过,但是产生了bug!!