About"static"
static静态修饰符,大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在。
?
在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是有种情况例外,就是该成员是用static声明的。
?
在java类库当中有很多类成员都声明为static,可以让用户不需要实例化对象就可以引用成员,最基本的有Integer.parseInt(),Float.parseFloat()等等用来把对象转换为所需要的基本数据类型。这样的变量和方法我们又叫做类变量和类方法。
?
下面是一个,个人认为比较典型的介绍类成员的例子:
?
public class StaticTest { int x=1; //实例变量 static int y=1; //类变量 public StaticTest() { x++; y++; } public void nonStaticMethod() { System.out.println("run a non_static method."); } public static void staticMethod() { System.out.println("run a static method."); } public static void main(String args[]) { //生成实例t1 StaticTest t1=new StaticTest(); //生成实例t2 StaticTest t2=new StaticTest(); //输出实例t1中的变量x System.out.println("t1.x="+t1.x); //输出实例t2中的变量x System.out.println("t2.x="+t2.x); //System.out.println("StaticTest.x="+StaticTest.x); 该行代码有编译错误,错误如下: //无法从静态上下文中引用非静态变量x //nonStaticMethod(); 该行代码有编译错误,错误如下: //无法从静态上下文中引用非静态方法 nonStaticMethod(); //对于以上两个编译错误的解释: //对于非静态属性和方法,必须先实例化对象后,通过对象的引用才能够访问这些成员, //但是有种情况例外,就是该成员是用static声明的。故正确使用方法如下: t1.nonStaticMethod(); //在不用对象引用的情况下,对静态方法直接调用: staticMethod(); //当然,也可以用对象的引用来调用静态方法,但这违背了定义静态方法的目的,故不推介: t1.staticMethod(); //输出类StaticTest中的类变量y(静态变量y) System.out.println("StaticTest.y="+StaticTest.y); //当然,也可以用对象的引用来调用静态属性,但这违背了定义静态属性的目的,故不推介: System.out.println("t1.y="+t1.y); } } ?
?
上例中t1.y和t2.y是 指向同一个储存空间。?
执行后输出结果如下:
t1.x=2
t2.x=2
run a non_static method.
run a static method.
run a static method.
StaticTest.y=3
t1.y=3
对以上结果的解释说明:
当生成StaticTest类的实例t1时系统为实例变量x初始化分配空间,并执行x++,因此t1的x为2,而y++使y也为2;生成第二个实例t2时重新初始化x为1、而类变量y此时已在创建t1的时候被++为2,故此时y再次++变为3。 实例变量无法由类直接引用,必须在生成实例后由实例进行引用。?另外一个例子,基于上面的StaticTest 类:
?
public class UsingStatic{ StaticTest t1; StaticTest t2; public UsingStatic() { t1 = new StaticTest(); t2 = new StaticTest(); } public void usingNonStaticMember() { //successful scenario: System.out.println("t1.x="+t1.x); System.out.println("t2.x="+t2.x); t1.nonStaticMethod(); t2.nonStaticMethod(); //failure scenario: //System.out.println("t1.x="+StaticTest.x);//无法从静态上下文中引用非静态变量x //StaticTest.nonStaticMethod();//无法从静态上下文中引用非静态方法 nonStaticMethod(); } public void usingStaticMember() { //successful scenario: System.out.println("StaticTest.y="+StaticTest.y); StaticTest.staticMethod(); //not suggested,no point to using a object to invoke the static attributes. //the suggested approach see the successful scenario, use the class to invoke the static attributes. System.out.println("t1.y="+t1.y); System.out.println("t2.y="+t2.y);//not suggested //not suggested,no point to using a object to invoke the static methods. //the suggested approach see the successful scenario, use the class to invoke the static methods. t1.staticMethod(); t2.staticMethod();//not suggested }}??
?
运行usingNonStaticMember()的结果:t1.x=2?
?
至于类方法,如:Integer.parseInt(),可以在不创建对象的情况下使用。至今未发现难点。
?
?
?
?
?
?
?
接下来讲讲为什么 main函数的写法是固定的:
?
为什么要那样写,和JVM的运行有关系。
当一个类中有main()方法,执行命令“java 类名”则会启动虚拟机执行该类中的main方法。
由于JVM在运行这个Java应用程序的时候,首先会调用main方法,调用时不实例化这个类的对象,而是通过类名直接调用因此需要是限制为public static。
对于java中的main方法,jvm有限制,不能有返回值,因此返回值类型为void。
main方法中还有一个输入参数,类型为String[],这个也是java的规范,main()方法中必须有一个入参,类细必须String[],至于 字符串数组的名字,这个是可以自己设定的,根据习惯,这个字符串数组的名字一般和sun java规范范例中mian参数名保持一致,取名为args。
因此,main()方法定义必须是:“public static void main(String 字符串数组参数名[])”。
?