专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java编程思想:使用 Java 运算符(java?:运算符)

temp10 2024-10-21 12:21:03 java教程 14 ℃ 0 评论

运算符以一个或多个自变量为基础,可生成一个新值。自变量采用与原始方法调用不同的一种形式,但效果是相同的。根据以前写程序的经验,运算符的常规概念应该不难理解。

加号(+)、减号和负号(-)、乘号(*)、除号(/)以及等号(=)的用法与其他所有编程语言都是类似的。

Java编程思想:使用 Java 运算符(java?:运算符)

所有运算符都能根据自己的运算对象生成一个值。除此以外,一个运算符可改变运算对象的值,这叫作“副作用”(Side Effect)。运算符最常见的用途就是修改自己的运算对象,从而产生副作用。但要注意生成的值亦可由没有副作用的运算符生成。

几乎所有运算符都只能操作“主类型”(Primitives)。唯一的例外是“=”、“ ==”和“ !=”,它们能操作所有对象(也是对象易令人混淆的一个地方)。除此以外,String类支持“+”和“ +=”。

优先级

运算符的优先级决定了存在多个运算符时一个表达式各部分的计算顺序。Java对计算顺序作出了特别的规定。其中,最简单的规则就是乘法和除法在加法和减法之前完成。程序员经常都会忘记其他优先级规则,所以应该用括号明确规定计算顺序。例如:

A = X + Y - 2/2 + Z; 

为上述表达式加上括号后,就有了一个不同的含义。

A = X + (Y - 2)/(2 + Z); 

赋值

赋值是用等号运算符(=)进行的。它的意思是“取得右边的值,把它复制到左边”。右边的值可以是任何常数、变量或者表达式,只要能产生一个值就行。但左边的值必须是一个明确的、已命名的变量。也就是说,它必须有一个物理性的空间来保存右边的值。举个例子来说,可将一个常数赋给一个变量(A=4),但不可将任何东西赋给一个常数(比如不能4=A)。

对主数据类型的赋值是非常直接的。由于主类型容纳了实际的值,而且并非指向一个对象的句柄,所以在为其赋值的时候,可将来自一个地方的内容复制到另一个地方。例如,假设为主类型使用“A=B”,那么B处的内容就复制到A。若接着又修改了A,那么B根本不会受这种修改的影响。作为一名程序员,这应成为自己的常识。

但在为对象“赋值”的时候,情况却发生了变化。对一个对象进行操作时,我们真正操作的是它的句柄。所以倘若“从一个对象到另一个对象”赋值,实际就是将句柄从一个地方复制到另一个地方。这意味着假若为对象使用“ C=D”,那么CD最终都会指向最初只有D才指向的那个对象。

//: 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类非常简单,它的两个实例(n1n2)是在main()里创建的。每个Number中的i值都赋予了一个不同的值。随后,将n2赋给n1,而且n1发生改变。在许多程序设计语言中,我们都希望n1n2任何时候都相互独立。但由于我们已赋予了一个句柄,所以下面才是真实的输出:

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; 

这样便可保留两个独立的对象,而不是将n1n2绑定到相同的对象。但您很快就会意识到,这样做会使对象内部的字段处理发生混乱,并与标准的面向对象设计准则相悖。其时,大家也会注意到对象的赋值会产生一些令人震惊的效果。

方法调用中的别名处理将一个对象传递到方法内部时,也会产生别名现象。

//: 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 

别名和它的对策是非常复杂的一个问题。从现在开始就应加以重视,以便提早发现它的缺点。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表