常见的操作符
注:上面的操作数优先级从上到下依次降低,同一个单元格内的优先级相同 我们在编程的是候难免会忘记操作符的顺序,所以应该用括号明确规定运算顺序。 复制代码 代码如下: public class Precedence{ public static void main(String [] args){ int x=1,y=2,z=3; int a=x + y – 2 / 2 + z; int b=x + ( y – 2 ) / ( 2 + z ); System.out.println(“a =” + a + “b=”+b); } } 输出 a=5 b=1 输出语句中的+在这种上下文环境中意味着“字符串连接”,并且如果必要,他还要执行“字符串转换”。当编译器观察到一个String后面进梗着一个”+”,而这个”+”的后面又紧跟着一个非String类型的元素时,就会尝试着将这个非String类型的元素转换成String类型。 赋值 赋值操作符”=”,他的含义是:取右边的值(右值),然后复制给左边(左值)。右值可以是任何常数,变量或者表达式,或者是任意可以产生值的方法。但左边必须是一个明确的以命名的变量。也就是说,必须有一个屋里空间可以储存等号右边的值。比如可以将一个常数赋值给一个变量 a = 4 但是不能把任何东西赋值给一个常数,常数不能作为左值 4 = a不成立。 基本类型数据储存了实际的数值,而并非指向一个对象的引用,所以在为其赋值的时候,是直接讲一个地方的内容复制到了另一个地方。比如基本数据类型使用a = b,实际的含义是将b中的内容复制给a,如果之后给a从新赋值b不会受到影响。但是并不是所有的赋值都会达到这种预期的效果。 为对象做赋值操作的时候,其实我们操作的是对象的引用,所以若我们将一个对象赋值给另一个对象实际上是将”引用”从一个地方复制到另一个地方,这就意味着我们在就该其中一个对象值的同时,另一个也会跟这发生变化。 复制代码 代码如下: class Tank{ int level; } public class Assignment{ public static void main(String [] args){ Tank t1=new Tank(); Tank t2=new Tank(); t1.level=9; t2.level=47; System.out.print(“1: t1.level” +t1.level+”,t2.level”+t2.level); t1 = t2; System.out.print(“2: t1.level” +t1.level+”,t2.level”+t2.level); t1.level=27; System.out.print(“3: t1.level” +t1.level+”,t2.level”+t2.level); } } 输出 1:t1.level: 9,t2.level:47; 2:t1.level: 47,t2.level:47; 3:t1.level:27,t2.level:27; 在这个例子中就发生了操作引用的问题,我们在修改t1的同时t2也被修改了,而在大多情况下我们是希望t1与t2可以相互独立的,但是由于赋值操作的是一个对象的引用,所以这里t1和t2包含的是相同的引用,它们指向相同的对象(原本t1包含的对对象的引用,是一个指向值为9的对象。在t1赋值的时候,这个引用被覆盖,也就是丢失了;而那个不再被引用的对象会由”垃圾回收器”自动清理。 这种特殊的现象通常称作”别名现象”,是Java操作对象的一种基本方式。在这个例子中如果想避免别名现在,我们应该直接对对象的值进行操作: t1.level=t2.level; 这样写便可以保持两个对象的独立,但是直接操作对象的域很容易导致混乱,并且,违背了良好的面向对象程序设计的原则。 下面的例子介绍了方法调用中的别名问题 复制代码 代码如下: 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.print(“1: x.c ” + x.c); f(x); System.out.print(“2: x.c” + x.c); } } 输出 1: x.c: a 2: x.c: z 我们在使用f方法的时候似乎觉得它的作用域内复制其参数Letter y的一个副本;但实际上只是传递了一个引用。所以代码行 y.c='z'; 实际改变的是f()之外的对象。 其他赋值操作符
|
|
来自: 紫衣风华 > 《C#基础理论知识》