赋值是用等号运算符(=)进行的。它的意思是“取得右边的值,把它复制到左边”。右边的值可以是任何常数、变量或者表达式,只要能产生一个值就行。但左边的值必须是一个明确的、已命名的变量。也就是说,它必须有一个物理性的空间来保存右边的值。举个例子来说,可将一个常数赋给一个变量(A=4;),但不可将任何东西赋给一个常数(比如不能4=A)。
对主数据类型的赋值是非常直接的。由于主类型容纳了实际的值,而且并非指向一个对象的句柄,所以在为其赋值的时候,可将来自一个地方的内容复制到另一个地方。例如,假设为主类型使用“A=B”,那么B处的内容就复制到A。若接着又修改了A,那么B根本不会受这种修改的影响。作为一名程序员,这应成为自己的常识。
但在为对象“赋值”的时候,情况却发生了变化。对一个对象进行操作时,我们真正操作的是它的句柄。所以倘若“从一个对象到另一个对象”赋值,实际就是将句柄从一个地方复制到另一个地方。这意味着假若为对象使用“C=D”,那么C和D最终都会指向最初只有D才指向的那个对象。下面这个例子将向大家阐示这一点。
这里有一些题外话。在后面,大家在代码示例里看到的第一个语句将是“package 03”使用的“package”语句,它代表本书第3章。本书每一章的第一个代码清单都会包含象这样的一个“package”(封装、打包、包裹)语句,它的作用是为那一章剩余的代码建立章节编号。在第17章,大家会看到第3章的所有代码清单(除那些有不同封装名称的以外)都会自动置入一个名为c03的子目录里;第4章的代码置入c04;以此类推。所有这些都是通过第17章展示的CodePackage.Java程序实现的;“封装”的基本概念会在第5章进行详尽的解释。就目前来说,大家只需记住象“package 03”这样的形式只是用于为某一章的代码清单建立相应的子目录。
为运行程序,必须保证在classpath里包含了我们安装本书源码文件的根目录(那个目录里包含了c02,c03c,c04等等子目录)。
对于Java后续的版本(1.1.4和更高版本),如果您的main()用package语句封装到一个文件里,那么必须在程序名前面指定完整的包裹名称,否则不能运行程序。在这种情况下,命令行是:
Java c03.Assignment
运行位于一个“包裹”里的程序时,随时都要注意这方面的问题。
下面是例子:
//: Assignment.Java
// Assignment with objects is a bit tricky
package c03;
class Number {
int i;
}
public class Assignment {
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
n1.i = 9;
n2.i = 47;
System.out.println("1: n1.i: " + n1.i +
", n2.i: " + n2.i);
n1 = n2;
System.out.println("2: n1.i: " + n1.i +
", n2.i: " + n2.i);
n1.i = 27;
System.out.println("3: n1.i: " + n1.i +
", n2.i: " + n2.i);
}
} ///:~
Number类非常简单,它的两个实例(n1和n2)是在main()里创建的。每个Number中的i值都赋予了一个不同的值。随后,将n2赋给n1,而且n1发生改变。在许多程序设计语言中,我们都希望n1和n2任何时候都相互独立。但由于我们已赋予了一个句柄,所以下面才是真实的输出:
1: n1.i: 9, n2.i: 47
2: n1.i: 47, n2.i: 47
3: n1.i: 27, n2.i: 27
看来改变n1的同时也改变了n2!这是由于无论n1还是n2都包含了相同的句柄,它指向相同的对象(最初的句柄位于n1内部,指向容纳了值9的一个对象。在赋值过程中,那个句柄实际已经丢失;它的对象会由“垃圾收集器”自动清除)。
这种特殊的现象通常也叫作“别名”,是Java操作对象的一种基本方式。但假若不愿意在这种情况下出现别名,又该怎么操作呢?可放弃赋值,并写入下述代码:
n1.i = n2.i;
这样便可保留两个独立的对象,而不是将n1和n2绑定到相同的对象。但您很快就会意识到,这样做会使对象内部的字段处理发生混乱,并与标准的面向对象设计准则相悖。由于这并非一个简单的话题,所以留待第12章详细论述,那一章是专门讨论别名的。其时,大家也会注意到对象的赋值会产生一些令人震惊的效果。
1. 方法调用中的别名处理
将一个对象传递到方法内部时,也会产生别名现象。
//: PassObject.Java
// Passing objects to methods can be a bit tricky
class Letter {
char c;
}
public class PassObject {
static void f(Letter y) {
y.c = 'z';
}
public static void main(String[] args) {
Letter x = new Letter();
x.c = 'a';
System.out.println("1: x.c: " + x.c);
f(x);
System.out.println("2: x.c: " + x.c);
}
} ///:~
在许多程序设计语言中,f()方法表面上似乎要在方法的作用域内制作自己的自变量Letter y的一个副本。但同样地,实际传递的是一个句柄。所以下面这个程序行:
y.c = 'z';
实际改变的是f()之外的对象。输出结果如下:
1: x.c: a
2: x.c: z
别名和它的对策是非常复杂的一个问题。尽管必须等至第12章才可获得所有答案,但从现在开始就应加以重视,以便提早发现它的缺点。
分享到:
相关推荐
Java变量赋值运算符及相关实例 Java变量赋值运算符是Java编程语言中的一种基本运算符,主要用于将右方操作数的值赋给左方操作数。赋值运算符的符号是“=”,是一个二元运算符,需要两个操作数。左方操作数必须是一...
本话题聚焦于“多线程线程变量赋值”,讨论如何在不通过参数传递的情况下,为线程变量直接赋值。 首先,我们需要理解线程变量(Thread Local Variables)的概念。线程变量,也称为线程局部变量,是一种特殊类型的...
在这个教程中,我们将学习如何使用`yml`配置文件为静态变量赋值,特别是针对像数据查询引擎连接工具类这样的场景。 首先,我们需要在`yml`配置文件中定义所需的参数。以`clickhouse`为例,我们会在`application.yml...
给两个整型变量赋值,然后交换两个变量的值,最后输出交换后的变量值。
本篇将深入探讨如何利用YAML作为中介,来修改JSON文件中的特定变量值。 首先,JSON是一种轻量级的数据交换格式,它易于人阅读和编写,同时也方便机器解析和生成。其语法基于JavaScript对象语法,但不依赖于...
在Java编程语言中,String类型变量的赋值问题是一个重要的概念,主要涉及到对象引用和不可变性。这里我们将深入探讨这两个关键点。 首先,Java中的String类是不可变的,这意味着一旦创建了一个String对象,就不能...
这是因为我们在 `method` 方法中对实例变量和静态变量进行了赋值。 java 变量命名需要遵守一定的规则和惯例,以确保程序的可读性和维护性。在变量命名时,我们需要区分局部变量和实例变量,并遵守变量的作用域和...
Java 变量初始化的时机是指在 Java 语言中变量的初始化过程,包括变量的声明、初始化和赋值的步骤。 Java 变量声明 在 Java 语言中,每个变量必须先声明,然后才能使用。声明变量时必须指定该变量的数据类型。...
Java编程语言中的变量赋值和操作符顺序在面试中是一个常见的考点,特别是在处理复杂运算时。本题讨论了一个试图巧妙地交换两个整型变量`x`和`y`值的陷阱,通过使用异或操作符`^`。然而,这种方法在Java中并不奏效,...
本文将深入探讨如何在Java中调用JavaScript的代码以及如何通过JavaScript为Java变量赋值。 一、Java调用JavaScript 1. Webview组件:在Android中,我们通常使用WebView组件来加载和显示网页内容。这个组件还提供了...
在Android面试中,Java基础知识是不可或缺的部分,其中涉及到的一个经典陷阱是关于变量赋值的问题,特别是涉及异或操作符的“巧妙”交换变量值的方法。本文以一个具体的例子来阐述这个问题,即`CleverSwap`类中的...
在Java编程语言中,变量是存储数据的容器,而数据类型则是定义变量可以存储哪种类型的数据。Java提供了两种主要的数据类型:基本数据类型和引用数据类型。基本数据类型包括整型(byte, short, int, long)、浮点型...
在 Java 中,变量的生命周期和作用域是通过变量的声明和赋值来实现的。例如,以下是一个变量的声明和赋值的示例: ```java public class TestScope { public static void main(String[] args) { int x = 12; { ...
通过以上讨论,我们可以看到,Java中子类对象赋值给父类对象是一种强大且灵活的设计模式,它允许我们在代码中使用抽象的父类引用,从而简化编程,增加代码的通用性和可维护性。在实际项目中,合理利用这一特性,能够...
#### 十、Java变量赋值 **3.3 变量赋值** - **说明**: 示例展示了变量赋值的过程。 - **应用实例**: 例如,`a = 2; b = 1;` 表示为 `a` 赋值为 `2`,`b` 赋值为 `1`。 #### 十一、Java数据类型转换 **3.4 数据...
等代码,体现了Java变量赋值和类型转换的使用。 * 数学运算:如System.out.println(Math.round(10.55));等代码,展示了Java中的数学运算函数使用。 二、集合框架 * LinkedHashSet的使用:如Set<String > set = new...
Java 中的基本类型和引用类型变量是两个不同的概念,它们在内存分配、变量赋值和函数传递等方面有着本质的区别。 基本类型是 Java 中的八种基本类型,包括 byte、short、int、long、float、double、char 和 boolean...
"Java Class 对象、静态变量声明和赋值详解" Java 中的 Class 对象是 Java 语言中非常重要的一部分,它代表了 Java 应用程序中的类和接口。每个类和接口都可以用 Class 对象来表示,包括枚举和注解。甚至数组也可以...
//得到输入的值,保存到变量a //Scanner是jdk类库中的类 //保存在java.util包下 int a = new Scanner(System.in).nextInt(); System.out.print("输入整数b:"); int b = new Scanner(System.in).nextInt(); ...
在Java编程语言中,赋值...这些运算符不仅用于简单地为变量赋值,还可以在复杂的表达式中组合使用,实现对变量值的快速计算和更新。在编程实践中,应根据需求选择合适的赋值运算符,以优化代码的可读性和执行效率。