/*
1、static翻译为“静态”
2、所有static关键字修饰的都是类相关的,类级别的。
3、所有static修饰的,都是采用“类名.”的方式访问
4、static修饰的变量:静态变量
5、static修饰的方法:静态方法
变量的分类:
变量根据声明的位置进行划分:
在方法体当中声明的变量:局部变量
在方法体外声明的变量:成员变量
成员变量又可以分为:
实例变量
静态变量
(方法中不能定义静态变量。)
*/
class VarTest{
//以下实例的,都是对象相关的,访问时采用“引用.”的方式访问,需要先new对象。
//需要对象的参与即可访问,可能有空指针异常的发生
//成员变量中的实例变量
int i;
//实例方法
public void m2(){
}
//不需要对象的参与即可访问,没有空指针异常的发生
//以下静态的,都是类相关的,访问时采用“类名.的”的方式访问,不需要new对象。
static int k;
public static void m1(){
}
}
/*
成员变量什么时候声明为实例的,什么时候声明为静态的?
*/
public class StaticTest{
public static void main(String[] args){
Chinese c1=new Chinese("123456","张三","中国");
System.out.println("idCard="+c1.idCard);
System.out.println("name="+c1.name);
System.out.println("country="+c1.country);
}
}
class Chinese{
//身份证号
String idCard;//一个对象一份,每一个人的身份证不同,所以身份证号是实例变量
//姓名
String name;//姓名也是一个人一个姓名,也是实例变量
//国籍
String country="chinese";
//国籍都是中国,不会随着对象的改变而改变。
//无参数
public Chinese(){
}
//有参数
public Chinese(String s1,String s2,String s3){
idCard=s1;
name=s2;
country=s3;
}
}
//假如国籍声明为实例变量,内存图是什么样的
//假如国籍声明为静态变量,内存图是什么样的
国籍声明为实例变量,内存图是什么样的
首先,类加载器将StaticTest.class、Chinese.class、String.class加载到方法区中。
之后,main方法压栈,出现main方法栈帧。执行到new构造方法时,构造方法也会压栈,压栈后在堆中创建内存,并为其赋予默认值。(无参数,如果有参数则赋予值),指针指向这样的堆内存。
对于chinese这个类来说,中国人的国籍一定是中国,不会因为对象的变化而变化,显然是整个类的特征,不再属于某个对象。如果声明为实例变量,则会浪费内存。
国籍声明为静态变量,内存图是什么样的
不需要new对象(调用构造方法)就存在,而且在类加载时就存在
总结:静态变量存在方法区、实例变量存放在堆中、局部变量存在栈中。
访问静态变量和实例变量
实例变量通过引用.访问
静态变量通过类名.访问(也可以通过引用.的方式访问,而且就算引用是个空指针,也不会出现空指针异常)
如果这个类型的所有对象的某个属性值都是一样的,不建议定义为实例变量,浪费内存空间,建议定义为静态变量,在方法区中只保留一份节省内存开销。