我改了个名字,设成了静态,这样就不用new了!谈谈这句话所代表的

新手们往往喜欢使用静态的方法,有的因为不用new,有的看到ThinkInJava上说new的过程非常costly,认为使用静态方法不用new从而有更快的执行效率。

希望能够就静态方法的使用展开讨论,大家共同进步。

阎宏的《Java与模式》中12章,有一句话:
"因为一个方法是不是静态的,对于Java语言来说是一个很大的区别,必须在一开始就加以考虑。"
以此作为引子,希望能够讨论出几条Killer理由,让大家增加static方法的使用造诣。

我觉得每new一个对象就要占用一部分资源。
而且我很讨厌在class的开头引入一大堆的包,我更喜欢通过封装和继承,使一个class只要引入一、两个class就好了,我的jsp就是这样,只引入一个bean,所有jsp要用的功能都用bean封装一下。(当然这很容易,只要写一个公共bean,包含常用的方法,然后具体的页面bean继承这个公共bean,加入自己特质的一些东西就OK。)

再说static,我是参照了java API的做法,你看Integer.parseInt()是一个静态方法,我看了源代码,Integer.parseInt()都没有用线程安全的关键字sy(记不全了)。再想想自己平时调用java API时很多方法都是直接调用,不用new的。我不是太懂,我自己分析的是,只要不需要在对象里保存特有的信息,那么就可以作成static的。比如Calendar,因为必须保存一个时间点的时间,因此Calendar需要new,SimpleDateFormate,因为要保存格式信息因此也必须new。Integer.intValue()要先保存整数值进去才可以调用,因此就必须new,而Integer.parseInt(String str)由于要转化的字符有参数输入,调用前后不需要保存任何信息因此就是静态。

我懂得不多,参照了java API的写法,我觉得这个方法应该用static。

package javanet;

public class TestStatic {

public TestStatic() {
}
public static void doSomething() throws Exception{
Thread.sleep(10);
}
public void doOtherSomething() throws Exception{
Thread.sleep(10);
}
public static void main(String args[]) throws Exception{
String rtn="static ";
long start=System.currentTimeMillis();
rtn+=System.currentTimeMillis()+" started.";
for(int i=0;i<1000;i++){
doSomething();
}
long end=System.currentTimeMillis();
rtn+=System.currentTimeMillis()+" end.";
rtn+=(end-start)+ " total.";
System.out.println(rtn);
start=System.currentTimeMillis();
rtn="instance "+System.currentTimeMillis()+" started.";
for(int i=0;i<1000;i++){
new TestStatic().doOtherSomething();
}
end=System.currentTimeMillis();
rtn+=System.currentTimeMillis()+" end.";
rtn+=(end-start)+ " total.";
System.out.println(rtn);
start=System.currentTimeMillis();
rtn="instance "+System.currentTimeMillis()+" started.";
TestStatic test=new TestStatic();
for(int i=0;i<1000;i++){
test.doOtherSomething();
}
end=System.currentTimeMillis();
rtn+=System.currentTimeMillis()+" end.";
rtn+=(end-start)+ " total.";
System.out.println(rtn);
}
}

我的运行结果:
1。命令行:JDK1.4.1_02
D:\>javac TestStatic.java

D:\>java TestStatic
static 1059964948738 started.1059964958753 end.10015 total.
instance 1059964958753 started.1059964968767 end.10014 total.
instance 1059964968767 started.1059964978782 end.10015 total.

D:\>java TestStatic
static 1059965002546 started.1059965012560 end.10014 total.
instance 1059965012560 started.1059965022575 end.10015 total.
instance 1059965022575 started.1059965032589 end.10014 total.

D:\>java TestStatic
static 1059965132863 started.1059965142878 end.10015 total.
instance 1059965142878 started.1059965152892 end.10014 total.
instance 1059965152892 started.1059965162906 end.10014 total.

2。Jbuilder7 with JDK1.3.1

static 1059965207821 started.1059965217986 end.10165 total.
instance 1059965217986 started.1059965228080 end.10094 total.
instance 1059965228080 started.1059965238175 end.10095 total.


static 1059965260667 started.1059965270822 end.10155 total.
instance 1059965270822 started.1059965280916 end.10094 total.
instance 1059965280916 started.1059965290991 end.10075 total.

static 1059965305321 started.1059965315486 end.10165 total.
instance 1059965315486 started.1059965325590 end.10104 total.
instance 1059965325590 started.1059965335675 end.10085 total.

3。Jbuilder7 with JDK1.4.0-b92

static 1059965465762 started.1059965475916 end.10154 total.
instance 1059965475916 started.1059965486001 end.10085 total.
instance 1059965486001 started.1059965496105 end.10104 total.

static 1059965537195 started.1059965547439 end.10244 total.
instance 1059965547439 started.1059965557534 end.10095 total.
instance 1059965557534 started.1059965567618 end.10084 total.

static 1059965618732 started.1059965628947 end.10215 total.
instance 1059965628947 started.1059965639041 end.10094 total.
instance 1059965639041 started.1059965649126 end.10085 total.

莫名其妙。

2。Jbuilder7 with JDK1.3.1
3。Jbuilder7 with JDK1.4.0-b92
都比较符合我的猜测。

JDK1.4.1_02,好像有点bug。

测试可以改进,应该用三个版本分别编译3次,还要把循环设置多一点,让其他的时间变成很小的因素!


基于我对面向对象的概念的浅薄理解,我觉得,

毫无疑问

使用静态方法,的确破坏了面向对象的概念。

但是我很想知道的是

使用 静态方法,到底是会 增加系统的开销,还是相反,会减少系统

开销。

希望高手指点

我JAVA的基础一般,姑且说一下,让高手更正。

static的东西一经调用,就会驻留内存,而且不会释放。但自始致终只驻留“一份”。

new的东西就有生命周期,每new一下就用多一些空间,但用完后会被回收。

>static的东西一经调用,就会驻留内存,而且不会释放。但自始致终只驻留“一份”。

>new的东西就有生命周期,每new一下就用多一些空间,但用完后会被回收。

你说的很对,考虑这一层的话,那就看这个方法被访问的频率了来确定是static还是new了。

我也这样理解,到这里我想大家的理解是一致的。
关键是再往后推论,很容易会这么想:
在一个类里作两个方法,一个静态的,一个实例的,只包含一句代码:
Thread.sleep(10*1000);

static的只有一份,那么我在JSP中调用这个静态方法,JSP是多线程的,而静态方法只有一份。如果方法执行需要10妙,我在两个窗口内打开这个JSP,应该先执行一个,后执行一个。如果是实例方法,在两个窗口中打开JSP,new了两个Local变量,一定两个分别执行。这时候,使用static和使用instance应该有明显的区别。
事实上,我在JBuilder里试了又试,没什么明显的区别。

我是化工改行计算机的,对底层技术了解很少,不太了解真正的执行代码过程,到这里我也不能为自己解惑。另外,如果将上述的方法设为synchronized 会怎么样呢?

用不用静态,和具体的应用有关,根本不是效率或者资源的问题。

不管是不是静态,在两个jsp里就是两个Thread。
那个Thread调用的不是这个方法的线程,也不是这个类的线程,是调用所有这些东西的线程,比如这个jsp!

java是多线程的,但是前提是你必须用多线程的技术来编程!

是我没说清楚,我是说在一个类里实现两个方法,然后在2个JSP中分别调用这个类的静态方法和实例方法。

因为是两个线程,所以没有影响。