java学习笔记 java编程思想 第3章 操作符

编程入门 行业动态 更新时间:2024-10-05 15:23:15

java<a href=https://www.elefans.com/category/jswz/34/1770117.html style=学习笔记 java编程思想 第3章 操作符"/>

java学习笔记 java编程思想 第3章 操作符

目录

    • 3.1 更简单的打印语句
    • 练习1
    • 3.2 使用Java操作符
    • 3.3 优先级
    • 3.4 赋值
    • 练习2
      • 3.4.1 方法调用中的别名问题
    • 练习3
    • 3.5 算术操作符
    • 练习4
    • 3.6 自动递增和递减
    • 3.7 关系操作符
      • 3.7.1 测试对象的等价性
    • 练习5
    • 练习6
    • 3.8 逻辑运算符
    • 练习7
      • 3.8.1 短路
    • 3.9 直接常量
    • 练习8
      • 3.9.1 指数记数法
    • 练习 9
    • 3.10 按位操作符
    • 练习10
    • 3.11 移位操作符
    • 练习 11
    • 练习 12
    • 练习13
    • 3.12 三元操作符 if-else
    • 3.13 字符串操作符 +和 +=
    • 3.14 使用操作符时常犯的错误
    • 3.15 类型转换操作符
      • 3.15.1 截尾和舍入
      • 3.15.2 提升
    • 3.16 Java没有sizeof()
    • 3.17 操作符小姐
    • 练习14


在最底层,Java中的数据是通过使用操作符来操作的。

3.1 更简单的打印语句

import java.util.Date;
// javase5新增加的概念 静态导入(static import)
import static net.mindview.util.Print.*;public class Test01 {}class HelloDate {public static void main(String[] args) {print("Hello, it's: ");print(new Date());}
}
// 运行结果
Hello, it's: 
Sat Mar 27 20:19:13 CST 2021

练习1

import static  net.mindview.util.Print.*;public class Exec01 {public static void main(String[] args) {System.out.println("Hello");print("Hello");}
}
// 运行结果
Hello
Hello

3.2 使用Java操作符

大股份操作符都操作基本数据类型,而“=”、“==”、“!=”还可以操作对象。此外,String类支持“+”和“+=”。

3.3 优先级

在字符串中,“+”的意思是“字符串连接”。

public class Test02 {public static void main(String[] args) {int x = 1, y = 2, z = 3;int a = x + y - 2/2 + z;  // 5int b = x + (y - 2) / (2 + z);  // 1System.out.println("a="  + a + ", b=" + b);}
}
// 运型结果
a=5, b=1

3.4 赋值

赋值使用操作符“=”。意思是:取右边的值(即右值),把它估值给左边(即左值)。

