概念理解
1、成员变量之一:类变量(静态变量)概念:
类变量也叫静态变量,是类中独立于方法之外的变量,用static修饰(static [ 全局的、静态的 ] 是静态修饰符,用来修饰成员变量和成员方法,或静态代码块 [ 静态代码块独立于类成员,JVM加载类时会执行静态代码块,每个代码块只执行一次,按顺序执行 ])。属于成员变量。这类变量一旦赋值,在任何new创建出来的实例中都具有相同的值。
2、成员变量之二:实例变量概念:
实例变量,也是独立于方法之外的变量,只不过没有static修饰。每一个new出来的新实例都可以对他赋予自己需要的值。
3、局部变量概念:
局部变量时类方法中的变量。
代码理解:
<span style="font-size:12px;"><span style="font-size:12px;"></span></span><span style="font-size:12px;"><pre name="code" class="java">public class VairableLearn{
static int ClassVairable = 0; //类中独立于方法之外的变量,有static修饰符,即类变量,作用域在类域中,即从类的开始到回收。存储在方法区中的静态区
String StrVarirable = "HelloWorld !";//类中独立于方法之外的变量,无static修饰符,即成员变量或实例变量,作用域在类域中,即从类的开始到回收。对象存储在堆,引用存储在栈。
public static void main(String[] args){
int a = 0;//在类方法之中的变量,即局部变量,作用域在类方法域中,即从方法的声明到方法的结束。存储在栈中。
}</span>
不同变量的内存分配:
Java程序运行时的内存结构分为:
1、方法区;
2、栈内存;
3、堆内存;
4、本地方法栈。
- -方法区- -
方法区是系统分配的一个内存逻辑区域,是JVM在装载类文件时,用于存储类型信息(类的描述信息)。存放的信息主要包括:
1、类的基本信息:全限定名、直接父类的全限定名、是类还是接口、访问修饰符,直接父接口的全限定名的有序列表。
2、已装载类的详细信息:
- 运行时常量池:在方法区中,每个类型都对应一个常量池,存放该类型所用到的所有常量,常量池中存储了诸如文字字符串、final变量值、类名和方法名常量。他们以数组的形式通过索引被访问,是外部调用与类型对象话的桥梁(存的可能是个普通的字符串,然后经过常量池的解析,则变成指向某个类的引用)。
- 字段信息:字段信息存放类中声明的每个字段的信息,包括字段的名、类型、修饰符。字段名称指的是类或接口的实例变量或类变量;字段的描述符是一个指示字段的类型的字符串,如private A a = null ; 则 a 为字段名,A为描述符,private为修饰符。
- 方法信息:类中声明的每个方法的信息,包括方法名,返回值类型,参数类型,修饰符,异常,方法的字节码(在编译的时候,就已经将方法的局部变量、操作栈数大小等确定并存放在字节码中,在装载的时候,随着类一起装入方法区)。
- 到类classloader的引用:到该类的类装载器的引用
3、静态变量:就是类变量,类的所有实例都共享,我们只需要知道,在方法区有个静态区,静态区专门存放静态变量和静态块。
4、到类class的引用:虚拟机为每个被装载的类创建一个class实例,用来代表这个被装载的类。
5、到类classloader的引用:到该类的类装载器的引用
- -Java栈- -
JVM栈是程序运行时单位,决定了程序如何执行,或者说数据如何处理。
在Java中,一个线程就会有一个线程的JVM栈与之对应,因为不同的线程执行逻辑显然不同,因此都需要一个独立的JVM栈来存放该线程的执行逻辑。
对方法的调用:Java栈内存,以帧的形式存放本地方法的调用状态,包括方法调用的参数、局部变量、中间结果等(方法都是以方法帧的形式存放在方法区的),每调用一个方法就将对应该方法的方法帧压入Java栈,成为当前方法帧。当调用结束(返回)时,就弹出该帧。
这意味着:在方法中定义的一些基本类型的变量和引用变量都在方法的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后(方法执行完成后),Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作它用。--------同时,因为变量被释放,该变量对应的对象,也就失去了引用,也就变成了可以被gc对象回收的垃圾。
因此我们可以知道成员变量与局部变量的区别:
局部变量,在方法内部声明,当该方法运行完时,内存即被释放。
成员变量,只要该对象还在,哪怕某一个方法运行完了,还是存在。从系统的角度来说,声明局部变量有利于内存空间的更高效利用(方法运行完即回收)。成员变量可用于各个方法间进行数据共享。
Java 栈内存的组成:
1、局部变量区:局部变量区为一个以字为单位的数组,每个数组元素对应一个局部变量的 值。调用方法时,将方法的局部变量组成一个数组,通过索引来访问。若为非静态方法,则加入一个隐含的引用参数this,该参数指向调用这个方法的对象。而 静态方法则没有this参数。因此,对象无法调用静态方法。
2、操作数栈:操作数栈也是一个数组,但是通过栈操作来访问。所谓操作数是那些被指令操作的数据。当需要对参数操作时如a=b+c,就将即将被操作的参数压栈,如将b 和c 压栈,然后由操作指令将它们弹出,并执行操作。虚拟机将操作数栈作为工作区。
3、帧数据区组成:帧数据区处理常量池解析,异常处理等。
- -Java堆- -
Java的堆是一个运行时的数据区,用来存储数据的单元,存放通过new关键字新建的对象和数组,对象从中分配内存。
在堆中声明的对象,是不能直接访问的,必须通过在栈中声明的指向该引用的变量来调用。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。
- -本地方法栈- -
Java通过Java本地接口JNI(Java Native Interface)来调用其它语言编写的程序,在Java里面用native修饰符来描述一个方法是本地方法。