java运算符
加(+)、减(-)、乘(*)、除(/)、等号(=)
几乎所有运算符都只能操作“主类型”(Primitives)。唯一的例外是“=”、“==”和“!=”,它们能操作所有对象(也是对象易令人混淆的一个地方)。除此之外,String类型支持“+”和“+=”。
优先级
运算符的优先级决定了存在多个运算符时一个表达式各部分的计算顺序。java对计算顺序作出了特别的规定。其中,最简单的规则就是乘法和除法在加法和减法之前完成。程序员经常都会忘记其他优先级规则,所以应该用括号明确规定计算顺序。例如:
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 5;
int c = 6;
//int d = a+b -2/2 + c; //20
//为上述表达式加上括号后,就有了一个不同的含义。
int d = a+(b-2)/(2+c);
System.out.println(d);//10
}
}
赋值
赋值使用等号运算符(=)进行的。它的意思是“取得右边的值,把它复制到左边”。右边的值可以是任何常数、变量或者表达式,只要能产生一个值就行。但左边的值必须是一个明确的、已命名的变量。也就是说,它必须有一个物理性的空间来保存右边的值。举个例子来说,可将一个常数赋给一个变量(A=4;),但不可以将任何东西赋给一个常数(比如不能 4 = A)。
例题:
class Number {
int i;
}
public class Test {
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);//9 47
n1 = n2;
System.out.println("2: n1.i: " + n1.i + ", n2.i: " + n2.i);//47 47
n1.i = 27;
System.out.println("3: n1.i: " + n1.i + ", n2.i: " + n2.i);//27 27
}
} /// :~
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
图1
看来改变n1的同时也改变了n2!这是由于无论n1还是n2都包含了相同的句柄,它指向相同的对象(最初的句柄位于n1内部,指向容纳了值9的一个对象。在赋值过程中,那个句柄实际已经丢失;它的对象会由“垃圾收集器”自动清除)。如图2。
图2
这种特殊的现象通常也叫作“别名”,是java操作对象的一种基本方式。但假若不愿意在这种情况下出现别名,又该怎么操作呢?可放弃赋值,并写入下述代码:
n1.i = n2.i;
这样便可以保留两个独立的对象,而不是将n1和n2绑定到相同的对象。但您很快就会意识到,这样做会使对象内部的字段处理发生混乱,并与标准的面向对象设计准则相悖。
图3
算数运算符
java的基本运算符与其他大多数程序设计语言是相同的。其中包括加号(+)、减号(-)、除号(/)、乘号(*)以及模数(%,从整数除法中获得余数)。整数除法会直接砍掉小数,而不是进位。java也用一种简写形式进行运算,并同时进行赋值操作。这是由等号前的一个运算符标记的,而且对于语言中的所有的运算符都是固定的。例如,为了将4加到变量x,并将结果赋给x,可用:x+=4。
import java.util.Random;
public class MathOps {
// prt()方法打印一个String
static void prt(String s) {
System.out.println(s);
}
// pInt()先打印一个String,再打印一个 int
static void pInt(String s, int i) {
prt(s + " = " + i);
}
// pFlt()先打印一个 String,再打印一个 float。
static void pFlt(String s, float f) {
prt(s + " = " + f);
}
public static void main(String[] args) {
// Create a random number generator,
// seeds with current time by default:
Random rand = new Random();//创建Random(随机)对象
int i, j, k;
// '%' limits maximum value to 99:
j = rand.nextInt() % 100;
k = rand.nextInt() % 100;
pInt("j", j);
pInt("k", k);
i = j + k;
pInt("j + k", i);
i = j - k;
pInt("j - k", i);
i = k / j;
pInt("k / j", i);
i = k * j;
pInt("k * j", i);
i = k % j;
pInt("k % j", i);
j %= k;
pInt("j %= k", j);
// Floating-point number tests:
float u, v, w; // applies to doubles, too
v = rand.nextFloat();
w = rand.nextFloat();
pFlt("v", v);
pFlt("w", w);
u = v + w;
pFlt("v + w", u);
u = v - w;
pFlt("v - w", u);
u = v * w;
pFlt("v * w", u);
u = v / w;
pFlt("v / w", u);
// the following also works for
// char, byte, short, int, long,
// and double:
u += v;
pFlt("u += v", u);
u -= v;
pFlt("u -= v", u);
u *= v;
pFlt("u *= v", u);
u /= v;
pFlt("u /= v", u);
}
} /// :~
自动递增和递减
和C类似,java提供了丰富的快捷运算方式。这些快捷运算可使代码更清爽,更易录入,也更易读者辨读。两种很不错的快捷运算方式是递增和递减运算符(常称作“自动递增”和“自动递减”运算符)。其中,递减运算符是“--”,意为“减少一个单位“;递增运算符是“++”,意为“增加一个单位”。举一个例子来说,假设A是一个int(整数)值,则表达式++A就等价于(A=A+1)。递增和递减运算符结果生成的事变量的值。
对每种类型的运算符,都有两个版本可供选用;通常将其称为“前缀版”和“后缀版”。“前递增”表示++运算符位于变量或者表达式的前面;而“后递增”表示++运算符位于变量或表达式的后面。类似地,“前递减”意味着 -- 运算符位于变量或表达式的前面;而 “后递减”意味着 -- 运算符位于变量或表达式的后面。对于前递增和前递减(如++A 或--A),会先执行运算,再生成值。而对于后递增和后递减(如A++或A--),会先生成值,再执行运算。
public class AutoInc {
public static void main(String[] args) {
int i = 1;
prt("i : " + i);
prt("++i : " + ++i); // Pre-increment
prt("i++ : " + i++); // Post-increment
prt("i : " + i);
prt("--i : " + --i); // Pre-decrement
prt("i-- : " + i--); // Post-decrement
prt("i : " + i);
}
static void prt(String s) {
System.out.println(s);
}
} /// :~
输出结果:
i : 1
++i : 2
i++ : 2
i : 3
--i : 2
i-- : 2
i : 1
也就是说,++ 或-- 会改变运算对象,不仅仅是使用自己的值。
递增运算正是对“C++”这个名字的一种解释,暗示着“超越C的一步”。在早期的一次JAVA演讲中,Bill Joy(创始人之一)声称“Java=(C++)--” (C++ 减减) 意味着java已去除了C++一些 没来由 折磨人的地方,形成一种更精简的语言。