  • 右值:可以是任何常数、变量、表达式(只要能生成一个值就能当作右值)。
  • 左值:必须是一个明确的、已命名的变量。常数不能作为左值。也就是说,必须有一个物理空间可以存储等号右边的值。
a = 4;

对基本数据类型的赋值,使用a=b,修改a的内容,b的内容不会受到这中修改的影响。

但是在为对象赋值时,就发生了变化。对一个对象进行操作时,其实真正操作的是对象的引用。

代码实例

import static net.mindview.util.Print.*;public class Test03 {public static void main(String[] args) {Tank t1 = new Tank();Tank t2 = new Tank();t1.level = 9;t2.level = 10;print("1: t1:level=" + t1.level + ", t2:level=" + t2.level);// t1也指向了t2指向的那个level=10的对象,// 之前t1指向的那个level=9的对象没有任何引用指向它,会被垃圾回收器自动清理。t1 = t2;print("1: t1:level=" + t1.level + ", t2:level=" + t2.level);t1.level = 2222;print("1: t1:level=" + t1.level + ", t2:level=" + t2.level);}
}class Tank {int level;
}
// 运行结果
1: t1:level=9, t2:level=10
2: t1:level=10, t2:level=10
3: t1:level=2222, t2:level=2222

这中现象称为“别名现象”,它是java操作对象的一种的方式。

// 避免别名问题的办法就是不进行引用赋值,而是将对象里面的基本类型进行赋值。
t1.level = t2.level;

这样做可以保持连个对象彼此相互对立。但是直接操作对象内的域容易导致混乱,违背了面向对象程序设计的原则。这可不是小问题,所有从现在开始就应该注意,为对象赋值可能会产生意想不到的结果。

练习2

public class Exec02 {public static void main(String[] args) {Student stu1 = new Student();Student stu2 = new Student();stu1.score = 99;stu2.score = 80;System.out.println("1: stu1: score=" + stu1.score + ", stu2: score=" + stu2.score);stu1 = stu2;System.out.println("2: stu1: score=" + stu1.score + ", stu2: score=" + stu2.score);stu2.score = 89.0f;System.out.println("3: stu1: score=" + stu1.score + ", stu2: score=" + stu2.score);}
}class Student {int sno;float score;
}// 运行结果
1: stu1: score=99.0, stu2: score=80.0
2: stu1: score=80.0, stu2: score=80.0
3: stu1: score=89.0, stu2: score=89.0

3.4.1 方法调用中的别名问题

将一个对象传递给方法时,也会出现别名问题。

代码示例

import static net.mindview.util.Print.print;public class PassObject {public static void f(Letter y) {y.c = 'z';}public static void main(String[] args) {Letter l = new Letter();l.c = 'a';print("1: c=" + l.c);// 传递引用,f(Letter y)会将传入的引用l复制一份,赋值给局部变量y// 实际改变的是f()之外的对象f(l);print("2: c=" + l.c);}
}
class Letter {char c;
}
// 运行结果
1: c=a
2: c=z

练习3

import static net.mindview.util.Print.print;public class Exec03 {float score;public static void main(String[] args) {Exec03 e = new Exec03();e.score = 10.0f;print("1: score=" + e.score);e.method1(e);print("2: score=" + e.score);}public void method1(Exec03 obj) {obj.score = 20.0f;}
}
// 运行结果
1: score=10.0
2: score=20.0

3.5 算术操作符

+, -, *, /, %
+=, -=. *=, /=, %=

练习4

import static net.mindview.util.Print.print;public class Exec04 {public static void main(String[] args) {Vehicle vehicle1 = new Vehicle();vehicle1.distance = 50;vehicle1.time = 0.5;// 车辆行驶的平均速度 单位:km/hdouble velocity = vehicle1puteVelocityByDistanceAndTime(vehicle1.distance, vehicle1.time);print("d=" + vehicle1.distance + "km, t=" + vehicle1.time + "h, v=" + velocity + "km/h");}}
class Vehicle {double distance;  // 车辆行驶路程 单位:kmdouble time;  // 车辆行驶时间 单位:hourpublic double computeVelocityByDistanceAndTime(double d, double t) {return d / t;}
}
// 运行结果
d=50.0km, t=0.5h, v=100.0km/h

3.6 自动递增和递减

代码

import static net.mindview.util.Print.print;public class Test05 {public static void main(String[] args) {int i = 1;print("i : " + i);  // 1print("++i : " + ++i);  // 2print("i++ : " + i++);  // 2print("i : " + i);  // 3print("--i : " + --i);  // 2print("i-- : "  + i--);  // 2print("i : " + i);  // 1}
}
// 运行结果
i : 1
++i : 2
i++ : 2
i : 3
--i : 2
i-- : 2
i : 1

3.7 关系操作符

3.7.1 测试对象的等价性

class EquivalenceInteger {public static void main(String[] args) {// 因为不通过new创建对象,直接使用字面值赋值,s1和s2都指向同一个地址,即整数常量池中的10的地址Integer n1 = 10;Integer n2 = 10;System.out.println(n1 == n2);  // trueSystem.out.println(n1 != n2);  // false// 通过new创建了两个对象,s1和s2分别指向了两个对象。// ==和!=都比较的是堆中对象的的地址值。Integer n3 = new Integer(10);Integer n4 = new Integer(10);System.out.println(n3 == n4);  // falseSystem.out.println(n3 != n4);  // true}
}
// 运行结果
true
false
false
trueclass EqualMethod {public static void main(String[] args) {Integer n1 = new Integer(10);Integer n2 = new Integer(10);System.out.println(n1.equals(n2));  // true}
}
// 运行结果
trueclass Value {int i;
}class EqualMethod2 {public static void main(String[] args) {Value v1 = new Value();Value v2 = new Value();// 因为equals()方法默认是比较引用的,两个引用不一样所以说false。System.out.println(v1.equals(v2));  // false}
}
// 运行结果
false

练习5

public class Exec05 {public static void main(String[] args) {Dog d1 = new Dog();d1.name = "spot";d1.says = "Ruff!";Dog d2 = new Dog();d2.name = "scruffy";d2.says = "Wurf!";System.out.println(d1.name + ", " + d1.says);System.out.println(d2.name + ", " + d2.says);}
}class Dog {String name;String says;
}
// 运行结果
spot, Ruff!
scruffy, Wurf!

练习6

public class Exec06 {public static void main(String[] args) {Cat c1 = new Cat();c1.name = "spot";c1.says = "Ruff!";Cat c2 = new Cat();c2.name = "scruffy";c2.says = "Wurf!";Cat c = c1;System.out.println(c == c1);  // trueSystem.out.println(c.equals(c1));  // true}
}class Cat {String name;String says;
}
// 运行结果
true
true

3.8 逻辑运算符

&&, ||, !

逻辑运算符只能用在布尔值上,这与C/C++不一样。

整数类型不能转换为布尔类型,其他类型都可以转换。

练习7

import java.util.Random;public class Exec07 {public static void main(String[] args) {Coin coin = new Coin();Exec07 t = new Exec07();int count = 0;System.out.println("=========开始扔硬币============");while ( count++ < 10) {System.out.print("第" + count +"次: ");t.throwCoin(coin);coin.show();}}public void throwCoin(Coin coin) {Random random = new Random();int n = random.nextInt(1000);coin.isPositive = n % 2 == 0;}
}class Coin {boolean isPositive;public void show() {if (isPositive) System.out.println("正面");else System.out.println("反面");}
}
// 运行结果
=========开始扔硬币============
第1次: 反面
第2次: 反面
第3次: 反面
第4次: 正面
第5次: 反面
第6次: 正面
第7次: 反面
第8次: 正面
第9次: 反面
第10次: 反面

3.8.1 短路

import static net.mindview.util.Print.*;public class Test07 {public static void main(String[] args) {Test07 t = new Test07();// test3(1)没有执行boolean ret = t.test1(0) && t.test2(4) && t.test3(1);System.out.println(ret);}public boolean test1(int val) {print("test(" + val + ")");print("result: " + (val < 1));return val < 1;}public boolean test2(int val) {print("test(" + val + ")");print("result: " + (val < 2));return val < 2;}public boolean test3(int val) {print("test(" + val + ")");print("result: " + (val < 2));return val < 3;}
}
// 运行结果
test(0)
result: true
test(4)
result: false
false

3.9 直接常量

直接常量的后缀字符表示类型,

类型后缀字符前缀字符
longL或者l-
floatF或者f-
doubleD或者d-
十六进制数-0x或者0X
八进制数-0

C/C++和java中没有二进制数的直接常量表示法。其他进制数可以通过IntegerLongtoBinaryString()方法,自动转化为int,显示二进制数。

练习8

public class Exec08 {public static void main(String[] args) {long x = 0x1L;long y = 0xAL;long w = 01L;long v = 010L;System.out.println("x = " + Long.toBinaryString(x));System.out.println("y = " + Long.toBinaryString(y));System.out.println("x + y = " + Long.toBinaryString(x + y));System.out.println("w = " + Long.toBinaryString(w));System.out.println("v = " + Long.toBinaryString(v));System.out.println("w + v = " + Long.toBinaryString(w + v));}
}
// 运行结果
x = 1
y = 1010
x + y = 1011
w = 1
v = 1000
w + v = 1001

3.9.1 指数记数法

练习 9

public class Exec09 {public static void main(String[] args) {float minFloat = 1.4E-45f;float maxFloat = 3.4028235E38f;System.out.println("float min=" + minFloat + ", max=" + maxFloat);double minDouble = 4.9E-324d;double maxDouble = 1.7976931348623157E308d;System.out.println("double min=" + minDouble + ", max=" + maxDouble);}
}
// 运行结果
float min=1.4E-45, max=3.4028235E38
double min=4.9E-324, max=1.7976931348623157E308

3.10 按位操作符

&, |, ~, ^
&=, |=, ^=

按位操作符,不会“短路”。在移位表达式中,不能使用别运算,原因将在后面解释。

练习10

public class Exec10 {public static void main(String[] args) {int x = 0x55;int y = 0xAA;System.out.printf("%8s\n", Integer.toBinaryString(x));System.out.printf("%8s\n", Integer.toBinaryString(y));}
}
// 运行结果1010101
10101010

3.11 移位操作符

<<, >>, <<<, >>>
<<=, >>=, <<<=, >>>=

为了防止移位超出最大位数:对charbyteshort进行移位,进行移位之前,先会转换为int类型,计算结果也是int值,只有数值低5位有用(因为2的5次方是32,int类型数值只有32位)。long类型的值,结果long,只有低6位有用。

如果对byteshort进行无符号左移和无符号右移位运算时,可能会出现结果会不正确。因为在移位之前,会转换为int类型,再右移,然后将结果截断,赋值给原来的类型,这个过程可能会出现结果是-1的情况。

import static net.mindview.util.Print.*;public class Test08 {public static void main(String[] args) {int x = -1;// 负数使用的是补码// -1的原码是10000000 00000000 00000000 00000001// -1的反码是11111111 11111111 11111111 11111110// -1的补码是11111111 11111111 11111111 11111111print(Integer.toBinaryString(x));  // 11111111 11111111 11111111 11111111// x无符号右移10位,位x >>>= 10;// 将x的补码无符号右移10位的00000000 11111111 11111111 11111111print(Integer.toBinaryString(x)); // 11111111 11111111 11111111long y = -1;// -1 的原码是 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001// -1 的反码是 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111110// -1 的补码是 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111print(Long.toBinaryString(y));  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111y >>>= 10;print(Long.toBinaryString(y));  // 00000000 00111111 11111111 11111111 11111111 11111111 11111111 11111111short s = -1;// -1 的原码是 10000000 00000001// 先将short类型,转换为int类型 10000000 00000000 00000000 00000001// 然后后面的计算和int一样了print(Integer.toBinaryString(s));s >>>= 10;// 11111111 11111111 11111111 11111111// 右移10位是  00111111 11111111 11111111// 然后截取 11111111 11111111print(Integer.toBinaryString(s));byte b = -1;print(Integer.toBinaryString(b));// 这个移位运算的结果,没有赋值给b,而是直接打印出来的int类型,没有截断,所以结果数正确的。print(Integer.toBinaryString(b>>>10));}
}

练习 11

public class Exec11 {public static void main(String[] args) {int x = 0x80000000;for (int i = 0; i < 32; i++) {x >>>= 1;System.out.println(Integer.toBinaryString(x));}}
}
// 运行结果
1000000000000000000000000000000
100000000000000000000000000000
......
100
10
1
0

练习 12

public class Exec12 {public static void main(String[] args) {int x = 0xffffffff;x <<= 5;System.out.println(Integer.toBinaryString(x));for (int i = 0; i < 32; i++) {x >>>= 1;System.out.println(Integer.toBinaryString(x));}}
}
// 运行结果
11111111111111111111111111100000
1111111111111111111111111110000
111111111111111111111111111000
11111111111111111111111111100
1111111111111111111111111110
111111111111111111111111111
.......
11
1
0

练习13

public class Exec13 {public static void main(String[] args) {char ch = '~';// 126=0111 1110show(ch);}public static void show(char ch) {System.out.println(Integer.toBinaryString(ch));}
}
// 运行结果
1111110

3.12 三元操作符 if-else

boolean-exp ? value0 : value1

如果boolean-exp(布尔表达式)为true,就计算value0,value0就是最终整个三元操作符的值。如果boolean-exp(布尔表达式)为false,就计算value1。value1就是最终整个三元操作符的值。

3.13 字符串操作符 +和 +=

在字符串中的用途:连接不同的字符串、

这是是一种操作符重载(operator overloading)。

public class Test09 {public static void main(String[] args) {int x = 0, y = 1, z = 2;String s = "x, y, z";print(s + x + y + z);  // x, y, z012print(x + " " + s);  // 0 x, y, zs += "(summed) =";print(s + (x + y + z));  // x, y, z(summed) =3// 基本类型转换为字符串常用的方法print("" + x);  // 0}
}
// 运行结果
x, y, z012
0 x, y, z
x, y, z(summed) =3
0

3.14 使用操作符时常犯的错误

while(x = y) {// ...
}

在java中,x = y不会像C/C++那样,会将int类型转换为boolean类型,导致死循环。

但是,在java中,有和C/C++一样的问题,就是使用按位与(&)、按位或(|)代替逻辑与(&&)、逻辑或(||),但是操作数必须是boolean类型。

  • &:不是短路运算。当操作数全部是整型数值或者可与转换为整型数值时,是位运算符,进行位运算。当操作数全部为布尔类型时,是逻辑运算符。

3.15 类型转换操作符

java中有两种类型转换:

  • 隐式类型转换:将一种数据类型自动转换为另一种类型,不需要显示的声明。如:10 / 3.0 的结果是3.3333333333333335

    public class A {public static void main(String[] args) {int a = 10;System.out.println(a / 3);      // 3System.out.println(a / 3.0);    // 3.3333333333333335} 	
    }
    
  • 显示类型转换:将想要转换的数据类型放到圆括号里面,可以显式的进行数据类型的转换,或者在不能自动进行准换的时候强制进行类型转换。

    public class A {public static void msin(String[] args) {int i = 100;// 对变量进行类型转换long a = (long) i;// 对数值进行类型转换long b = (long) 200.1;String s = "10";// int b = (int) s;    // 编译时的错误: 不兼容的类型: String无法转换为int}
    }
    

从信息是否丢失的角度,分为:

  • 窄化转换(narrowing conversion):将能容纳信息多的类型转换为容纳信息少的数据类型,这可能会造成信息地丢失。编译器会提示需要显示转换。
  • 扩展转换(widening conversion):不会造成信息丢失,编译器不会提示需要显示转换。

java允许把任何基本数据类型转换为别的基本类数据型,但布尔类型除外。“类”数据类型不允许随意进行类型转换,必须在其所属类型的类族之间进行类型转换。

3.15.1 截尾和舍入

在进行narrowing conversion时,必须注意截尾和舍入问题。不管是float还是是double类型,转换为int时,总是将数字截尾,不是四舍五入。

public class A {public static void main(String[] args) {float fa = 21.7f;float fb = 21.4f;double da = 21.7;double db = 21.4;System.out.println("(int)fa : " + (int)fa);  // 21System.out.println("(int)fb : " + (int)fb);  // 21System.out.println("(int)da : " + (int)da);  // 21System.out.println("(int)db : " + (int)db);  // 21}
}

如果想四舍五入,需要使用java.lang.Math类中的round()方法。

public class A {public static void main(String[] args) {float fa = 21.7f;float fb = 21.4f;double da = 21.7;double db = 21.4;System.out.println("Math.round(fa) : " + Math.round(fa));  // 22System.out.println("Math.round(fb) : " + Math.round(fb));  // 21System.out.println("Math.round(da) : " + Math.round(da));  // 22System.out.println("Math.round(db) : " + Math.round(db));  // 21}
}

3.15.2 提升

除布尔类型的其他基本数据类型,执行算术运算或按位运算,会将类型小的,自动转换为类型大的。比如:

  • byte类型进行位运算:会先自动转换为int类型,然后再进行位运算,最后的结果是int类型的数值。
  • int类型和double类型相加:会先将int类型转换为double类型,然后再在相加,最后的结果是double类型的数值。

3.16 Java没有sizeof()

C/C++中,sizeof()可以得到系统为某个数据分配的字节数。这最大的原因是为了“移植”。在不同机器上,数据类型的字节数可能不同。

java不需要sizeof()操作符,因为所有数据类型在所有的机器上大小都是相同的。

3.17 操作符小姐

必须注意narrowing conversion的结果,否则会造成信息地丢失。

布尔类型没有运算,智能赋值为true或false,测试它是否为true或false。布尔值不能相加相减。

chart、byte和short在运算过程中,会自动进行数据类型提升为int类型,得到的结果是int值,必须显式类型转换为指定的类型。

对两个较大的int类型值座乘法运算,有很大可能会溢出,但是编译器部署提示任何警告或异常。

// 因为int的最大值是2147483647,100000 * 100000的结果为10000000000大于2147483647,产生溢出。
public class A {public static void main(String[] args) {int a = 100000;int b = 100000;System.out.println( a * b);  // 1410065408}
}

练习14

public class Exec14 {public static void main(String[] args) {compareTwoStr("asdf", "asdf");compareTwoStr("asd", "asdf");}public static void compareTwoStr(String s1, String s2) {System.out.println("" + s1 + " == " + s2 + ": " + (s1 == s2));System.out.println("" + s1 + " != " + s2 + ": " + (s1 != s2));System.out.println("" + s1 + ".equals(" + s2 + "): " + (s1.equals(s2)));}
}
// 运行结果
asdf == asdf: true
asdf != asdf: false
asdf.equals(asdf): true
asd == asdf: false
asd != asdf: true
asd.equals(asdf): false

更多推荐

java学习笔记 java编程思想 第3章 操作符

本文发布于:2024-02-28 06:19:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1768679.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学习笔记   思想   操作   java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!