c语言中的静态变量必需是局部变量,就类似于全局变量

java 的静态只能修饰全局变量.

原因是因为c语言的类型是五大种修饰符,但是有的书上写的却是六种,如下.

分别是:auto, const, register,

static, volatile, extern.

局部变量除非显式指明为static,否则默认为auto,所以一般不会在代码中使用类型

修饰符auto.

    在后编译器时代,优化器可以合理的分配寄存器,所以一般不会在代码中使用类型修

饰符register.

    extern只用于声明全局变量,用法单一。

1、auto:这个关键字用于声明变量的生存期为自动,即将不在任何类、结构、枚举、联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量。这个关键字不怎么多写,因为所有的变量默认就是auto的。

register



这个关键字命令编译器尽可能的将变量存在

CPU

内部寄存器中而不是通过内存寻址访问以提高效率。


register



这个关键字命令编译器尽可能的将变量存在

CPU

内部寄存器中而不是通过内存寻址访问以提高效率。


2、register:这个关键字命令编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率。

3、static 常见的两种用途:

   1>统计函数被调用的次数;

   2>减少局部数组建立和赋值的开销.变量的建立和赋值是需要一定的处理器开销的,特别是数组等含有较多元素的存储类型。在一些含有较多的变量并且被经常调用的函数中,可以将一些数组声明为static类型,以减少建立或者初始化这些变量的开销.    详细说明:

   1>、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与栈变量和堆变量的区别。

   2>、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。     3>当static用来修饰全局变量时,它就改变了全局变量的作用域,使其不能被别的程序extern,限制在了当前文件里,但是没有改变其存放位置,还是在全局静态储存区。  

 使用注意:

   1>若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;     2>若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;     3>设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题(只要输入数据相同就应产生相同的输出)。

4、const:值得注意的是,const修饰的是在它前面的类型,如果它前面没有类型,那它修饰的是紧跟着它的那个类型。如:(a)const int i = 0; 和 (b)int const i = 0; 是完全一样的。在(a)中,const前面没有类型,它就修饰它后面的那个int类型。在(b)中,const修饰它前面的int类型,两者没有任何区别。

5、volatile:volatile修饰符的作用是告诉优化器不能优化这个变量的读写操作,一定要为这个变量的读写操作生成代码。

例如:

/* 延时操作 */

int foo(void) {

/* 100次减法后返回*/

volatileint i = 100; /*(a)*/

while (i> 0) i--;  /*(b)*/

return 0;

}

    在无volatile修饰的情况下,因为变量i的变化对上下文无影响,所以优化器很可能会省略掉对i操作的代码,而只生成return 0的代码,加上volatile可以保证编译器一定为语句(a)和(b)生成代码,达到延时的目的。


reglister int i;下去了解这几种修饰符.

java的静态变量不管定义在什么地方,都不会随类的结束而结束,而是随着程序的结束才会结束.原因是因为在jvm中,[堆,栈,常量区]特意为静态的变量分配的静态存储区.所以,有静态变量的地方必需加上Finalize方法.

java初始化:

1:构造函数(如果没有声明构造函数,系统就会自动给定一个以没有参数的构造函数),如果程序员定义了带参数的构造函数,而没有默认的构造函数,则默认的构造函数将不存在,带参数的构造函数和默认的构造函数是可以一起存在的.

2:初始化块(给程序做初始化,也可以替代构造函数的功能,初始化块更加简洁,而且不需要调用,并且在构造函数之前执行)

3:静态初始化块(初始化静态成员,不需要调用,这个在初始化块之前执行)

如果存在父子关系的类,那么就是父类的静态块,然后是子类的静态块,然后是父类的初始化块,然后是父类的构造函数,然后再是子类的初始化块,然后是子类的构造函数.可以这样理解:要有孩子,必需要有父亲,孩子和父亲,有一种遗传基因关系,所以,有了父亲的基因在前,然后孩子的遗传基因,然后,父亲发育成熟之后(构造函数之后)才会生孩子.这样理解,就很好理解初始化顺序了.

例如代码:

/**

* 研究java初始化

* @author wanggang-pc

*

*/

public class Test1 {

public static void main(String[] args){

Test1.pr();

Test1 t=new Test1();

Test1.pr();

}

public static int temp=0;//静态变量以及对他的初始化

public Test1(){

temp+=2;

//System.out.println();

System.out.println("构造函数初始化"+temp);

}

static{

temp+=3;

//System.out.println();

pr();

System.out.println("这是静态块"+temp);

}

{

temp+=2;

//System.out.println();

System.out.println("这是实例初始化快"+temp);

}

public static void pr(){

temp+=2;

System.out.println(temp);

}

/**以下是执行结果

* 这是静态块3

5

这是实例初始化快7

构造函数初始化9

11

通过上述结果,可以知道,在初始化过程中,首先执行的是静态块的初始化,然后执行实例化块里面的代码,然后才是执行构造函数里面的初始化代码。所以,我们在初始化的时候,可以通过new一个对象,在这个对象的构造函数实现初始化,也可以让你需要的初始化变量或者执行方法在这个实例的静态类中初始化,也可以在他的实例化初始化块中进行初始化。

字符串的初始化String str="111";String str=new String("111");String str=new String();str="111";

*/

}

6、如果这个类还存在父类,那又应该怎么解释初始化方法?

public class Test2 extends Test1 {


public static void main(String[] args) {

// TODO Auto-generated method stub

//pr();

Test2 e=new Test2();

}

{

System.out.println("这是子类的实例初始化块");

}

static{

System.out.println("这是子类的静态块");

}

public Test2(){

System.out.println("这是子类构造块");

}


/**

*运行结果如下

5

这是静态块5

这是子类的静态块

这是实例初始化快7

构造函数初始化9

这是子类的实例初始化块

这是子类构造块

由上述的证明可以得知,在有父类的情况下,实例化父类的子类,那么他先执行父类的静态块,然后执行子类的静态块,然

后再去执行父类的实例化块,然后是父类的构造函数,过后才是执行它的实例化块,最后是它自己的构造函数

*/

}




在java里面,非静态可以自动调用静态,但是静态不能直接使用非静态(必需实例化之后才可以完成),静态的成员直接调用静态成员.静态优先于初始化块.

原因:静态的static的生命周期由内存结构决定.