Creating and Destroying Objects
Consider static factpry methods instead of construction
四个优点两个缺点
One advantage of static factory methods is that,unlike constructors,they have names.
A second advantage of static factory methods is that,unlike constructors,they are not required to create a new object each time they're invoked.
A third advantage of static factory methods is that,unlike constructors,they can return an object of any subtype of their return type.
A fourth advantage of static factory methods is that they reduce the vervosity of creating parameterized type instances.
The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.
A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.
注意 static factory method 和 factory pattern 是不同的意思
其中第四点
Foo<Map<Key, Value>> foo = new Foo<Map<Key, Value>>(); vs
Foo<Map<Key, Value>> foo = new Foo<Map<Key, Value>>(); 不利的地方在于,用了 static fatory 构造函数必须是 private 而继承机制的subclass要求父类是super或者protected, 或者说是在鼓励我们用 composition? Consider a builder when faced with many constructor parameters
当构造的参数很多的时候,又是可以选择性的构造,可以使用builder pattern
public class Dring {
private final String name;
private final int price;
private final int fat;
private final int suger;
private final int sodium; public static class Builder {//内置的一个static Builder class 让其使用的时候必须是 new Dring.Builder().xxxxx
private final String name;//这个是必须填写的参数
private final int price;
private int fat=0;//
private int suger=0;//可选择模式,默认为零
private int sodium=0;
public Builder(String name,int price){
this.name=name;
this.price=price;
}
public Builder fat (int fat){
this.fat=fat;
return this;
}
public Builder suger (int suger){
this.suger=suger;
return this;
}
public Builder sodium (int sodium){
this.sodium=sodium;
return this;
}
public Dring build (){
return new Dring(this);
}
}
private Dring (Builder builder){//不是独立函数 因为都在里面所以可以不用get来使用
this.name=builder.name;
this.price=builder.price;
this.suger=builder.suger;
this.fat=builder.fat;
this.sodium=builder.sodium;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
public int getFat() {
return fat;
}
public int getSuger() {
return suger;
}
public int getSodium() {
return sodium;
} } //测试
public class Test2 { public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Dring dring = new Dring.Builder("hongniu", 6).fat(50).suger(20).build();
System.out.println(dring.getName()+"\n"+dring.getPrice()+"\n"+dring.getSodium()+"\n"+dring.getSuger()+"\n"+dring.getFat()); } }
/*
输出
hongniu
6
0
20
50
*/
注意Effecttive Java 和 我自己学的模式设计中的 builder 还是不一样的。注意细看!
Enforce the singleton property with a private constructor an enum type
即是单例模式,设计模式内容看。
Enforce noninstantiability with a private constructor
当需要设计一个静态方法和静态field类的时候,考虑使其无法实例化。
public class StaticM {
private StaticM(){//private之后就无法继承
throw new AssertionError();
} public static void say(){
System.out.print("Hello");
}
} public class Test2 { public static void main(String[] args) throws Exception {
StaticM.say();
} }
Avoid creating unnecessary objects
String s = new String ("s") 与String s = "s" 的区别在于,前者无论如何都直接再创建一个对象,后者 如果创建的对象“s”已经之前被创建过了,那么不用new来创建变量,而是创建一个并非是“引用”的“自动”变量。这个变量拥有它的“值”,并置于堆栈中,因此更加高效。
下面摘录自 http://blog.csdn.net/uber001/article/details/51496887的一段文章
浮点数值不适合用于禁止出现舍入误差的金融计算中。例如System.out.println( 2.0 - 1.1);将打印0.899999999999999,而不是0.9。因为浮点数值采用二进制系统表示,而二进制无法精确表示分数1/10,就像十进制无法精确表示1/3一样。如果需要在数值计算中不含有舍入误差,就应该使用BigDecimal类。
一、 包装类(Wrapper Class)共同的方法
JAVA的包装类
Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class),有些地方也翻译为外覆类或数据类型类。
包装类均位于java.lang包,包装类和基本数据类型的对应关系如下表所示
包装类对应表 基本数据类型 包装类
byte Byte
boolean Boolean
short Short
char Character
int Integer
long Long
float Float
double Double
在这八个类名中,除了Integer和Character类以后,其它六个类的类名和基本数据类型一直,只是类名的第一个字母大写即可。
值得说明的是,java是可以直接处理基本类型的,但是在有些情况下我们需要将其作为对象来处理,这时就需要将其转化为包装类了.所有的包装类(Wrapper Class)都有共同的方法,他们是:
(1)带有基本值参数并创建包装类对象的构造函数.如可以利用Integer包装类创建对象,Integer obj=new Integer(145);
(2)带有字符串参数并创建包装类对象的构造函数.如new Integer("-45.36");
(3)可生成对象基本值的typeValue方法,如obj.intValue();
(4)将字符串转换为基本值的 parseType方法,如Integer.parseInt(args[0]);
(5)生成哈稀表代码的hashCode方法,如obj.hasCode();
(6)对同一个类的两个对象进行比较的equals()方法,如obj1.eauqls(obj2);
(7)生成字符串表示法的toString()方法,如obj.toString().
转换关系:
基本类型------>包装器类
Integer obj=new Integer(145);
包装器类------>基本类型
int num=obj.intValue();
字符串------>包装器类
Integer obj=new Integer("-45.36");
包装器类------>字符串包装器类
String str=obj.toString();
字符串------>基本类型
int num=Integer.parseInt("-45.36");
基本类型------>字符串包装器类
String str=String.valueOf(5);
二、JDK1.5的新特性:自动装包/拆包(Autoboxing/unboxing)
自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
自动装包:基本类型自动转为包装类.(int >> Integer)
自动拆包:包装类自动转为基本类型.(Integer >> int)
在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀,现在自动转换机制
解决了我们的问题。
int a = 3;
Collection c = new ArrayList();
c.add(a);//自动转换成Integer.
Integer b = new Integer(2);
c.add(b + 2);
这里Integer先自动转换为int进行加法运算,然后int再次转换为Integer.
public class Test2 { public static void main(String[] args) throws Exception {
// Integer i1 = new Integer(100);
// Integer i11 = new Integer (100);
// Integer i2 = new Integer (200);
// Integer i22 = new Integer (200);
// System.out.println("Is i1==i11 "+(i1==i11));
// System.out.println("Is i2==i22 "+(i2==i22));
//上面的例子都是false 因为new 的问题?
Integer i1 = 100;
Integer i11 = 100;
Integer i2 = 200;
Integer i22 = 200;
System.out.println("Is i1==i11 "+(i1==i11));
System.out.println("Is i2==i22 "+(i2==i22));
//输出
// Is i1==i11 true
// Is i2==i22 false
// 在java的自动封装 auto-boxing 中 Integer在 -128到127中是自动封装成int的所以第一次的比较实际上是比较数值是否对等
//第二次没有自动封装成200,所以比较的是对象是否相等。因为“==”比较是比较地址还是数值,在封装的时候具有一定迷惑性,所以
//如果要进行数值的比较 ,请用equal方法 即 i1.equal(i11) } }
除了自动封装类型,还有封装类型和基本类型的使用不要混淆。
public static void main(String[] args) throws Exception {
Long sum = 0L;// long sum=0L;时间相比短了非常非常多,性能影响很可怕!
for (int x=0;x<Integer.MAX_VALUE;x++){
sum +=1;
}
System.out.println(sum);
} // 如果是使用的Long封装数据类型,对于sum+=1是对象级别操作,十分浪费内存,在里面会有new的出现、
//目前个人理解,封装类型的出现时为了map等collection 对于数据是“对象”级处理的需要、
避免不必要的内存生成,下面一个例子摘录自 Effective JAVA
public class Person {
private final Date birthDate; // DON'T DO THIS!
public boolean isBabyBoomer(){
// Unnecessary allocation of expensive object;
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime(); gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime(); return birthDate.compareTo(boomStart) >= 0 &&
birthDate.compareTo(boomEnd) < 0;
}
}//这个是错误的 class Person { private final Date birthDate;
private static final Date BOOM_START;
private static final Date BOOM_END; static {
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime(); gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
} public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0 &&
birthDate.compareTo(BOOM_END) < 0;
}
} //对于这两者有什么区别呢?前者每次调用方法的时候, 每次都要生成时间(1946, Calendar.JANUARY, 1, 0, 0, 0)和(1965, Calendar.JANUARY, 1, 0, 0, 0);
//你会发现,既然每次调用用来判断的时间都没有变化,为什么我们每次使用这个方法要再New 一次,这是对资源的浪费,所以在第二个例子,我们将要比较的两个时间用static记录,这样只有在第一次使用的时候需要new,之后就是复用,节省很多空间。
Eliminate obsolete object references
虽然java提供了垃圾回收机制,但是垃圾回收并不是万能的,在一些情况下我们也要仔细的小心一些内存溢出的情况,其中一个就是消除无用的引用,因为java垃圾回收装置并不会判断哪些引用对我们人来讲是有用还是无用,需要我们自行判断,就比如下面这个例子
- public Object pop(){
- if(size==0) throw new EmptyStackException();
- return elements[--size]; //这是堆栈的模拟,假设elements[--8],那么其实还是保留了elements[8]的引用,这是个无用引用,没有人为null是无法自动回收的。
- }
- public Object pop(){
- if(size == 0) throw new EmptyStackException();
- Object result = elements[--size];
- elements[size] = null; // Eliminate obsolete reference 消除引用
- return result;
- }
内存泄露的另一个常见来源是缓存。一旦你把对象引用放到缓存中,很容易会忘掉它直到它不再有用后仍然停留在缓存中。(尚且未涉及缓存)
Avoid finalizer
所谓JAVA终结器,就是JAVA自动回收所使用的函数方法 finalize()。
这个终结函数可以说是一无是处,只是提供了,万一我们忘记了手动释放一些重要资源,他能释放,晚点比没有好,但是正常情况下,资源的释放很重要,我们必须用好。意思说,终结器不要用。
1.终结方法的缺点在于不能保证会及时的执行。
2.及时的执行finalize()方法时垃圾回收算法的一个主要功能,这种算法在不同的JVM实现中大相径庭。(不可依赖,因为不同的算法不同的表现)
3.Java语言规范不仅不能保证finalize()方法会被及时的执行,而且根本就不保证他们会执行。
4.还有一点,使用finalize()有一个非常严重的Severe性能损失。
垃圾回收器只有在内存不够的时候才会调用。
最好使用 try finally
Creating and Destroying Objects的更多相关文章
- Effective Java P2 Creating and Destroying Objects
This chapter concerns creating and destorying objects : when and how to create them, when and how to ...
- Java高效编程(2) -- Creating and Destroying Objects
Item 1: Consider static factory methods instead of constructors Advantage: One advantage of static f ...
- C#生成DBF文件
C# 生成DBF,无需注册Microsoft.Jet.OLEDB. namespace ConsoleApplication { class Program { static void Main(st ...
- Effective Java 第三版笔记(目录)
<Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时 ...
- Effective Java 目录
<Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...
- 【Effective Java】阅读
Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...
- SWIG 3 中文手册——5. SWIG 基础知识
目录 5 SWIG 基础知识 5.1 运行 SWIG 5.1.1 输入格式 5.1.2 SWIG 输出 5.1.3 注释 5.1.4 C 预处理器 5.1.5 SWIG 指令 5.1.6 解析限制 5 ...
- 《Effective Java》读书笔记 - 2.创建和销毁对象
Chapter 2 Creating and Destroying Objects item 1:Consider static factory methods instead of construc ...
- .NET使用FastDBF写入DBF
FastDBF源代码地址:https://github.com/SocialExplorer/FastDBF 第一步在解决方案中新建一个类库的项目:取名为SocialExplorer.FastDBF ...
随机推荐
- p1518 The Tamworth Two
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> ...
- 关于java和c语言中,变量重名问题
请看下面的两段代码: #include <iostream>#include <cstdio>#include <cstring> using namespace ...
- 【洛谷p1258】小车问题
(……吓人,心有余悸) 小车问题[传送门] 洛谷算法标签:: (行吧它居然是个二分[解方程的我抖抖发瑟]) 作为一个写了一页演草纸才解出来的方程,显然我要好好写一写(希望不会半途而废) 思路: 先把其 ...
- 31. Next Permutation (java 字典序生成下一个排列)
题目: Implement next permutation, which rearranges numbers into the lexicographically next greater per ...
- deepin系统安装成功了之后重启电脑没有deepin启动选项的简单解决办法
开机 连续按 f10(我的电脑是惠普的,由于主板的不同可能启动键也有所不同)进入 bios 界面如图 选择系统设置,启动选项 之后如图 选择 uefi 模式下的开机顺序栏的 操作系统管理员选项并 ...
- Apache commons(Java常用工具包)简介
Apache Commons是一个非常有用的工具包,解决各种实际的通用问题,下面是一个简述表,详细信息访问http://jakarta.apache.org/commons/index.html Be ...
- 安卓——Handler延迟跳转
//声明控制对象 Handler handler =new Handler(){ @Override public void handleMessage(Message msg) { super.ha ...
- MySQL-1236问题处理
2018年9月26日 9:25 现象:192.168.7.206.192.168.7.207互为双主,同步报错 1236 7.206现象如下 root@mysqldb 09:15 [mys ...
- Physical Limits of ASM
Oracle version 7, only 1,022 datafiles per database could be used. Oracle version 11g, support 65,5 ...
- 在springboot中用redis实现消息队列
环境依赖 创建一个新的springboot工程,在其pom文件,加入spring-boot-starter-data-redis依赖: <dependency> <groupId&g ...