zoukankan      html  css  js  c++  java
  • 4.3 成员变量和局部变量

    一、定义

    成员变量指的是在类里面定义的变量,也就是前面所说的field;局部变量指的是在方法里定义的变量。
    Java程序里的变量划分为如图所示:

    1.1 成员变量

    成员变量可以不用初始化,系统会为它分配默认初始值。初始化规则与数组初始化规则相同。
    成员变量分为类变量和实例变量两种,定义成员变量时,有static修饰的是类变量,类变量从该类准备阶段起开始存在,知道系统完全销毁这个类,类的作用域与这个类的生存范围相同;无static修饰的是实例变量,实例变量则从该类的实例被创建起开始存在,直到系统完全销毁这个类,实例变量的作用域与对于实例的生存范围相同。
    只要类存在,程序就可以访问类变量,访问类变量的语法格式:

    类名.类变量
    

    只要实例存在,程序就可以访问实例变量,访问实例变量的语法格式:

    实例.实例变量
    

    注意:类变量也可以用该类的实例来访问,但实质上还是通过该类来访问类变量,语法格式:

    实例.类变量
    

    既是说通过一个实例来修改了类变量的值,由于这个类变量并不属于它,而是属于对于的类。因此修改的仍然是类变量,与通过该类来修改类变量完全相同,这也会导致通过其他实例来访问这个类变量也是被修改的值。

    class FieldTest 
    {
    	//定义一个类变量
    	public static String name;
    	//定义一个实例变量
    	public int a;
    
    	public static void main(String[] args) 
    	{
    		//定义两个FieldTest类的实例
    		var p1=new FieldTest();
    		var p2=new FieldTest();
    
    		//访问类变量name;:系统分配默认初始值null
    		System.out.println(FieldTest.name);
    		//下面通过实例方式访问类变量,实质也是通过类来访问
    		System.out.println(p1.name);
    
    		//通过实例p1来修改类变量和实例变量
    		p1.name="Java";
    		p1.a=10;
    
    		//通过实例p1访问类变量和实例变量
    		System.out.println(p1.name);
    		System.out.println(p1.a);
    
    		//通过实例p2访问类变量和实例变量
    		System.out.println(p2.name);//类变量已经被p1进行修改
    		System.out.println(p2.a);
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    null
    null
    Java
    10
    Java
    0
    
    输出完成 (耗时 0 秒) - 正常终止
    

    从上面可以发现:类变量的作用域比实例变量的作用域大。实例变量也可以访问类变量,同一个类的所有实例变量访问类变量时,实际上都是访问的该类的同一个变量。在以后的编程中,对于static修饰的类变量,最好用类来访问,增加程序的可读性

    1.2 局部变量

    与成员变量不同的是,局部变量除形参以外,必须进行显示初始化,也就是说,必须先给方法局部变量和代码块局部变量指定初始值,否则不可以访问它。局部变量分为三种
    1、形参:在定义方法签名时定义的变量,形参的作用域在整个方法内有效。
    2、方法局部变量:在方法体内定义的局部变量,它的作用域是从定义该变量的地方生效,到该方法结束时失效。
    3、代码块内的局部变量:在代码块定义的局部变量,这个局部变量的作用域从定义改变了的地方生效,到代码块结束的地方失效。

    {
    	public static void main(String[] args) 
    	{
    		{
    			//定义一个代码块局部变量
    			int a;
    			//下面代码将出现错误,因为变量a还未初始化
    			//System.out.println("代码块局部变量a:"+a);
    			//BlockTest.java:9: 错误: 可能尚未初始化变量a
    			a=5;
    			System.out.println("代码块局部变量a:"+a);
    		}
    
    		//在代码块外访问变量a是不存在的,超出了代码块局部变量a的作用域
    		//System.out.println(a);
    		//BlockTest.java:16: 错误: 找不到符号
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    代码块局部变量a:5
    
    输出完成 (耗时 0 秒) - 正常终止
    

    Java允许局部变量和成员变量同名,如果方法里的局部变量与成员变量同名,局部变量会覆盖成员变量,如果需要在这个方法里引用被覆盖的长远变量,则可以使用this(对于实例)或类名(对于类变量)作为调用者来访问成员变量。

    class  VariableOverrrideTest
    {
    	//定义一个name实例变量
    	private String name="U盘";
    	//定义一个price类变量
    	public static double price=55.0;
    
    	//定义普通方法
    	public void info()
    	{
    		//方法里的局部变量覆盖成员变量
    		var name="孙悟空";
    		//直接访问name变量,将输出name的局部值
    		System.out.println(name);
    
    		//使用this来输出name实例变量的值
    		System.out.println(this.name);
    	}
    	public static void main(String[] args) 
    	{
    		//方法里的局部变量会覆盖成员变量
    		var price=65.0;
    		//直接访问price变量,将输出局部变量的值
    		System.out.println(price);
    		//使用类名访问局部类变量
    		System.out.println(VariableOverrrideTest.price);
    		//运行info()
    		new VariableOverrrideTest().info();
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    65.0
    55.0
    孙悟空
    U盘
    
    输出完成 (耗时 0 秒) - 正常终止
    

    二、成员变量的初始化和内存中的运行机制

    当系统加载类或创建类的实例时,系统会为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值,初始值的规则与数组相同。

    public class  ProgramRun
    {
    	//这是一个类变量
    	public static int num;
    	//这是一个实例变量
    	public String name;
    	
    
    	public static void main(String[] args) 
    	{
    		//创建两个实例变量
    		var p1=new ProgramRun();
    		var p2=new ProgramRun();
    
    		//分别为两个Person对象的name变量赋值
    		p1.name="张三";
    		p2.name="孙悟空";
    		
    		p1.num=2;
    		System.out.println(p2.num);
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    2
    
    输出完成 (耗时 0 秒) - 正常终止
    

    (1)当程序执行到var p1=new ProgramRun();时,这行代码第一次使用Person类,则系统通常会在第一次使用Person类时加载这个类,并初始化这个类。系统为该类的类变量分配内存空间,并指定默认初始值。

    当ProgramRun类初始化完成后,系统会在堆内存中为类变量num分配一块内存区,并设置num的默认值0。
    (2)接着创建两个ProgramRun对象p1,p2,类里面包含了名为name的实例变量,实例变量在创建实例时分配内存空间并指定初始值的。

    (3)分别为两个Person对象的name变量赋值
    p1.name="张三";
    p2.name="孙悟空";

    (4)当执行到p1.num=2;时,此时通过ProgramRun对象来修改ProgramRun类的类变量,其实通过ProgramRun对象p1来访问类变量num,实质上还是通过类来访问,故通过对象p2来访问变量num,还是访问的同一块区域。

    三、局部变量的初始化和在内存中的运行机制

    局部变量定义后,必须经过显式的初始化后才能使用,系统不会为局部变量执行初始化,这意味着定义局部变量时,系统并未为其分配内存空间,知道等到程序为这个变量赋初始值时,系统才会为局部变量分配内存,并将初始值保存到这块内存中。
    局部变量不属于任何类或实例,因此它总是保存在栈内存中。栈内存中的变量无需系统垃圾回收,往往随方法或代码块的运行结束而结束。因此局部变量的作用域是从初始化该变量开始,知道该方法或代码块完成而结束。由于局部变量只保存基本类型或者对象的引用,因此局部变量所占的内存空间很小。

  • 相关阅读:
    JavaScript操作符instanceof揭秘
    Linux打开txt文件乱码的解决方法
    Working copy locked run svn cleanup not work
    poj 2299 UltraQuickSort 归并排序求解逆序对
    poj 2312 Battle City 优先队列+bfs 或 记忆化广搜
    poj2352 stars 树状数组
    poj 2286 The Rotation Game 迭代加深
    hdu 1800 Flying to the Mars
    poj 3038 Children of the Candy Corn bfs dfs
    hdu 1983 Kaitou Kid The Phantom Thief (2) DFS + BFS
  • 原文地址:https://www.cnblogs.com/weststar/p/12347859.html
Copyright © 2011-2022 走看看