zoukankan      html  css  js  c++  java
  • java变量与内存深入了解

    =========================================================================================

        在我看来,学习java最重要是要理解what(这东西是什么),why(为什么要用它),where(在哪用它),how(怎么用)。所以接下来,我都是以这样的思想来和大家交流,从最基础的知识讲起。如果有啥出错的,欢迎大家前来批评。本人虚心接纳。

    =========================================================================================

    一.前言

             对于变量,我们再熟悉不过了,谁都知道声明一个变量,赋值。其实一直以来,变量也并不简单,我们很少系统地整理分类,更少研究变量对应的储存结构,这次就深入地了解一下变量,以及常量。

    二.What(什么是变量,先从变量说起)

             1.变量的简单定义:通俗来说,变量就是可以被改变的数据。在程序中声明变量的语法格式如下: 数据类型 变量名称= 值  例如:int x= 1,数据类型定义这个变量是什么类型的(有整型,浮点型等),变量名称只是个别名,值就是对应的数据。

             2.变量的深入定义:由上面可知,变量就是一个可改变的数据,既然是数据,在计算机中肯定有对应的存储空间来存储这个数据。也就是说,变量其实就是内存中的一个存储空间,用来存储数据。那这么说,声明一个变量,也就是相当于变量空间的开辟,那么,变量的深入定义还对应上面简单定义哪些呢?

                (1).声明一个变量=变量空间的开辟

                (2).变量的数据类型=这个空间要存储什么数据?

                (3).变量名称=这个空间叫什么名字?

                (4).变量的值=这个空间的第一次数据是什么?

        那么, 这些变量空间究竟在哪里呢?其实这些变量空间对应计算机内存的堆栈,下面会详细讲解。

             3.变量的分类

                (1).按声明的位置来分类:

                       a.成员变量:声明在方法之外的变量,不过没有 static 修饰。可以不设值,因为有默认值(下面数据类型会有默认值)

                       b.局部变量:声明在类的方法中的变量。必须对其初始化,否则编译不过。

                       c.类变量:声明在方法之外的变量,用 static 修饰

                (2).按数据类型划分(也就是定义数据是什么类型)

                       a.基本数据类型:

                           byte:在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0

                           short:短整型,在内存中占16位,即2个字节,取值范围-32768~32717,默认值0

                           int:整型,用于存储整数,在内在中占32位,即4个字节,取值范围-2147483648~2147483647,默认值0

                           long:长整型,在内存中占64位,即8个字节-2^63~2^63-1,默认值0L

                           float:浮点型,在内存中占32位,即4个字节,用于存储带小数点的数字(与double的区别在于float类型有效小数点只有6~7位),默认值0

                           double:双精度浮点型,用于存储带有小数点的数字,在内存中占64位,即8个字节,默认值0

                           char:字符型,用于存储单个字符,占16位,即2个字节,取值范围0~65535,默认值为空

                           boolean:布尔类型,占1个字节,用于判断真或假(仅有两个值,即true、false),默认值false

                       注意:整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。                

                            转换从低级到高级:byte,short,char—> int —> long—> float —> double

                             (1).强制类型转换: 转换过程中可能导致溢出或损失精度

                                     

                                   

                             (2).自动类型转换:必须满足转换前的数据类型的位数要低于转换后的数据类型,例如: short数据类型的位数为16位,就可以自动转换位数为32的int类型,同样float   数据类型的位数为32,可以自动转换为64位的double类型。       

                             (3).float和double区别:默认的浮点数都是double 只有在数组后边加上f才是 float的,float f=12.2f;这是定义一个float类型的数据 

                     b.引用数据类型: 除了8中基本类型以外剩下的都是引用类型(类,接口,数组等,后面详细介绍,new的是引用类型)

                          String:一定要注意,string是引用类型,不是基本类型。

              那么,就有人问了,基本类型和引用类型有啥区别,啥是引用类型,这就有很大学问了,顺便也扯上了变量内存结构了。

                 (3).详细讲解基本类型和引用类型的区别以及两者在内存的存储位置

                      a.上面说过了变量声明就是一个内存空间的开辟,那这些内存空间在哪呢?

                              首先了解一下java内存结构:JVM分了5片内存:

                              1.程序计数器:记录程序执行到哪一个指令

                              2.本地方法栈:与虚拟机栈功能相似,不过虚拟机栈为java方法服务,本地方法栈为Native方法服务

                              3.方法区:存放字节码,常量 ,静态变量,是一个共享的区域

                              4.虚拟机栈:执行方法其实就是栈帧入栈,出栈的过程,因为是跟方法有关的,而且局部变量常常在方法中,所以栈存储的是局部变量

                   

                              5.堆:存放引用类型,成员变量

      注意:(1).我们接触最多的是堆和栈(虚拟机栈),这里一定要注意这两个的区别。

              (2).栈主要是存储方法帧的,每执行一个方法的时候,就会为该方法创建一个栈帧,使其入栈。然而局部变量一般随着方法生成而存在,所以局部变量存储在栈中。

             (3).堆一般用来存放引用型对象,以及对应的成员变量,当对象创建时,会在堆中开辟一块地址,并给这个对象的成员变量使用。

                       b.基本类型没什么好说的,就是一个空间存储数.但注意:很多网上教程会说,基本类型是存在栈中,这是错误的,因为基本类型也分成员变量和局部变量,局部变量随着方法入栈就存在栈中,而成员变量会随着对象在堆中空间的开辟而存储在堆中。例如: int[] a=new int[]{1,2}; 由于new了一个对象,所以new int[]{1,2}这个对象时存储在堆中的,也就是说1,2这两个基本数据类型是存储在堆中。

                       c.引用类型就比较特别,引用类型占用两块内存,一个栈,一个堆, 栈中存放的是堆中的地址。啥意思?什么是引用类型?举个简单例子,一间房子,我可以在里面 放置家具,放完后用钥匙锁着,把钥匙放在抽屉里面,那我想找某个家具是不是通过钥匙来找到房间再进去找家具。从这个例子我们可以对应一下,房间就是内存开辟的空间,家具就是数 据,钥匙就相当于引用类型(堆中的地址),抽屉相当于,具体的数据放在堆上,引用类型放在栈上。例如:String s=new String("hello world"),new出来的hello world是存放在堆中,并且将这个堆地址给栈中s来保存。

                    

           (4).变量的作用域:

                      a.从定义上说,变量作用域到大括号结束,出了大括号就就不存在了

                      b.从内存上解释,一个类中什么时候有大括号的存在?只有两种情况,一个是类两端有大括号,例如:public class Person{},还有是类里面的方法有大括号,例如:public void a(){}。先说类里面的方法,上面也说了,执行完这个函数就相当于出栈,那么局部变量也当然随着函数的结束而销毁,大括号等同于这个类或方法已经执行完了,也就是说作用域只在大括号内,出了大括号就意味着函数结束了,也就是出栈了,变量作用域就无效了。同理,类两端里面是全局变量,执行到大括号也就是类被释放了,对应的全局变量也没了。

           (5).举个例子说明一下

               

     

             

               上面方法执行流程为:

                       1.main方法的栈帧入栈,在main的帧当中有一个a= 20;

                       2.当执行show(a)时,此时传入了一个参数a= 20;执行show方法,show方法的栈帧入栈,第一次打印结果为a= 20,a改为50,再次打印 结果为:a = 50;

                       3.当执行完show方法后,show方法的栈帧就会出栈;

                       4.此时栈中只有一个main方法的栈帧,所以在执行完show方法后,再去打印a ,此时a = 20;

       三.总结

               1.这篇文章更多是强调变量对应的内存关系,详细了解堆栈,一定要明确好关系。

                2.引用型基本上都是new出来的,string特别点,引用型new出来的内容放在堆上,地址存放在栈上。

                3.基本类型也分成员变量和局部变量,局部变量随着方法入栈就存在栈中,而成员变量会随着对象在堆中空间的开辟而存储在堆中。

                4.局部变量是存储在栈中,成员变量是存放在堆中(因为随着类的创建生成,类创建是在堆上)。

    ===========================================================================

          用心查阅,有心分享,分享之际,互相指教,受益你我,何乐不为?

     ===========================================================================

  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/pla1949/p/7834351.html
Copyright © 2011-2022 走看看