面试题:静态变量、实例变量、局部变量与线程安全 背1
静态变量:线程非安全。
加static关键字的变量,只能放在类里,不能放到方法里。
静态变量有默认初始化值。 成员变量也有初始化值 局部变量没有
静态变量表示所有实例共享的一个属性,位于方法区,共享一份内存,而成员变量是对象的特殊描述,不同对象的实例变量被分配在不同的内存空间,一旦静态变量被修改,其他对象均对修改可见,故线程非安全。
实例变量:单例模式(只有一个对象实例存在)线程非安全,非单例线程安全。
成员变量(实例变量):
1、成员变量定义在类中,即类中的普通变量,在整个类中都可以被类中方法所访问(如过和局部变量重名,需用this关键字)。
2、成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中。
3、成员变量有默认初始化值
实例变量为对象实例私有,在虚拟机的堆中分配,若在系统中只存在一个此对象的实例,在多线程环境下,被某个线程修改后,其他线程对修改均可见,故线程非安全;如果每个线程执行都是在不同的对象中,那对象与对象之间的实例变 量的修改将互不影响,故线程安全。
成员变量和类变量的区别:
1、两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失,且优先于对象存在。
2、调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3、数据存储位置不同
成员变量存储在堆内存的对象中,是对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区
static还可以修饰方法,静态方法只能访问静态变量,不可以访问成员变量,因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。同时静态方法中不能使用this,super关键字,因为this代表当前对象,而静态方法在时,有可能没有对象,所以this无法使用。
局部变量:线程安全。
1、局部变量只定义在局部范围内,如:函数内,for循环语句内等,只在所属的区域有效。
2、局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。
3、局部变量没有默认初始化值
4、在使用变量时需要遵循的原则为:就近原则,先找局部变量,再找实例变量(如果同名,实例变量需要用this关键字引用)
5、局部变量不能逐级重名,比如函数内定义过一个变量,就不能在for循环内定义相同的变量(两层for循环一个用i一个用j也是这个道理)
由于每个线程执行时将会把局部变量放在各自栈帧的工作内存中,线程间不共享,故不存在线程安全问题。