static关键字
-
相关概念:
- static翻译为:静态的
- 所有static关键字修饰的都是类相关的,类级别的
- 所有static关键字修饰的都是采用“类名.”的方式访问
- static修饰的变量:静态变量
- static修饰的方法:静态方法
补充回顾-变量的分类:
- 变量根据声明的位置进行划分:
- 在方法体当中声明的变量叫做:局部变量
- 在方法体外声明的变量叫做:成员变量
- 而成员变量又可以分为:
- 实例变量
- 静态变量
- 而成员变量又可以分为:
看相关代码总结知识点:
class VarTest{ int i; // i为实例变量 public void m1(){ // m1()为实例方法 int x = 200; } /* 实例-总结:1.以上都是实例的,对象相关的,访问时采用“引用.”的方式访问,需要new对象。 2.实例相关的,必须先有对象才能访问,可能会出现空指针异常。 */ static int k; // k为静态变量 public static void m2(){ // m2()为静态方法 int m = 100; } /* 静态-总结:1.以上都是静态的,都是类相关的,访问时采用“类名.”的方式访问。不需要new对象。 2.不需要对象的参与 即可访问,不会导致空指针异常。 */ }
- 实例相关的都需要new对象,通过“引用.”的方式访问
- 静态相关的都用“类名.”的方式访问,也可以使用“引用.”的方式,只不过不建议,因为会让程序员产生困惑:这是实例变量还是静态变量?
-
思考:什么时候变量声明为实例的,什么时候声明为静态的呢?
答:如果这个类型的所有对象的某个属性都是一样的,不建议定义为实例变量,因为会浪费内存空间(原因如下内存图)。即:如果一个对象一份的属性,就定义为实例变量;如果所有对象的属性都是一样的则定义为静态变量。
如以下 程序所示:
class Chinese{ // 身份证号 String idCard; // 每个人的身份证号都不同,即一个对象一份,应定义为实例变量 // 姓名 String name;// 姓名也是如此,应定义为实例变量 // 国籍 String country;// 而国籍,对于Chinese类来说,每个人的国籍都是“中国”,不会随着对象的改变而改变 // 显然,国籍并不是对象级别的特征 // 国籍属于整个类的特征,整个族的特征 // 所以国籍应该定义为静态变量 static String contry; // *****重点:静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了 // 静态变量存储在方法区 }
静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了;静态变量存储在方法区
-
那么,如果声明为实例变量,内存图是怎样的?而声明为静态变量,内存图又是怎样的?
如以下内存图所示:
(声明为实例变量的内存图)
(声明为静态变量的内存图)
-
思考:什么时候声明实例方法,什么时候声明静态方法?
答:(先记着,后面还会讲)当这个方法体中直接访问了实例变量,这个方法一定时实例方法。
在以后开发中,大部分情况下,如果是工具类的话,工具类当中的方法一般都是静态的(静态方法有一个优点,即不需要new对象,直接采用“类名.”方式调用,极其方便。工具类就是为了方便,所以工具类中的方法一般都是static的)
何为工具类? ....以后说 .....
举例:如:张三考试得了90分,李四考试得了100分,
不同的对象参与考试的结果不同,
我们可以认为"考试"这个行为是与对象相关的行为,
所以应将“考试”这个行为定义为实例方法。
静态代码块.....实例代码块.......(不是很重要,先略过)
-
复习JVM内存管理:
- Java中一共有三个变量,须掌握哪个变量存储在哪块内存上。
- 栈区:方法只要执行,无论是实例方法、静态方法还是构造方法,都会压栈。(栈区存储局部变量)
- 堆区:new出来的对象都在堆中,垃圾回收器GC主要针对堆区。(堆区存储实例变量)
- 方法区:方法区存放的是 类的信息、字节码信息、代码片段。(方法区存储静态变量)
- 注:方法的代码片段存储在方法区,但是方法执行过程中需要的内存在栈中。
public class staticTest{ // 静态变量在什么时候初始化? 类加载时初始化 // 静态变量存储在哪里? 方法区 static int i = 100; // 静态代码块什么时候执行? 类加载时执行 static{ System.out.println("i=" + i); // 这里可以访问i吗? 可以 } // 定义实例变量 int k = 111; // k变量是实例变量,在构造方法执行时内存空间才会开辟 static{ System.out.println("k="+k); //k变量可以访问吗? 不可以 /* static静态代码块是在类加载时执行,并且只执行一次 类加载时,k变量空间还没有开辟出来 所以会报错:无法从静态上下文中引用非静态变量k */ System.out.println("name=" + name); // 这里可以访问name吗? 不可以 /* 报错:非法前向引用 静态代码块和静态变量都是在类加载的时候执行,时间相同,只能靠代码顺序来决定谁先谁后 */ } static String name = "lihua"; }
-
总结:到目前为止,遇到所有的java程序,有顺序要求的是哪些?
- 对于一个方法来说,方法体中的代码是有顺序的,遵循自上而下的顺序执行
- 静态代码块1 和静态代码块2 是有先后顺序的
- 静态代码块和静态变量是有先后顺序的