浅谈Java中的变量

时间:2022-08-31 01:48:38

摘要:本文主要讨论了Java中的变量在使用时应注意的四个方面问题以及这些因素对变量影响。同时探讨了这些因素在Java虚拟机中的实现机制和变量在内存中的存储位置。

关键词:变量 成员变量 局部变量 Java虚拟机 变量内存布局 栈 堆 方法区

中图分类号:TP3 文献标识码:A 文章编号:1007-9416(2012)06-0204-02

变量是指数值可以改变的数据。与数学中的变量不同,在计算机程序设计语言中的引入变量实质是对一个或几个存储单元的抽象,这样对存储单元的操作可以转化为对变量的操作。变量在程序中用名字来标识。根据变量在程序中出现的位置和作用的不同,变量会有不同的称呼。

1、Java语言中使用变量时应注意的几个方面

1.1 类型

变量的类型决定了变量的数据性质、范围、可以进行的合法操作以及变量存储在内存中所占的空间(字节数)等。

Java语言有两种类型,基本类型和引用类型。基本类型包括整型(byte、short、int、long)浮点型(float、double)、字符型、布尔型。引用类型包括类、接口、数组等。

各类型数据进行混合运算时按byte、short、charintlongfloatdouble从低到高自动转换,但由高到低转换时须强制进行。有继承关系对象间的类型可以转换,子类转换为父类时可自动或强制进行,但父类转化成子类必须强制进行。

1.2 作用域

作用域是指可访问该变量的范围,即一个变量在多大范围内可以使用。Java语言根据变量作用域的不同常分为成员变量和局部变量。

成员变量包括类变量(静态变量)和实例变量,类变量作用域属于整个类,实例变量的作用域属于整个实例。在继承过程中子类新增变量与父类中原有变量同名时,作用域默认为子类,可通过super访问父类。Java语言对成员变量出于封装和安全性的考虑会通过public、protected、默认、private四种方式限制对变量的访问。

局部变量是指在方法中或语句块中声明的变量,局部变量只能在所在的方法或语句块中起作用。方法的形参也是局部变量的一种。当局部变量与成员变量同名时,在局部变量的作用域内成员变量被隐藏,如需使用成员变量必须用this指明。

1.3 值

基本类型数据的值直接存储于变量名所代表的存储空间中。引用数据类型变量所代表的存储空间的值是指针,它指向实例化后的对象,通过new运算实现。

对于对成员变量来讲,类变量属于该类对应的所有实例,它们共享它;而实例变量则属于对应实例。类变量使用时机可通过“类名.变量名”访问,也可通过“对象名.变量名”。但对于实例变量只能通过“对象名.变量名”来访问。Java语言中进行赋值操作或函数调用中传递参数时遵循值传递原则,对基本类型而言传递的值就是真正的信息本身,对引用类型的参数来说传递的是地址(句柄),而非对象的全部信息。

Java变量不但要先声明,还必须被初始化后才可以使用。成员变量在其所属对象创建之际就被系统默认初始化,如果需要的话还可以显示的初始化或通过构造函数对成员变量进行初始化。局部变量则没有默认初始化机制,必须在定义之初即进行初始化。用final声明的成员变量初始化后,不能被重新赋值或修改。

1.4 生存期

一个存储区绑定于一个变量的时间区间成为变量的生存期。方法里的局部变量在方法调用完就销毁,实例变量在类的相应的对象销毁时销毁,类变量随类的结束而结束。

Java中对象的清除是由系统自动完成的,因此实例变量随对象的清除而清除。但如果多个引用变量指向一个对象,这是变量的生存期可能会有变化。

2、Java变量在内存的布局

2.1 Java虚拟机运行时的数据区域

Java虚拟机在运行时会把它管理的内存划分成若干个不同的区域,这些区域都有各自的用处,以及创建和销毁的时间。有的区域随着虚拟机进程的启动而存在,有的区域依赖用户线程的启动和结束而建立和销毁。Java虚拟机运行时包括以下几个数据区域。

(1)程序计数器(program counter register);它是一块较小的内存空间,它的作用是当前线程所执行的字节码的行号指示器。字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。每个线程都需要一个独立的程序计数器,保证线程被切换后下次执行时能恢复到正确的执行位置。

(2)栈(stack);与程序计数器一样,栈也是线程私有的,生命周期与线程相同。位于通用RAM中,但通过它的“堆栈指针”可以从处理器哪里获得支持。堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建线程的时候,JAVA解释器必须知道存储在栈内所有数据的确切大小和生命周期,因为它必须生成相应的代码,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些JAVA数据存储在栈中——特别是对象引用,但是JAVA对象不存储其中。

(3)堆(heap);堆是Java虚拟机所管理的内存中最大的一块区域,被所有线程所共享,在虚拟机启动时创建。创建队的主要目的是存放对象实例。堆不同于堆栈的好处是:解释器不需要知道要从堆里分配多少存储区域,也不必知道存储的数据在堆里存活多长时间。因此,在堆里分配存储有很大的灵活性。当你需要创建一个对象的时候,只需要new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。堆是垃圾收集器管理的主要区域。

(4)方法区(method area);Java方法区与Java堆一样是各个线程共享的内存区域。它用于存储已被虚拟机记载的类信息、常量、静态变量、方法代码(编译后的java代码)。在当前的Java实现中,方法代码不包括在垃圾回收堆中,但计划在将来的版本中实现。每个类文件包含了一个Java类或一个Java界面的编译后的代码。可以说类文件是Java语言的执行代码文件。为了保证类文件的平台无关性,Java虚拟机规范中对类文件的格式也作了详细的说明。

(5)本地方法栈(nativa method stack);本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java服务,而本地方法栈则视为虚拟机使用到的native方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构没有强制的规定,因此具体的虚拟机可以自由的实现它。

2.2 变量的存储与访问机制

(1)局部变量的存储与访问;当线程调用一个方法时,每个被执行的方法都会同时创建一个栈帧(stack frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。而这所有的工作都是在Java虚拟机的栈中完成的。

(2)对象的存储与访问;假设有下面的代码:object obj=new object( );出现在方法体中。引用类型变量obj将出现在Java栈帧的局部变量表中。newobject( )将在堆中开辟一块区域存储实例化的object类型数据,并将这块内存的首地址赋值给obj,同时还要在堆内形成指向方法区用来保存此对象类型数据的指针,指向方法区存储对象类型数据区域。方法区的对象类型数据应包括类变量、方法、对象类型、父类、实现接口等信息。通过这些机制保证了对成员变量的访问和有继承关系的对象的类型转换实现。由此可见,对象的存储与访问涉及到了栈、堆、方法区三个重要的Java虚拟机运行时的数据区域。

参考文献

[1]周志明.深入理解Java虚拟机:JVM高级特性与最佳实践.机械工业出版社.

[2]朱庆生,古平.Java语言程序设计.清华大学出版社.

上一篇:全台网建设中数据安全的思考 下一篇:Oracle数据库应用系统性能优化问题探讨