Java表达式2.0
1 .数据类型转换
自动类型转换的规则
自动类型转换遵循一定的规则,这些规则确保了转换的合理性和安全性。以下是自动类型转换的主要规则:
-
容量小的类型自动转换为容量大的类型
Java中,数据类型的容量从小到大依次为:byte
→short
→int
→long
→float
→double
。当进行算术运算或赋值操作时,如果操作数的类型不同,系统会自动将容量小的类型转换为容量大的类型,以确保运算的正确性和数据的完整性。 -
操作数为
double
型时的转换规则
如果表达式中有一个操作数是double
类型,那么整个表达式的结果会被提升为double
类型。这是因为double
类型具有最高的精度和最大的容量,能够容纳其他类型的数据,从而避免了精度丢失。 -
操作数为
float
型时的转换规则
如果表达式中有一个操作数是float
类型,那么整个表达式的结果会被提升为float
类型。这是因为float
类型比int
、long
等整数类型具有更高的精度,但比double
类型稍低。 -
操作数为
long
型时的转换规则
如果表达式中有一个操作数是long
类型,而没有float
或double
类型的操作数,那么整个表达式的结果会被提升为long
类型。这是因为long
类型比int
类型具有更大的范围,能够容纳更大的整数值。
示例与解释
以下是一些具体的示例,帮助理解自动类型转换的规则:
示例1:操作数为double
型
double result = 10 + 3.5;
-
在这个表达式中,
10
是int
类型,3.5
是double
类型。 -
根据自动类型转换规则,
int
类型的10
会被自动转换为double
类型,然后与3.5
进行加法运算。 -
最终,整个表达式的结果是
13.5
,并且结果的类型是double
。
示例2:操作数为float
型
float result = 10 + 3.5f;
-
在这个表达式中,
10
是int
类型,3.5f
是float
类型。 -
根据自动类型转换规则,
int
类型的10
会被自动转换为float
类型,然后与3.5f
进行加法运算。 -
最终,整个表达式的结果是
13.5f
,并且结果的类型是float
。
示例3:操作数为long
型
long result = 10L + 5;
-
在这个表达式中,
10L
是long
类型,5
是int
类型。 -
根据自动类型转换规则,
int
类型的5
会被自动转换为long
类型,然后与10L
进行加法运算。 -
最终,整个表达式的结果是
15L
,并且结果的类型是long
。
示例4:多个操作数的类型提升
double result = 10 + 5L + 3.5f;
-
在这个表达式中,
10
是int
类型,5L
是long
类型,3.5f
是float
类型。 -
首先,
int
类型的10
会被自动转换为long
类型,与5L
进行加法运算,结果是15L
。 -
然后,
15L
会被自动转换为float
类型,与3.5f
进行加法运算,结果是18.5f
。 -
最后,由于表达式中存在
double
类型的操作数,18.5f
会被自动转换为double
类型,最终结果是18.5
,并且结果的类型是double
。
自动类型转换的意义
自动类型转换在Java中具有重要的意义,它不仅简化了代码的编写,还提高了代码的可读性和可维护性。通过自动类型转换,开发者可以避免显式地进行类型转换,从而减少代码的冗余和出错的可能性。同时,自动类型转换还确保了数据在转换过程中的安全性和准确性,使得开发者可以更加专注于逻辑的实现,而不是类型转换的细节。
注意事项
尽管自动类型转换非常方便,但在某些情况下,开发者仍然需要注意以下几点:
-
精度丢失:虽然自动类型转换会尽量避免精度丢失,但在某些情况下,如将
float
或double
转换为整数类型时,可能会导致精度丢失。 -
范围溢出:如果转换后的类型范围不足以容纳原始数据,可能会导致范围溢出。例如,将一个非常大的
long
值转换为int
类型时,可能会导致数据丢失或错误。 -
显式类型转换:在某些情况下,如果需要将容量大的类型转换为容量小的类型,需要使用显式类型转换(强制类型转换),并注意可能引发的异常。
-
有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的 那种数据类型,再进行计算。
byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
boolean类型不能与其它数据类型运算。
-
int a = 100; long b = 200;
-
b = a + b; System.out.println(b); 计算下列结果?
-
int a = 123; double d = a + 123; System.out.println(d);
-
int b = a /300; System.out.println(b);
强制类型转换
-
条件:转换的数据类型必须是兼容的
-
格式:(数据类型) 变量 , (数据类型) 是强制类型转换后的数据类型。例:
double d = 123.456d;System.out.println(d);int i = d;// 编译不通过int i = (int) d;// 截断操作System.out.println(i);;
-
*注意:强制转换有可能造成数据的缺失或者精度的缺失
编码情况1: long l1 = 123; // ok long l1 = 1234567890123456789; // 编译不通过 System.out.println(l1); float f1 = 12.3; // 编译不通过 // float f1 =(float) 12.3; 编码情况2: 整型常量,默认类型为int型 浮点型常量,默认类型为double类型 byte b = 12; byte b1 = b + 1;// 编译不通过 float f1 = b + 12.3;// 编译不通过 // byte b1 = (byte) (b + 1); // float f1 = (float) (b + 12.3);
2. 作用域
-
变量起作用的范围,称为作用域。
-
范围:变量在哪对大括号中声明定义的,范围就是哪对大括号。
-
在同一个作用域中,不能定义重复的变量。
-
3. 运算符
3.1 算数运算符
-
算术运算符用在数学表达式中,它们的作用和在数学中的作用一样。下表列出了所有的算术运算符。
-
表格中的实例假设整数变量A的值为10,变量B的值为20:
操作符 | 描述 | 例子 |
---|---|---|
+ | 加法:相加运算符两侧的值 | A + B 等于 30 |
- | 减法:左操作数减去右操作数 | A – B 等于 -10 |
* | 乘法:相乘操作符两侧的值 | A * B 等于 200 |
7/2 | 除法:左操作数除以右操作数 | B / A 等于 3 |
% | 取余(取模):左操作数除以右操作数的余数 | B % A 等于 0 |
++ | 自增:操作数的值增加1 | B++ 或 ++B 等于 21 |
-- | 自减:操作数的值减少1 | B-- 或 --B 等于 19 |
-
自增自减运算符
-
基本使用
int a = 5; a++; System.out.println(a); // 此时a的值为6 a--; System.out.println(a); // 此时a的值为5
-
a++
和++a
的区别int a = 5; int b = a++; System.out.println(a); // 6 System.out.println(b); // 5 int c = 5; int d = ++c; System.out.println(c); // 6 System.out.println(d); // 6
-
a++
先赋值后自增 -
++a
先自增后赋值int i = 6; int j = i++ + ++i; int k = --j - i-- - j-- + i++;
-
-
3.2 关系运算符
-
下表为Java支持的关系运算符
-
表格中的实例整数变量A的值为10,变量B的值为20:
运算符 | 描述 | 例子 |
---|---|---|
== | 检查如果两个操作数的值是否相等,如果相等则条件为真。 | (A == B)为假 |
!= | 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 | (A != B)为真 |
> | 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 | (A > B)为假 |
< | 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 | (A < B)为真 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 | (A >= B)为假 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 | (A <= B)为真 |
3.3 逻辑运算符
-
下表列出了逻辑运算符的基本运算,假设布尔变量A为真,变量B为假
运算符 | 说明 |
---|---|
逻辑与 & | 两个条件为true,结果才是true,否则是false |
逻辑或 | | 两个条件有一个是true,结果就是true |
逻辑非 ! | 取反:!false为true,!true为false |
短路与 && | 左侧表达式为false,则直接返回false |
短路或 || | 左侧表达式为true, 则直接返回true |
&”和“&&”的区别
单&时,左边无论真假,右边都进行运算
双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。(一假俱假)
“|”和“||”的区别同理,||表示:当左边为真,右边不参与运算。(一真俱真)
//1>2的结果为false,那么整个表达式的结果即为false,还要计算2>(3/0),因为0不能做除数,所以会输出异常信息 boolean d = 1>2 & 2>(3/0); System.out.println(d); //1>2的结果为false,那么整个表达式的结果即为false,将不再计算2>(3/0) boolean c = 1>2 && 2>(3/0); System.out.println(c);
3.4 赋值运算符
-
下面是Java语言支持的赋值运算符:
操作符 | 描述 | 例子 |
---|---|---|
= | 简单的赋值运算符,将右操作数的值赋给左侧操作数 | C = A + B将把A + B得到的值赋给C |
+= | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 | C += A等价于C = C + A |
-= | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 | C -= A等价于C = C - A |
*= | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 | C *= A等价于C = C * A |
/= | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 | C /= A,C 与 A 同类型时等价于 C = C / A |
3.5 位运算符 (了解)
-
下表列出了位运算符的基本运算,假设整数变量 A 的值为 60 和变量 B 的值为 13:
操作符 | 描述 | 例子 |
---|---|---|
& | 如果相对应位都是1,则结果为1,否则为0。 | (A&B),得到12,即 0000 1100 |
| | 如果相对应位都是0,则结果为0,否则为1。 | (A | B)得到61,即 0011 1101 |
^ | 如果相对应位值相同,则结果为0,否则为1。 | (A ^ B)得到49,即 0011 0001 |
〜 | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 | (〜A)得到-61,即 1100 0011 |
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数。 | A << 2得到240,即 1111 0000 |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 | A >> 2得到15,即 1111 |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 | A >>> 2得到15,即 0000 1111 |
-
注意:
&和|既是逻辑运算符,也是位运算符。如果两侧操作数都是boolean类型,就作为逻辑运算符。如果两侧的操作数是整数类型,就是位运算符。
-
位运算是直接对整数的二进制进行的运算。
public static void main(String[] args) {int a = 60; // 0011 1100int b = 13; // 0000 1101System.out.println(a&b); // 0000 1100System.out.println(a|b); // 0011 1101} public class JavaDemo {public static void main(String[] args) {/*1.位运算符操作的都是整型的数据2.<<在一定范围内,每向左移一位,相当于*2>>在一定范围内,每向左移一位,相当于/2*/int i = 21;System.out.println("i<<2=" + (i << 2));System.out.println("i<<3=" + (i << 3));System.out.println("i<<27=" + (i << 27));System.out.println("i>>2=" + (i >> 2)); } }
-
java中的进制声明
public static void main(String[] args) {int a = 0b11; //声明二进制变量int b = 011; //声明八进制变量int c = 11; //声明十进制变量int d = 0xaabb; //声明十六进制变量System.out.println(a);System.out.println(b);System.out.println(c);System.out.println(d);}
3.6 其他运算符
-
条件运算符(x?y:z)
条件运算符也被称为三元运算符。
其中 x 为 boolean 类型表达式,先计算 x 的值,若为true,则整个运算的结果为表达式 y 的值,否则整个运算结果为表达式 z 的值。
int a = 10; int b = a > 10 ? 10 : 0; class calc {public static void main(String[] arg) {int a = 10;int b = 20;int c = 30;int result = (a > b ? a : b) > c ? (a > b ? a : b) : c;System.out.println(result);} }
-
instanceof 运算符
该运算符用于操作对象实例,检查该对象是否是一个特定类型(类型或接口类型)。
如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。
String name = "James"; boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真
如果被比较的对象兼容于右侧类型,该运算符仍然返回true。
字符串类型:String String不是基本数据类型,属于引用数据类型 使用方式与基本数据类型一致。例如:String str = “abcd”; 一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据。
字符串连接符(+) “+”运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串然后再进行连接。
int a=12; System.out.println("a="+ a);//输出结果: a=12 String a = "3"; int b = 4 ; int c = 5 ; System.out.println(a+b+c); System.out.println(b+c+a);
3.7 运算符优先级
-
算术运算符 > 关系运算符 > 逻辑运算符
-
复杂的运算需要用小括号
()
来强制控制运算顺序,可读性强int a = 3;int b = a += a++;int c = b *= a;