Java语言(5)【类&对象】-引用、字面量、常量

一、什么是引用?

Java中创建变量,要么是基本数据类型变量、用于存储数值;要么是类变量、用于创建对象。这两种变量的机制在Java中是不同的。两者有何区别呢?

下文中用于创建对象的变量,我们称之为“引用”。

我们举例说明:

1)创建基本类型的变量和赋值

  int x = 42;
  int y = x;

  内存中的操作是:

  (1)为x分配内存空间(int是32bit),把此内存空间的二进制数据为表示42。

  (2)位y分配内存空间(int是32bit),刷新y的内存空间的二进制数据为与x相同的值(42)。

  最终内存效果如下。 x、y分别有不同的内存空间,只是其内存空间内表示的数值相等。

   

2)创建类对象和赋值

  Point p = new Point(1.0, 2.0);
  Point q = p;

  运行这段代码后,内存操作如下:

  (1)为p创建内存空间。

  (2)new关键字为Point类型对象创建内存空间(一般是堆内),保存对象内容。

  (3)p的内存空间内容指向Point类型对象的内存空间。(类似C语言中指针的概念,可能Java中引用的本质也是内存地址)

  (4)为q创建内存空间。把p中保存的指向Point类型对象的引用数据赋值到q的内存空间。此时q也指向Point类型对象。

  最终内存效果如下:

   

  JVM虚拟机中,仍然只有一个 Point 对象的副本,但是这个对象的引用有两个副本。

  变量p、q中内存实际对象实例之间是索引关系,所以称之为“引用” 。


二、基本数据类型变量和引用变量的使用区别

Java中的五种引用类型:数组、类、接口、枚举、注解

“对象”指应用类型的值或实例。

引用类型的对象、和基本类型的值有本质区别。

(1)基本类型是java内定的,用户不可新增。引用类型由用户定义。

(2)基本类型表示单个值,引用类型是聚合类型。可以包含0个或多个基本值或对象。

(3)基本类型需要1~8个字节的内存空间。把基本只存储到变量中,或出入方法时,计算机会复制表示这个值的字节。而对象基本上需要更多的内存,创建对象时会在heap(堆)动态分配内存,存储这个对象,如果不在需要这个对象了,存储它的内存会被自动垃圾回收机制回收。

1)赋值操作

  int x = 42;
  int y = x;
  基本数据类型变量赋值,是把变量内存空间刷新为赋的值。

  Point p = new Point();
  Point q = p;
  把对象赋值给引用变量,或者通过引用变量向引用变量赋值,不会复制这个对象实例的内存,而是把这个对象的引用存储在引用变量中。

2)方法入参、出参操作

  基本数据类型作为方法的入参、出参,本质上是变量在方法内、外分别有独立的内存空间。入参是把方法外变量内存空间的值 传递给 方法内变量内存空间,在方法内对变量的值的修改,不影响方法外变量的值。出参是把方法内变量内存空间的值 传递给 方法外变量内存空间的值。(这种方式称之为“值传递”)。

  引用类型作为方法的入参、出参。本质上是方法内、外有两个引用,但是两个引用指向的是同一对象空间。方法内对对象的修改,在方法外依然会体验。(类同与C语言中使用指针变量作为参数的方式)。

3)比较操作

  基本类型和引用类型相等性比较时也有区别。

  相等运算符(==)比较时:

  (1)如果比较的是基本数据类型对象,是测试两个对象的值是否一样(即每一bit的值都完全相同)。

  (2)如果比较多是引用对象,比较的是引用而不是真正的对 象。也就是说,== 测试两个引用是否指向同一个对象,而不测试两个对象的内容是否相同。(即时两个引用变量对应的两个对象的内容一模一样,这两对象的引用比较,依然是不等的)。

  

  对引用类型来说,有两种相等:引用相等和对象相等。

  (1)采用==,比较的引用相等。

  (2)比较对象相等,需要采用equals ()方法。所有对象都从 Object 类继承了 equals() 方法,但其默认的实现方式是与 ==相同、 测试引用是否相同,而不测试内容是否相等。需比较对象内容是否相等的类可以自定义 equals() 方法。
    Java默认的String 类自定义了equals ()方法,比较的是对象是否是否相同。

    Java默认在数组上调用 equals() 方法,但作用和使用 == 运算符一样,因为数组始终继承默认的 equals() 方法,比较引用而不是数组的内容,比较数组是否相等可以使用 java.util.Arrays.equals() 实用方法。


熟悉C 程序员的程序员,完全可以把Java的引用看作指针或内存地址。

不过要记住,Java 程序中除了指向对象,无法对引用进行任何其他方式的操作。这也是Java保护内存安全的一种方式。如: 

(1)C/C++ 中的指针可以转换成整数、也可以把整数转换成指针、指针可以递增或递减。这些操作在Java中的引用上统统不允许。

(2)C/C++ 可以使用求地址运算符 &,也可使用运算符 * 和 ->。在Java中的引用上统统不支持。

在32位JVM上,对象的引用占用4个字节。

在64位系统中,对象引用通常是8字节长。但是在Sun / Oracle最近的JVM中,你可以启用Compressed Oops,这会将参考大小减少到4个字节,但要以堆大小的更小限制为代价。

三、Java中的字面量

字面量,可以理解为通过字面可识别其意义的,可以直接向变量赋值的内容。(非字面量,不能直接复制,需要通过new创建对象)

1)基本数据类型的字面量

  整数:1、4、-3等。

  浮点数:3.1415

  字符:单引号内从字符,比如'a'、'b'

  布尔型:true关键字、false关键字

2)对象的字面量

  字符串字面量:双引号内的字符串,如:"Hello World!"

  null关键字:null是一种特殊的字面量,引用对象可以直接赋值null。此时表示引用对象没有指向任何对象,也没有为任何对象分配内存空间。

  .class对象字面量:Java平台加载类阶段,会创建.class,详情后面章节再描述。

  注:字符串字面量中不能包含注释,而且只能有一行。Java 不支持把两行当成一行的任何接续字符。如果需要表示一串长文本,一行写不下,可以把这个文本拆成多个单独的字符串字面量,再使用 + 运算符把它们连接起来。

四、Java中的常量:

Java中通过final修饰的变量,称之为final变量。采用static final修饰的成员变量(字段)称之为常量。

常用方式如:
Class A {
  static final float PAI = 3.14。 //表示类字段是常量,类似于C语言中的全局常量的概念。其值不可变化、不创建对象依然可应用。标识符建议采用全大写。
}

Class B {
  final String strType = “Dog”。 //字段赋值后不可更改
}

Class C {
.  .....
  public void func() {
    final int i = 15; //字段赋值后不可更改
    final A a = new A(); //引用变量不可再指向其他对象
  }
}

final修饰基本数据类型的变量时,必须赋予初始值且不能被改。当final修饰基本数据类型变量时不赋予初始值、或当final修饰基本数据类型变量被改变时,就会报错。

final修饰引用变量时,该引用变量不能再指向其他对象。当final修饰的引用变量指向其他对象时,就会报错。

猜你喜欢

转载自www.cnblogs.com/yickel/p/12770527.html
今日推荐