成员变量和局部变量及运行机制
两者的区别在于定义变量的位置不同,运行的机制也有差异。成员变量定义在类中,局部变量定义在定义在方法中。
成员变量分为类变量和实例变量两种,局部变量分为形参(方法内)、方法局部变量和代码块内局部变量,比如循环内的。
类变量的生命周期和类一样,从类准备阶段开始,到完全销毁这个类,作用域则与类的生存范围相同。而实例变量从实例被创建起开始存在,直到实例被销毁,作用域对应实例作用域。可以发现,成员变量之所以称为成员变量
,是因为其与所在的整体共存亡的。
注意:类变量是属于类的,通过
实例.类变量
访问的依然是类变量,如果该实例修改了变量值,则其他实例访问时也将使用修改过的变量值。即访问了同一片内存区!
与成员变量不同,局部变量除了形参外,都必须显式初始化;而上面的成员变量可以进行默认初始化,赋值规则与数组动态初始化时赋值规则相同。
当通过类或对象调用某个方法时,系统1会在调用该方法栈区内为所有形参分配内存,并将实参值赋值给对应形参,即完成形参初始化。
Java允许局部变量和成员变量同名,如果需要在方法内引用被覆盖的成员变量(局部变量和成员变量同名),可以使用this
关键字。
1 | public class Test{ |
成员、局部变量初始化及运行机制
在类初始化或对象初始化时,系统会为成员变量分配内存空间,并指定默认初始值。需要关注的是,在创建一个对象时,不需要给类变量分配内存空间,只是为实例变量分配内存空间,因为类初始化时已经分配好了。在创建多个对象时,同样如此,也需要为实例变量分配内存空间,而且,实例变量是单个实例的,与类或其他实例无关。
局部变量定义后,必须经过显式初始化后才能使用,系统不会为局部变量执行初始化,就不会为变量分配内存空间,直到变量被初始化。与成员变量不同,局部变量不属于任何实例或类,因此它被保存在所在的方法栈中。如果变量是基本类型的变量,则会把值直接保存在对应内存中;但是变量是引用类型
,则它存放的是地址,地址是所引用的对象或数组的地址。
局部变量的生命周期是和方法或代码块一致,但所在栈内存无需垃圾回收,因为局部变量只保存基本类型的值或引用,所以所占内存比较小。
包装类
基本数据类型不具备对象特性:无成员变量,方法被调用。但有些时候显得不那么好,比如方法需要object
类型的参数,并且需要提供实际值,像2,3,4,这就麻烦了。Java提供了包装类概念,并为8种基本数据类型定义了引用类型(基本数据类型的包装类)。
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
上述除Character
外,其他包装类可传入参数创建一个包装类对象,
由于基本数据类型和包装类对象之间转换麻烦,JDK1.5提供了自动装箱和拆箱功能,去解决该问题。
自动装箱:基本类型变量赋值给包装类(或者Object变量);自动拆箱:包装类对象赋值给基本类型变量
1 | Integer a = 5;//基本类型赋值给Integer对象 |
虽然包装类是引用类型,但是实例是可以与数值比较的,比较时直接取出包装类的值进行比较。而包装类对象之间比较,只有指向同一对象时返回true。
1 | System.out.println(new Integer(1) == new Integer(1));//false |
从上面来看,系统将整数装箱成实例,会放入一个cache
数组(长度为256,Java就是这样设计的)中缓存起来,以后如需自动装箱则直接指向数组元素(若在-128~127之间),即引用同一个实例对象。这样的缓存设计有利程序的运行性能,节省开销。
字符串与基本类型的转换
字符串转基本类型有两种方式:
- 包装类的parseXxx(String s)方法(除了Character包装类外)
- 对应的构造器方法,Xxx(String s)
基本类型转字符串则使用String
的多个重载valueOf
方法。上述代码示例:
1 | String str = "123"; |
Java7、8增强包装类
Java7开始为所有包装类提供静态的compare(v1,v2)
方法,则可以通过该方法比较基本值的大小。比如:
1 | System.out.println(Boolean.compare(true,false));//1 |
Java8再次增强,开始支持无符号算术运算。如为Integer、Long增强了静态的toUnsignedString(int/long v)整型转化成无符号整数对应的字符串、toUnsignedString(int/long v,int radix)转化成指定进制无符号整数对应的字符串。
无符号整数的二进制最高位不再当作符号位看,即最小值为0。例如-2,对应的无符号整数为252