Java编程思想学习(三)----第三章:操作符
3.2使用Java操作符
操作符接受一个或多个参数,并生成一个新值。
操作符作用于操作数,生成一个新值。有些操作符可以改变操作数自身的值。几乎所以的操作符都只能操作“基本类型”。例外的操作符有“=”,“==”,“!=”,这些操作符能操作所有对象。String支持“+”和“+=”。
3.3优先级
@Test
public void precedence() {
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 = 5b = 1
}/* Output:a = 5 b = 1*///:~
System.out.println()语句中,当编译器观察到一个String后面紧跟一个“+”,而这个“+”的后面又紧跟一个非String类型的元素时,就会尝试将非String类型元素转换为String。
3.4赋值
对基本数据类型的赋值是很简单的。基本类型存储了实际的数值,而并非指向一个对象的引用,所以在为其赋值的时候,是直接将一个地方的内容复制到另一个地方。
但是对象”赋值“的时候,情况发生了变化。对一个对象进行操作时,我们真正操作的是对对象的引用。
class Tank {
float level;
}
public class Assignment {
public static void main(String[] args) {
TankOld t1 = new TankOld();
TankOld t2 = new TankOld(); t1.level = 18;
t2.level = 24; System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); t1 = t2;
System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); t1.level = 33;
System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); test();
}/* Output:
1:t1.level: 18.0, t2.level: 24.0
1:t1.level: 24.0, t2.level: 24.0
1:t1.level: 33.0, t2.level: 33.0
test---------------
1:t1.level: 18.0, t2.level: 24.0
1:t1.level: 24.0, t2.level: 24.0
1:t1.level: 33.0, t2.level: 24.0
*///:~ public static void test() {
System.out.println("test---------------");
TankOld t1 = new TankOld();
TankOld t2 = new TankOld(); t1.level = 18;
t2.level = 24; System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); t1.level = t2.level;
System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level); t1.level = 33;
System.out.println("1:t1.level: "+t1.level + ", t2.level: "+t2.level);
}
}
原本t1包含的对对象的引用,是指向一个值为9的对象。在t1赋值时,这个引用被覆盖了,也就是丢失;而那个不再被引用的对象会由“垃圾回收器”自动清理。
避免错误可以写成:t1.level = t2.level;
直接操作对象内的域容易导致混乱,违背了良好的面向对象程序设计的原则。
3.4.1方法调用中的别名问题
class Letter{
char c;
} public class PassObject{ static voic f(Letter y){
y.c = 'z';
} public static void main(String[] args){
Letter x = new Letter();
x.c = 'a';
print("1:x.c:"+x.c); f(x);
print("2:x.c:"+x.c);
}
}/* Output:
1:x.c:a
2:x.c:z
*///~
现在需要知道它的存在,并在使用中注意这个陷阱。
3.5算数操作符
Java的基本算术操作符与其他大多数程序设计语言是相同的。其中包括加号(+)、减号(-)、除号(/)、乘号(*)以及取模操作符(%,它从整数除法中产生余数)。整数除法会直接去掉结果的小数位,而不是四舍五入地圆整结果。
简化符号同时进行运算和赋值操作。如x = x + 4,可以写为 x += 4。
要生成数字,程序首先会创建一个Random类的对象。如果在创建过程中没有传递任何参数,那么Java就好将当前时间作为随机数生成器的种子,并由此在程序每一次执行都产生不一样的输出。通过在创建Random对象时提供种子(随机数生产器对于特定的种子总是产生相同的随机数序列),就可以在每一次执行过程序时都生成相同的随机数。
3.5.1一元加、减操作符
一元减号用于转变数据的符号,而一元加号只是为了和一元减号相对应,但是它唯一的作用仅仅是讲较小类型的操作数提升为int。
3.6自动递增和递减
对于前缀递增和递减(如++a或--a),会先执行运算,在生成值。而对于后缀递增和后缀递减(如a++或a--),会先生成值在执行运算。它们是除了赋值操作符以外,唯一具有“副作用”的操作符。他们会改变操作数,而不仅仅是使用自己的值。
3.7关系操作符
关系操作符包括小于(<)、大于(>)、小于或等于(<=)、大于或等于(>=)、等于(==)以及不等于(!=)。
3.7.1测试对象的等价性
public class Equivalence {
public static void main(String[]args){
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
}/*Output:
false
true
*///:~
但是尽管对象的内容相同,然而对象的引用却是不同的,而==和!=比较的就是对象的引用。
如果想比较两个对象的实际内容是否相同,又该如何操作呢?此时,必须使用所有对象都适用的特殊方法equals()但这个方法不适用于“基本类型”,基本类型直接使用==和!=即可。
class Value{
int i;
} public class EqualsMethod2{
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals (v2));
}
}/*Output:
false
*///:~
equals()的默认行为是比较引用。所以除非在自己的新类中覆盖equals()方法,否则不可能表现出我们希望的行为。
大多数Java类库都实现了equals()方法,以便用来比较对象的内容,而非比较对象的引用。
3.8逻辑操作符
逻辑操作符“与”(&&)、“或”(||)、“非”(! )能根据参数的逻辑关系,生成一个布尔值(true或false)。
与在C及C++中不同的是:不可将一个非布尔值当作布尔值在逻辑表达式中使用。如果在应该使用String值的地方使用了布尔值,布尔值会自动转换成适当的文本形式。
在上述程序中,可将整数类型替换成除布尔型以外的其他任何基本数据类型。但要注意,对浮点数的比较是非常严格的。即使一个数仅在小数部分与另一个数存在极微小的差异,仍然认为它们是“不相等”的。
3.8.1 短路
public class ShortCircult{
static boolean test1(int val){
System.out.println("test1(" + val + ")");
System.out.println("result: " + (val < 1));
return val < 1;
}
static boolean test2(int val){
System.out.println("test2(" + val + ")");
System.out.println("result: " + (val < 2));
return val < 2;
}
static boolean test3(int val){
System.out.println("test3(" + val + ")");
System.out.println("result: " + (val < 3));
return val < 3;
}
public static void main(String[] args) {
boolean b=test1(0)&&test2(2)&&test3(2);
System.out.println("expression is " + b);
}
}/*Output:
test1 (0)
result: true
test2 (2)
result: false
expression is false
*///:~
第二个测试产生了一个false结果。由于这意味着整个表达式肯定为false,所以没必要继续计算剩余的表达式,那样只是浪费。“短路”一词的由来正源于此。
3.9 直接常量
@Test
public void literalsTest1() {
int i1 = 0x2f; // 十六进制(小写标识)
System.out.println("i1: " + Integer.toBinaryString(i1));
int i2 = 0x2F; // 十六进制(大写标识)
System.out.println("i2: " + Integer.toBinaryString(i2));
int i3 = 0177; // 八进制(前导零)
System.out.println("i3: " + Integer.toBinaryString(i3));
char c = 0xffff; // 超出char自身的范围
System.out.println("c: " + Integer.toBinaryString(c));
byte b = 0x7f; // 超出byte自身范围
System.out.println("b: " + Integer.toBinaryString(b));
short s = 0x7fff; // 超出short自身范围
System.out.println("s: " + Integer.toBinaryString(s));
long n1 = 200L; // long后缀
System.out.println("n1: " + Long.toBinaryString(n1));
long n2 = 200l; // long后缀(和1容易引起混淆)
System.out.println("n2: " + Long.toBinaryString(n2));
long n3 = 200;
System.out.println("n3: " + Long.toBinaryString(n3));
float f1 = 1;
float f2 = 1f; // float后缀
float f3 = 1F; // float后缀
double d1 = 1d; // double后缀
double d2 = 1D; // double后缀
} /* Output:
i1: 101111
i2: 101111
i3: 1111111
c: 1111111111111111
b: 1111111
s: 111111111111111
n1: 11001000
n2: 11001000
n3: 11001000
*///:~
如果在程序里使用了“直接常量”,编译器可以准确地知道要生成什么样的类型,但有时候却是模棱两可的。
直接常量后面的后缀字符标志了它的类型。若为大写(或小写)的L,代表long(但是,使用小写字母l容易造成混淆,因为它看起来很像数字1)。大写(或小写)字母F,代表float;大写(或小写)字母D,则代表double。
十六进制数适用于所有整数数据类型,以前缀0x(或0X),后面跟随0-9或小写(或大写)的a-f来表示。如果试图将一个变量初始化成超出自身表示范围的值(无论这个值的数值形式如何),编译器都会向我们报告一条错误信息。如果超出范围,编译器会将值自动转换成int型,并告诉我们需要对这次赋值进行“窄化转型”。如果将比较小的类型传递给Integer.toBinaryString()方法,则该类型将自动被转换为int。
3.9.1 指数记数法
@Test
public void exponents() {
//大写和小写一样
float expFloat = 1.39e-43f;
expFloat = 1.39E-43f;
System.out.println(expFloat);
double expDouble = 47e47d; // 'd'可选
double expDouble2 = 47e47d; // 自动转为double
System.out.println(expDouble);
float f4 = 1e-43f; // 10的次方
float f5 = (float) Math.pow(10, -43f);
System.out.println(f4);
System.out.println(f5);
System.out.println(f4 == f5);
} /* Output:
1.39E-43
4.7E48
1.0E-43
1.0E-43
true
*///:~
设计师们很自然地决定e代表“10的幂次”。
那么在Java中看到像1.39e-43f 这样的表达式时,请转换思维,它真正的含义是1.39×10-43。
编译器通常会将指数作为双精度数(double)处理,所以假如没有这个尾随的f,就会收到一条出错提示,告诉我们必须使用类型转换将double转换成float。
3.10 按位操作符
按位操作符会对两个参数中对应的位执行布尔代数运算,并最终生成一个结果。
①如果两个输入位都是1,则按位“与”操作符(&)生成一个输出位1;否则生成一个输出位0。
②如果两个输入位里只要有一个是1,则按位“或”操作符 (|) 生成一个输出位1;只有在两个输入位都是0的情况下,它才会生成一个输出位0。
③如果输入位的某一个是1,但不全都是1,那么按位“异或”操作 (^) 生成一个输出位1。
④按位“非”(~),也称为取反操作符,它属于一元操作符,只对一个操作数进行操作(其他按位操作符是二元操作符)。按位“非”生成与输入位相反的值——若输入0,则输出1,若输入1,则输出0。
按位操作符和逻辑操作符都使用了同样的符号,因此我们能方便地记住它们的含义:由于位是非常“小”的,所以按位操作符仅使用了一个字符。
对于布尔值,按位操作符具有与逻辑操作符相同的效果,只是它们不会中途“短路”。
3.11 移位操作符
">>" "<<"
Java中增加了一种“无符号”右移位操作符(>>>),它使用“零扩展”:无论正负,都在高位插入0。这一操作符是C或C++中所没有的。只有数值右端的低5位才有用。这样可防止我们移位超过int型值所具有的位数。若对一个long类型的数值进行处理,最后得到的结果也是long。此时只会用到数值右端的低6位,以防止移位超过long型数值具有的位数。
“移位”可与“等号”(<<=或>>=或>>>=)组合使用。如果对byte或short值进行这样的移位运算,得到的可能不是正确的结果。它们会先被转换成int类型,再进行右移操作,然后被截断,赋值给原来的类型,在这种情况下可能得到-1的结果。
@Test
public void bitManipulation() {
Random rand = new Random(47);
int i = rand.nextInt();
int j = rand.nextInt();
printBinaryInt("-1", -1);
printBinaryInt("+1", +1);
int maxpos = 2147483647;
printBinaryInt("maxpos", maxpos);
int maxeng = -2147483648;
printBinaryInt("maxeng", maxeng);
printBinaryInt("i", i);
printBinaryInt("j", j);
printBinaryInt("~j", ~j);
printBinaryInt("-i", -i);
printBinaryInt("i & j", i & j);
printBinaryInt("i | j", i | j);
printBinaryInt("i ^ j", i ^ j);
printBinaryInt("i << 5", i << 5);
printBinaryInt("i >> 5", i >> 5);
printBinaryInt("(~i) >> 5", (~i) >> 5);
printBinaryInt("i >>> 5", i >>> 5);
printBinaryInt("(~i) >>> 5", (~i) >>> 5);
// 10111010001001000100001010010101
//11111101110100010010001000010100
//
/* Output:
-1, int: -1, binary:
11111111111111111111111111111111
+1, int: 1, binary:
1
maxpos, int: 2147483647, binary:
1111111111111111111111111111111
maxeng, int: -2147483648, binary:
10000000000000000000000000000000
i, int: -1172028779, binary:
10111010001001000100001010010101
j, int: 1717241110, binary:
1100110010110110000010100010110
~j, int: -1717241111, binary:
10011001101001001111101011101001
-i, int: 1172028779, binary:
1000101110110111011110101101011
i & j, int: 570425364, binary:
100010000000000000000000010100
i | j, int: -25213033, binary:
11111110011111110100011110010111
i ^ j, int: -595638397, binary:
11011100011111110100011110000011
i << 5, int: 1149784736, binary:
1000100100010000101001010100000
i >> 5, int: -36625900, binary:
11111101110100010010001000010100
(~i) >> 5, int: 36625899, binary:
10001011101101110111101011
i >>> 5, int: 97591828, binary:
101110100010010001000010100
(~i) >>> 5, int: 36625899, binary:
10001011101101110111101011
*/
long l = rand.nextLong();
long m = rand.nextLong();
printBinaryLong("-1L", -1L);
printBinaryLong("+1L", +1L);
long ll = 9223372036854775807L;
printBinaryLong("maxpos", ll);
long lln = -9223372036854775808L;
printBinaryLong("maxeng", lln);
printBinaryLong("l", l);
printBinaryLong("m", m);
printBinaryLong("~m", ~m);
printBinaryLong("-l", -l);
printBinaryLong("l & m", l & m);
printBinaryLong("l | m", l | m);
printBinaryLong("l ^ m", l ^ m);
printBinaryLong("l << 5", l << 5);
printBinaryLong("l >> 5", l >> 5);
printBinaryLong("(~l) >> 5", (~l) >> 5);
printBinaryLong("l >>> 5", l >>> 5);
printBinaryLong("(~l) >>> 5", (~l) >>> 5);
/* Output:
-1L, Long: -1, binary:
1111111111111111111111111111111111111111111111111111111111111111
+1L, Long: 1, binary:
1
maxpos, Long: 9223372036854775807, binary:
111111111111111111111111111111111111111111111111111111111111111
maxeng, Long: -9223372036854775808, binary:
1000000000000000000000000000000000000000000000000000000000000000
l, Long: -8652529054300476342, binary:
1000011111101100000010101010101100001101101011000110110001001010
m, Long: 2955289354441303771, binary:
10100100000011010011000000001010010011111101111010011011011011
~m, Long: -2955289354441303772, binary:
1101011011111100101100111111110101101100000010000101100100100100
-l, Long: 8652529054300476342, binary:
111100000010011111101010101010011110010010100111001001110110110
l & m, Long: 72066398748419146, binary:
100000000000010000000001000000001101001000010010001001010
l | m, Long: -5769306098607591717, binary:
1010111111101111010011101010101110011111111111111110111011011011
l ^ m, Long: -5841372497356010863, binary:
1010111011101111010001101010100110011110010110111100101010010001
l << 5, Long: -179768631971968704, binary:
1111110110000001010101010110000110110101100011011000100101000000
l >> 5, Long: -270391532946889886, binary:
1111110000111111011000000101010101011000011011010110001101100010
(~l) >> 5, Long: 270391532946889885, binary:
1111000000100111111010101010100111100100101001110010011101
l >>> 5, Long: 306069219356533602, binary:
10000111111011000000101010101011000011011010110001101100010
(~l) >>> 5, Long: 270391532946889885, binary:
1111000000100111111010101010100111100100101001110010011101
*/
printBinaryLong("i ^ m", i ^ m);
/* Output:
* i ^ m, Long: -2955289355552037810, binary:
* 1101011011111100101100111111110100101001110100111110010001001110
*/
char cone = 'a';
int conei = 'a';
char ctwo = 2;
char cthree = '0';
printBinaryInt("cthree", cthree);
cthree = (char) (cone + ctwo);
printBinaryInt("cone", cone);
printBinaryInt("conei", conei);
printBinaryInt("ctwo", ctwo);
printBinaryInt("cthree", cthree);
/* Output:
* 扩展
cthree, int: 48, binary:
110000
cone, int: 97, binary:
1100001
conei, int: 97, binary:
1100001
ctwo, int: 2, binary:
10
cthree, int: 99, binary:
1100011
*/
} public void printBinaryInt(String s, int i) {
System.out.println(s + ", int: " + i + ", binary:\n " + Integer.toBinaryString(i));
}
public void printBinaryLong(String s, Long l) {
System.out.println(s + ", Long: " + l + ", binary:\n " + Long.toBinaryString(l));
}
3.12 三元操作符if-else
三元操作符: boolean-exp ? value0 : value1
也可以换用普通的if-else语句(在后面介绍),但三元操作符更加简洁。
3.13 字符串操作符+和+=
引入了操作符重载(operator overloading)机制。表达式以一个字符串起头,那么后续所有操作数都必须是字符串型。
3.14 使用操作符时常犯的错误
while(x=y){
//......
}
不会得到编译时错误的情况是x和y都为布尔值。在这种情况下,x=y属于合法表达式。
3.15 类型转换操作符
如果要执行一种名为窄化转换(narrowing conversion)的操作(也就是说,将能容纳更多信息的数据类型转换成无法容纳那么多信息的类型),就有可能面临信息丢失的危险。而对于扩展转换(widelung conversion).则不必显式地进行类型转换,因为新类型肯定能容纳原来类型的信息,不会造成任何信息的丢失。
Java允许我们把任何基本数据类型转换成别的基本数据类型,但布尔型除外,后者根本不允许进行任何类型的转换处理。“类”数据类型不允许进行类型转换。
对象可以在其所属类型的类族之间可以进行类型转换,例如,“橡树”可转型为“树”,反之亦然。但不能把它转换成类族以外的类型,如“岩石”。
3.15.1 截尾和舍入
将float或double转型为整型值时,总是对该数字执行截尾。如果想要得到舍入的结果,就需要使用java.lang.Math中的round()方法。
3.15.2 提升
表达式中出现的最大的数据类型决定了表达式最终结果的数据类型。如果将二个float值与一个double值相乘,结果就是double,如果将一个int和一个long值相加,则结果为long。
3.16 Java没有sizeof
在C和C++中,sizeof()操作符可以告诉你为数据项分配的字节数。在C和C++中,需要使用sizeof()的最大原因是为了“移植”。不同的数据类型在不同的机器上可能有不同的大小,所以在进行一些与存储空间有关的运算时,程序员必须获悉那些类型具体有多大。Java不需要sizeof()操作符来满足这方面的需要,因为所有数据类型在所有机器中的大小都是相同的。
3.17 操作符小结
//:operators/AllOps.java
//Tests all the operators on all the primitive data types to show which ones are //accepted by the Java compiler. public class AllOps{
//To accept the results of a boolean test:
void f(boolean b){ } void boolTest(boolean x, boolean y){
//Arithmetic operators:
//! x=x*y;
//! x=x/y;
//! x=x%y;
//! x=x+y;
//! x=x-y;
//! x++;
//! x--;
//! x=+y;
//! x=-y;
//Relational and logical:
//! f(x>y);
//! f(x>=y);
//! f(x<y);
//! f(x<=y);
f(x == y);
f(x != y);
f(!y);
x = x && y;
x = x || y;
//Bitwise operators:
//! x=~y;
x = x & y;
x = x | y;
x = x ^ y;
//! x=x<<1;
//! x=x>>1;
//! x=x>>>1;
//Compound assignment:
//! x+=y;
//! x-=y;
//! x*=y;
//! x/=y;
//! x%=y;
//! x<<=1;
//! x>>=1;
//! x>>>=1;
x &= y;
x ^= y;
x |= y;
//Casting:
//! char c=(char)x;
//! byte b=(byte)x;
//! short s=(short)x;
//! int i=(int)x;
//! long l=(long)x;
//! double d=(double)x;
} void charTest(char x, char y){
//Arithmetic operators:
x = (char) (x * y);
x = (char) (x / y);
x = (char) (x % y);
x = (char) (x + y);
x = (char) (x - y);
x++;
x--;
x = (char) +y;
x = (char) -y;
//Relational and logical
f(x > y);
f(x >= y);
f(x < y);
f(x <= y);
f(x == y);
f(x != y);
//! f(!x);
//! f(x&&y);
//! f(x||y);
//Bitwise operators:
x = (char) ~y;
x = (char) (x & y);
x = (char) (x | y);
x = (char) (x ^ y);
x = (char) (x << 1);
x = (char) (x >> 1);
x = (char) (x >>> 1);
//Compound assignment:
x += y;
x -= y;
x *= y;
x /= y;
x %= y;
x <<= 1;
x >>= 1;
x >>>= 1;
x &= y;
x ^= y;
x |= y;
//Casting:
//! boolean b1=(boolean)x;
byte b = (byte) x;
short s = (short) x;
int i = (int) x;
long l = (long) x;
float f = (float) x;
double d = (double) x;
} void byteTest(byte x, byte y){
//Arithmetic operators:
x = (byte) (x * y);
x = (byte) (x / y);
x = (byte) (x % y);
x = (byte) (x + y);
x = (byte) (x - y);
x++;
x--;
x = (byte) +y;
x = (byte) -y;
//Relational and logical
f(x > y);
f(x >= y);
f(x < y);
f(x <= y);
f(x == y);
f(x != y);
//! f(!x);
//! f(x&&y);
//! f(x||y);
//Bitwise operators:
x = (byte) ~y;
x = (byte) (x & y);
x = (byte) (x | y);
x = (byte) (x ^ y);
x = (byte) (x << 1);
x = (byte) (x >> 1);
x = (byte) (x >>> 1);
//Compound assignment:
x += y;
x -= y;
x *= y;
x /= y;
x %= y;
x <<= 1;
x >>= 1;
x >>>= 1;
x &= y;
x ^= y;
x |= y;
//Casting:
//! boolean b1=(boolean)x;
char c = (char) x;
short s = (short) x;
int i = (int) x;
long l = (long) x;
float f = (float) x;
double d = (double) x;
} void shortTest(short x, short y){
//Arithmetic operators:
x = (short) (x * y);
x = (short) (x / y);
x = (short) (x % y);
x = (short) (x + y);
x = (short) (x - y);
x++;
x--;
x = (short) +y;
x = (short) -y;
//Relational and logical
f(x > y);
f(x >= y);
f(x < y);
f(x <= y);
f(x == y);
f(x != y);
//! f(!x);
//! f(x&&y);
//! f(x||y);
//Bitwise operators:
x = (short) ~y;
x = (short) (x & y);
x = (short) (x | y);
x = (short) (x ^ y);
x = (short) (x << 1);
x = (short) (x >> 1);
x = (short) (x >>> 1);
//Compound assignment:
x += y;
x -= y;
x *= y;
x /= y;
x %= y;
x <<= 1;
x >>= 1;
x >>>= 1;
x &= y;
x ^= y;
x |= y;
//Casting:
//! boolean b1=(boolean)x;
char c = (char) x;
byte b = (byte) x;
int i = (int) x;
long l = (long) x;
float f = (float) x;
double d = (double) x;
} void intTest(int x, int y){
//Arithmetic operators:
x = x * y;
x = x / y;
x = x % y;
x = x + y;
x = x - y;
x++;
x--;
x = +y;
x = -y;
//Relational and logical
f(x > y);
f(x >= y);
f(x < y);
f(x <= y);
f(x == y);
f(x != y);
//! f(!x);
//! f(x&&y);
//! f(x||y);
//Bitwise operators:
x = ~y;
x = x & y;
x = x | y;
x = x ^ y;
x = x << 1;
x = x >> 1;
x = x >>> 1;
//Compound assignment:
x += y;
x -= y;
x *= y;
x /= y;
x %= y;
x <<= 1;
x >>= 1;
x >>>= 1;
x &= y;
x ^= y;
x |= y;
//Casting:
//! boolean b1=(boolean)x;
char c = (char) x;
byte b = (byte) x;
short s = (short) x;
long l = (long) x;
float f = (float) x;
double d = (double) x;
} void longTest(long x, long y){
//Arithmetic operators:
x = x * y;
x = x / y;
x = x % y;
x = x + y;
x = x - y;
x++;
x--;
x = +y;
x = -y;
//Relational and logical
f(x > y);
f(x >= y);
f(x < y);
f(x <= y);
f(x == y);
f(x != y);
//! f(!x);
//! f(x&&y);
//! f(x||y);
//Bitwise operators:
x = ~y;
x = x & y;
x = x | y;
x = x ^ y;
x = x << 1;
x = x >> 1;
x = x >>> 1;
//Compound assignment:
x += y;
x -= y;
x *= y;
x /= y;
x %= y;
x <<= 1;
x >>= 1;
x >>>= 1;
x &= y;
x ^= y;
x |= y;
//Casting:
//! boolean b1=(boolean)x;
char c = (char) x;
byte b = (byte) x;
short s = (short) x;
int i = (int) x;
float f = (float) x;
double d = (double) x;
} void floatTest(float x, float y){
//Arithmetic operators:
x = (x * y);
x = (x / y);
x = (x % y);
x = (x + y);
x = (x - y);
x++;
x--;
x = +y;
x = -y;
//Relational and logical
f(x > y);
f(x >= y);
f(x < y);
f(x <= y);
f(x == y);
f(x != y);
//! f(!x);
//! f(x&&y);
//! f(x||y);
//Bitwise operators:
//! x = (float) ~y;
//! x = (float) (x & y);
//! x = (float) (x | y);
//! x = (float) (x ^ y);
//! x = (float) (x << 1);
//! x = (float) (x >> 1);
//! x = (float) (x >>> 1);
//Compound assignment:
x += y;
x -= y;
x *= y;
x /= y;
x %= y;
//! x <<= 1;
//! x >>= 1;
//! x >>>= 1;
//! x &= y;
//! x ^= y;
//! x |= y;
//Casting:
//! boolean b1=(boolean)x;
char c = (char) x;
byte b = (byte) x;
short s = (short) x;
int i = (int) x;
long l = (long) x;
double d = (double) x;
} void doubleTest(double x, double y){
//Arithmetic operators:
x = (x * y);
x = (x / y);
x = (x % y);
x = (x + y);
x = (x - y);
x++;
x--;
x = +y;
x = -y;
//Relational and logical
f(x > y);
f(x >= y);
f(x < y);
f(x <= y);
f(x == y);
f(x != y);
//! f(!x);
//! f(x&&y);
//! f(x||y);
//Bitwise operators:
//! x = (float) ~y;
//! x = (float) (x & y);
//! x = (float) (x | y);
//! x = (float) (x ^ y);
//! x = (float) (x << 1);
//! x = (float) (x >> 1);
//! x = (float) (x >>> 1);
//Compound assignment:
x += y;
x -= y;
x *= y;
x /= y;
x %= y;
//! x <<= 1;
//! x >>= 1;
//! x >>>= 1;
//! x &= y;
//! x ^= y;
//! x |= y;
//Casting:
//! boolean b1=(boolean)x;
char c = (char) x;
byte b = (byte) x;
short s = (short) x;
int i = (int) x;
long l = (long) x;
} }
在char、byte和short中,我们可看到使用算术操怍符中数据类型提升的效果。对这些类型的任何一个进行算术运算,都会获得一个int结果,必须将其显式地类型转换回原来的类型(窄化转换可能会造成信息的丢失),以将值赋给原本的类型。但对于int值,却不必进行类型转化,因为所有数据都已经属于int类型。但不要放松警惕,认为一切事情都是安全的,如果对两个足够大的int值执行乘法运算,结果就会溢出。下面这个例子向大家展示了这一点:
//:operators/Overflow.java
//Surprise! Java lets you overflow. public class Overflow{
public static void main(String[] args)
{
int big = Integer.MAX_VALUE;
System.out.println("big = " + big);
int bigger = big * 4;
System.out.println("bigger = " + bigger);
}
}/*Output:
big = 2147483647
bigger = -4
*///:~
Java编程思想学习(三)----第三章:操作符的更多相关文章
- [Java编程思想-学习笔记]第3章 操作符
3.1 更简单的打印语句 学习编程语言的通许遇到的第一个程序无非打印"Hello, world"了,然而在Java中要写成 System.out.println("He ...
- Java编程思想学习(五)----第5章:初始化与清理
随着计算机革命的发展,“不安全”的编程方式已逐渐成为编程代价高昂的主因之一. C++引入了构造嚣(constructor)的概念,这是一个在创建对象时被自动调用的特殊方法.Java中也采用了构造器,并 ...
- [Java编程思想-学习笔记]第1章 对象导论
1.1 抽象过程 Java是一门面向对象的语言,它的一个优点在于只针对待解问题抽象,而不用为具体的计算机结构而烦心,这使得Java有完美的移植性,也即Java的口号"Write Once, ...
- Java编程思想学习(四)----第四章:控制执行流程
在Java中,涉及的关键字包括if-else.while.do-while.for.return.break 以及选择语句switch.然而,Java并不支持goto语句(该语句引起许多反对意见,但它 ...
- [Java编程思想-学习笔记]第2章 一切都是对象
2.1 创建新的数据类型:类 通过第一章掌握了面向对象的理论后,我们知道每个对象必定属于一个类型,那么Java如何创建新的数据类型?如下程序所示: class Circle { // 属性 // 方 ...
- [Java编程思想-学习笔记]第4章 控制执行流程
4.1 return 关键字return有两方面的用途:一方面指定一个方法结束时返回一个值:一方面强行在return位置结束整个方法,如下所示: char test(int score) { if ...
- JAVA编程思想读书笔记(三)--RTTI
接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...
- Java编程思想学习(八) 内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类的定义是简单的,但是它的语法确实很是复杂,让人不是很好理解.下面就内部类做一个小结. 一.内部类的分类 总的来讲内部类分为普通内部类,匿 ...
- java编程思想--学习心得
学习Java编程思想,需要了解语言特性,对于各种名词,能够借助项目代码,解释其含义,不借助搜索工具,明白其在什么样场景下使用,会带来什么样的问题,能否避免这类问题. 学习的过程,与软件开发相同,一样是 ...
- Java编程思想学习(一)----对象导论中多态的理解
1.1抽象过程 1)万物皆对象. 2)程序是对象的集合,他们通过发送消息来告知彼此所要求做的. 3)每个对象都有自己的由其他对象所构成的存储. 4)每个对象都拥有其类型. 5)某一特定类型的所有对象都 ...
随机推荐
- Spring Boot:定制自己的starter
在学习Spring Boot的过程中,接触最多的就是starter.可以认为starter是一种服务——使得使用某个功能的开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由Spring Boo ...
- Fiddler--的一些使用技巧
1.Filters请求与响应的会话过滤 请求会话列表中存在上百个请求,怎么过滤想要的,可以启用 Fiddler Filters强大的过滤机制,还可以依据正则来过滤,如: REGEX:(?insx). ...
- 使用UpdatePanel时FileUpload失效的问题
出处:http://www.cnblogs.com/caicainiao/archive/2010/12/08/1900377.html 1.使用UpdatePanel后,FileUpload的Has ...
- 动画基础--基于Core Animation(3)
参考:https://zsisme.gitbooks.io/ios-/content/ 前面的文章动画基础--基于Core Animation(1),动画基础--基于Core Animation(2) ...
- leetcode 之Linked List Cycle(24)
两个思路,一是用哈希表记录每个结点是还被访问过:二是定义两个快.慢指针,如果存在环的话,两个指针必定会在某位结点相遇. bool linkListNode(ListNode *head) { List ...
- linux命令(36):which命令
我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. ...
- JVM字节码执行引擎和动态绑定原理
1.执行引擎 所有Java虚拟机的执行引擎都是一致的: 输入的是字节码文件,处理过程就是解析过程,最后输出执行结果. 在整个过程不同的数据在不同的结构中进行处理. 2.栈帧 jvm进行方法调用和方法执 ...
- 深度学习方法:受限玻尔兹曼机RBM(二)网络模型
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入 上解上一篇RBM(一)基本概念, ...
- 事务管理配置与@Transactional注解使用
spring,mybatis事务管理配置与@Transactional注解使用 概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framewor ...
- nginx实现正向代理和反向代理
注意:nginx正向代理有缺陷,如果同时实现http和https正向代理请使用squid软件 (1)正反向代理 正向代理:实现客户端上网 反向代理:代理访问后端web服务器, 区别:正向代理的对象是客 ...