java 引用数据类型变量

时间:2019-04-29 03:17:55  来源:igfitidea点击:

在这篇文章中,它描述了面向对象编程的一个重要概念:每个类实例,对象只由引用类型变量管理(对于那些也知道C++的人,你可以记住C++中的这个规则并不完全正确,因为对象也由值类型变量管理)。

这个规则对于理解是非常重要的,因为它是定义面向对象编程语言(C# )的一个基本事实。理解它,将理解和学习Java编程。

什么是引用数据类型变量

引用变量,或者说引用(Reference),是变量(就像一个原始数据类型,比如int vb),因为它们需要内存空间来存储它们的值。引用变量和基元数据类型变量之间的主要区别在于,第一个变量的值是表示堆中内存区域的地址(主要是地址)的数字。

当进程启动(应用程序)时,它需要活动内存(随机访问内存)来存储数据、代码和堆栈(一个固定的临时缓冲区,供将来使用)。JVM(Java虚拟机)根据运行前(基于源代码中定义的变量)和应用程序执行期间可以确定的内容为其保留内存空间。

因此,该进程管理并需要两个数据存储区:

stack栈——固定大小的栈;它的大小是根据函数执行前可用的信息来确定的(记住,最简单的Java应用程序需要一个函数——main);这个信息是由函数局部变量和输入变量(对于main,其局部变量实际上是应用变量;

Heap堆——动态的,它表示运行时需要或不需要的数据的内存需求;你不确定你是否需要它,以及它的大小,因为它取决于应用程序的执行和其他外部输入(假设我们有一个应用程序记录数组的值,但是它的大小和值是由用户在运行时给定的;因此我们知道应用程序将需要一些额外的内存空间,但我们不知道有多少字节,因为我们不知道用户将插入什么);为了保留这个空间,在运行时,我们将使用new运算符或函数;堆也称为动态管理的内存,因为它响应来自不同进程的内存请求,并在不再需要时释放使用过的内存。

下面是一个生成数组的示例,该数组的长度由用户在运行时给定:

try

      {

      int[] intValues;

      int num = 0;

      System.out.println("请输入数组大小 (0 - 255):");

	// 输入数组值

      num = System.in.read();

      intValues = new int[num];

	// 打印数组值 - 默认全部是0

      for(int i=0; i < intValues.length; i++)

          System.out.print(" "+intValues[i]);

      }

      catch(IOException ex){

          System.out.println(ex.getMessage());

      }

关于变量在内存中的位置的一般规则是:

  1. 在函数块中声明的变量(在Java中不能像C或C++那样声明全局变量,)或参数列表中的变量被放置在堆栈(函数栈)上;

  2. 使用new运算符创建的任何值都将放在堆中。

不要忘记在Java中,任何数组都是一个对象。数组引用在栈上,其值在堆中

java-7-reference-data-type-variables

如何定义引用数据类型变量

定义引用的语法为:

class_name reference_name;

每次定义引用时,如果它不是本地变量(默认值为没有地址的预定义值),则它的默认值等于*NULL**;在C/C++中,空值等于0。这意味着它不能被使用。

如果引用是一个局部变量(而不是实例变量-属性),那么我们将收到一个编译器错误。

如果我们考虑这个类

class Auto{

  int maxSpeed;

  float weight;

  int noSeats;

}

然后测试它,我们会得到一个 变量auto可能没有初始化 (variable auto might not have been initialized)编译器错误,如果我们尝试这个

public class TestAuto {

  public static void main(String[] args) {

      //定义局部变量/引用

      // 局部变量没有使用缺省值进行初始化

      Auto auto;          //编译错误

      auto.maxSpeed = 160;

  }

}

将运行时异常 java.lang.NullPointerException(因为对象不存在,并且没有存储160值的内存空间):

如何初始化引用数据类型变量

所有引用都是以地址(数字)作为值的变量。为了得到一个地址,我们必须请求并在堆中保留一些内存(仅在这里)。使用 new运算符完成此操作,如下所示:

reference_type reference=new reference_type(); // 如果是对象

base_type array_reference= new base_type[elements_number]; // 如果是数组

如果我们考虑这个Java示例:

public class TestAuto {

  public static void main(String[] args) {

      //定义一个Auto引用

      // 进行初始化

      Auto auto = new Auto();

      //初始化对象值

      auto.maxSpeed = 160;

      auto.noSeats = 5;

      auto.weight = 1500;

      //定义并初始化数组引用

      int[] someInts = new int[3];

      someInts[0] = 10;

      someInts[1] = 20;

      someInts[2] = 30;

  }

}

那么它在内存中看起来是这样的:

java-7-reference-data-type-variables

对象值及其引用的内存映像

注意当我们在两个引用之间使用=(相等)时,右引用的值将复制到左引用中。重要的是要理解复制的是引用值,而不是堆中的对象或数组值。这种类型的拷贝称为 浅拷贝

例如,如果我们在初始情况中添加一些指令(前一个示例)

Auto newAuto = auto;

int[] otherInts = someInts;

由两个引用管理的对象值

在内存中,主函数栈上有4个引用,堆中只有2个值(一个对象和一个数组)。在这种情况下,我们可以通过具有相同值的两个不同引用访问对象值:

java-7-reference-data-type-variables