作为一门面向对象的语言,我们学习java,对于对象的学习非常重要。大多的教程上都用抽象的概念驱使着我们理解对象,把现实抽象为对象,却忽略对创建对象的研究。如果学习抽象思维,运用抽象思维虚拟现实是走向java顶端的关键,那创建对象就是通向成功的垫脚石。今天我们就来谈谈创建对象。
说到创建对象,new 方法是java最常用也是最简单的方式。而恰恰是它的简单,让我们用的那么的随意。
举个例子:
public class Demo {
private String i;
private String love;
private String java;
public String getDemo(){
return i + love + java;
}
}
编译器如果不为我们优化,调用一次getDemo我们将创建2个对象。而我们都清楚,可以使用stringbuffer和stringbuilder代替。
public class Demo {
private String i;
private String love;
private String java;
public String getDemo(){
StringBuilder builder = new StringBuilder();
builder.append(i);
builder.append(love);
builder.append(java);
return builder.toString();
}
}
这样是解决了调用一次getDemo创建多个对象,那么单线程下,调用多次getDemo呢?那会创建多次stringbuider类型的对象。我们是否可以优化呢?请看代码:
public class Demo {
private String i;
private String love;
private String java;
private final ThreadLocal<StringBuilder> cache = new ThreadLocal<StringBuilder>();
public String getDemo(){
StringBuilder builder = cache.get();
if(builder==null){
builder = new StringBuilder();
cache.set(builder);
}else{
builder.delete(0, builder.length());
}
builder.append(i);
builder.append(love);
builder.append(java);
return builder.toString();
}
}
我们使用了threadlocal类,用线程保持着stringbuilder,当前线程下,不管我们调用多少次getDemo,都只会创建一次stringbuilder。熟悉多线程的你应该已经考虑安全的问题了。是的,使用成员属性容易引起线程安全问题。上面代码里的判断非空和set是非安全的。我们做修改后如下:
public class Demo {
private String i;
private String love;
private String java;
private final ThreadLocal<StringBuilder> cache = new ThreadLocal<StringBuilder>();
public String getDemo(){
StringBuilder builder = cache.get();
if(builder==null){
synchronized (this) {
builder = new StringBuilder();
cache.set(builder);
}
}else{
builder.delete(0, builder.length());
}
builder.append(i);
builder.append(love);
builder.append(java);
return builder.toString();
}
}
我们编写的程序,方法中每个new操作,运行在多线程情况下,最终会产生n个对象。我们知道new 创建的对象存在于堆中,它不会随着线程的执行结束而释放。而对于这些对象的回收,我们需要jvm的垃圾回收来完成,而垃圾回收什么时候开始,回收效果如果,我们往往不会去关注。
可以确定的是,我们都希望着jvm立刻回收不需要使用的对象,以便我们可以最大限度的使用内存。但是我们为什么不从源头,从创建的时刻,尽量少的使用它呢。
以上是我个人的理解,如有错误,敬请纠正。