Java内存、成员变量、局部变量

xiaoxiao2021-02-28  71

一 java内存分配 

Java 中的数据类型分为  1. 基本类型(原始数据类型) byte short int long float double char boolean  基本类型的变量持有原始值。  2. 复合数据类型(引用类型),引用类型持有引用值(即对某个对象的引用,而非对象本身)。

一般Java在内存分配时会涉及到以下区域:  1. 寄存器:我们在程序中无法控制  2. 栈:存放基本类型的数据和对象的引用但对象本身不存放在栈中,而是存放在堆中  3. 堆:存放用new产生的数据  4. 静态域:存放在对象中用static定义的静态成员  5. 常量池:存放常量  6. 非RAM存储:硬盘等永久存储空间  其中主要是堆,栈的存储。

堆,栈

函数中定义的一些基本类型的数据变量对象的引用变量都在函数的栈内存中分配。  栈的优势是存取速度比堆要快,仅次于直接位于CPU 的寄存器,而且数据可以共享。  存在栈中的数据大小与生存周期必须是确定的。因此里面的变量通常是局部变量、函数参数等。  当在一段代码块定义一个变量时(局部变量),Java就在栈中 为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆内存用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

在堆中产生了一个数组或对象后,还可以 在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。  引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序 运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍 然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。

栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。

堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

二 成员变量,局部变量

class A { int a;//成员变量 public static void main(String[] args) { //类变量 static int c; int b;//局部变量 } } 12345678910 12345678910

成员变量:作为类的成员而存在,直接存在于类中。

类变量:static 修饰,静态变量存储在方法区。

局部变量:方法内部,块内部都是局部,执行指令退出那个局部,局部变量自动清除。

1.成员变量可以被public,protect,private,static等修饰符修饰,而局部变量不能被控制修饰符及static修饰;两者都可以定义成final型

2.成员变量存储在堆,局部变量存储在栈

3.存在时间不同

4.成员变量有默认值,(被final修饰且没有static的必须显式赋值),局部变量不会自动赋值,局部变量在使用前必须被程序员主动的初始化,然后才能使用。

看下面对比成员变量局部变量:

public class Variable { int i; void test() { int j=8; if(j==i) System.out.println("相等"); else System.out.println("不相等"); } public static void main(String[] args) { Variable v=new Variable(); v.test(); } } 1234567891011121314 1234567891011121314

程序二:

public class Variable { void test() { int i; int j=8; //这里 i 被使用了,但是还没有赋值,所以报错 if(j==i) System.out.println("相等"); else System.out.println("不相等"); } public static void main(String[] args) { Variable v=new Variable(); v.test(); } } 12345678910111213141516 12345678910111213141516

第一个程序很正常,编译时不会出错。第二个程序编译时会错误,因为局部变量没有初始化。成员变量有默认值,(被final修饰且没有static的必须显式赋值),局部变量不会自动赋值

public static int transeInt(String s){ //digit不会报错,result 会报错 int digit; int result; if(s.length()==0||s==null) System.out.println("错误字符串"); for(int i=0;i<s.length();i++){ //这里digit被显示的赋值了(所以不一定是创建之后就被赋值) digit = s.charAt(i)-'0'; //result*10 还未被赋值就被使用了,所以报错 result = result*10+digit; } return result; }
转载请注明原文地址: https://www.6miu.com/read-42346.html

最新回复(0)