- 整数类型:
byte、short、int、long - 浮点数类型:
float、double - 字符类型:
char - 布尔类型:
boolean byte:1字节,-128 ~ 127short:2字节,-32768 ~ 32767int:4字节,-2147483648 ~ 2147483647long:8字节,-9223372036854775808 ~ 9223372036854775807float:4字节,3.4x1038double:8字节,1.79x10308char:2字节与运算,两个操作数,必须都是1,结果才是1或运算,两个操作数,其中一个1,结果就是1非运算,一个操作数,结果是其相反值,即:1的结果是0;0的结果是1异或运算,两个操作数,两者不同才是1,否则是0()!~++--*/%+-<<>>>>>&|+=-=*=/=NaN表示Not a NumberInfinity表示无穷大-Infinity表示负无穷大- 比较运算符:
>,>=,<,<=,==,!= - 与运算
&& - 或运算
|| - 非运算
! !>,>=,<,<===,!=&&||- 创建一个字符串
hello - 将变量
s指定hello - 创建一个字符串
world - 再将变量
s指定world - 数组所有元素初始化为默认值,整型是
0,浮点型是0.0,布尔型是false; - 数组创建后大小不可变
2. 变量与数据类型概述
基本数据类型(值类型):
各种类型内存大小及可表示数据大小
计算机中最小表示单位byte(字节,B),1字节可表示8位二进制,即8bit(位,b)。可表示范围:为28,即00000000~11111111,也即十进制的0~255,也即十六进制的00~FF
可表示数据大小
浮点数
float f1 = 3.4f;
float f2 = 3.4e38f; // 科学计数法表示的3.14x10^38
double d1 = 1.79;
double d2 = 1.79e308;
float类型变量需要加上f后缀,最大可表示3.4x1038
double最大可表示3.4x1038
float和double均支持科学计数法表示
字符类型
char用于表示一个,在Java中除可表示ASCII外,还可表示Unicode字符。char类型使用'(单引号)区分。
布尔型
boolean只有两个值true和false
boolean b1 = true; boolean b2 = false; boolean isGreater = 5 > 3; // 计算结果为true
常量
在变量前增加final关键字。按语言习惯,常量定义一般使用大写字母。
var关键字与类型推断
可以用var关键字来定义变量,编译器会根据赋值语句自动推断变量类型:
var sb = new StringBuilder();
变量作用域
在语句块({}内)中定义变量时应该注意,每个变量都有其作用范围。在内层括号内定义的变量,不能在外层括号(括号外)访问;但外层定义的,可以在内层括号内访问。要遵循作用域最小化原则,尽量将变量定义在尽可能小的作用域,并且,不要重复使用变量名。
{
...
int i = 0; // 变量i从这里开始定义
...
{
...
int x = 1; // 变量x从这里开始定义
...
{
...
String s = "hello"; // 变量s从这里开始定义
...
} // 变量s作用域到此结束
...
// 注意,这是一个新的变量s,它和上面的变量同名,
// 但是因为作用域不同,它们是两个不同的变量:
String s = "hi";
...
} // 变量x和s作用域到此结束
...
} // 变量i作用域到此结束
3. 整数
整数运算
整数运算与数学中的四则运算规则一致,包括:加(+)、减(-)、乘(*)、除(/)、括号(())等:
public class Main {
public static void main(String[] arg) {
int i = (100+99)*(88+99);
int j = 10*(5+8)/5;
System.out.println(i); // 37213
System.out.println(j); // 26
}
}
自增/自减
Java中使用++表示自增,使用--表示自减,分别表示对整数进行加1和减1操作:
int n = 1; n++; System.out.println(n); // 2 int y= 1+(++n); // ++ 写在前面,表示先对执行自增,再进行引用。也即:n会变成3 System.out.println(y); // 4 System.out.println(n); // 3 System.out.println(n++); // 3, ++ 写在后台,表示先引用再自增
++(或--)写在变量前面和后台是有区别的,写变量前面(++n)表示先对变量自增再引用;而写在后面(n++)表示先对变量引用,再自增。在实际使用中应该注意。
位移
位移是对二进制形式的整数,进行左移(<<)或右移>>。如:
int n = 3; // 二进制形式为:00000000 00000000 00000000 00000011 int a = n<<1; int b = n>>1; System.out.println(a); // 6,即:00000000 00000000 00000000 00000110 System.out.println(b); // 1,即:00000000 00000000 00000000 00000001
位运算的符号位
整数最高位为符号位,将3左移30位,其值会变成负数;
int n = 3; System.out.println(n<<29); // 1610612736,即:01100000 00000000 00000000 00000000 System.out.println(n<<30); // -1073741824,即:11000000 00000000 00000000 00000000
类似的,对正数进行右移超出其二进制长度,将变成0。而对负数进行位移时,其符号位保持不动,其结果仍是一个负数:
int n = 3; System.out.println(n>>2); // 0, 即: 00000000 00000000 00000000 00000000 System.out.println(n>>3); // 0, 即: 00000000 00000000 00000000 00000000 n = -3; System.out.println(n>>2); // -1, 即: 11111111 11111111 11111111 11111111 System.out.println(n>>3); // -1, 即: 11111111 11111111 11111111 11111111
对于右移来说,可以使用>>>,右移时符号位会跟随移动,会使负数变成正数:
int n = -3; System.out.println(n>>>30); // -1, 即: 00000000 00000000 00000000 00000011
对byte和short类型进行移位时,会首先转换为int再进行位移。
位运算
位运算是按位(二进制)进行与(&)、或(|)、非(~)和异或(^)运算。规则是:
// 与运算 n = 0 & 0; // 0 n = 0 & 1; // 0 n = 1 & 0; // 0 n = 1 & 1; // 1 // 或运算 n = 0 | 0; // 0 n = 0 | 1; // 1 n = 1 | 0; // 1 n = 1 | 1; // 1 // 非运算 n = ~0; // 1 n = ~1; // 0 // 异或运算 n = 0 ^ 0; // 0 n = 0 ^ 1; // 1 n = 1 ^ 0; // 1 n = 1 ^ 1; // 0
基于以上规则,对两个整数进行位运算时:
int n = 3; // 二进制形式为:00000000 00000000 00000000 00000011 int i = 2; // 二进制形式为:00000000 00000000 00000000 00000010 System.out.println(n&i); // 2, 即: 00000000 00000000 00000000 00000010 System.out.println(n|i); // 3, 即: 00000000 00000000 00000000 00000011 System.out.println(n^i); // 1, 即: 00000000 00000000 00000000 00000001
运算符优先级
类型自动提升与强制转型
如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。如果,short与int运算,short会自动转为int类型
还可以使用(类型)强制类型转换,强制类型转换可能会造成精度丢失,超出范围时,高位字段会被直接丢掉:
int i1 = 1234567; short s1 = (short) i1; // -10617
4. 浮点数运算
浮点数只能进行四则运算(加减乘除),不能进行位运算和移位运算。
在计算机中,浮点数虽然表示的范围大,但是,浮点数有个非常重要的特点,就是浮点数常常无法精确表示。所以,浮点数运算也会产生误差:
double x = 1.0 / 10; double y = 1 - 9.0 / 10; System.out.println(x); // 0.1 System.out.println(y); // 0.09999999999999998
类型提升
如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型:
但需要注意,在一个复杂的四则运算中,两个整数的运算不会出现自动提升的情况。例如:
double d = 1.2 + 24 / 5; // 5.2
结果为5.2,是因为在对子表达式24 / 5进行计算时,会按整数计算,结果为4。
溢出
整数运算在除数为0时会报错,而浮点数运算在除数为0时,不会报错,但会返回几个特殊值:
强制转型
可以将浮点数强制转型为整数。在转型时,浮点数的小数部分会被丢掉。如果转型后超过了整型能表示的最大范围,将返回整型的最大值:
int n1 = (int) 12.3; // 12 int n2 = (int) 12.7; // 12 int n2 = (int) -12.7; // -12 int n3 = (int) (12.7 + 0.5); // 13 int n4 = (int) 1.2e20; // 2147483647
5. 布尔运算
布尔(boolean)只有true和false两个值。布尔运算是一种关系运算,包括以下几类:
boolean isGreater = 5 > 3; // true int age = 12; boolean isZero = age == 0; // false boolean isNonZero = !isZero; // true boolean isAdult = age >= 18; // false boolean isTeenager = age >6 && age <18; // true
关系运算符的优先级:
强制转型
Java还提供一个三元运算符b ? x : y,它根据第一个布尔表达式的结果,分别返回后续两个表达式之一的计算结果。
6. 字符和字符串
在Java中,字符和字符串是两个不同的类型。
字符
在Java中,字符类型(char)是基本类型,一个char类型可以保存一个Unicode字符:
char c1 = 'A'; char c2 = '中';
因为Java在内存中总是使用Unicode表示字符,所以,一个英文字符和一个中文字符都用一个char类型表示,它们都占用两个字节。要显示一个字符的Unicode编码,只需将char类型直接赋值给int类型即可:
int n1 = 'A'; // 字母“A”的Unicodde编码是65 int n2 = '中'; // 汉字“中”的Unicode编码是20013
还可以直接用转义字符\u+Unicode编码来表示一个字符:
// 注意是十六进制: char c3 = '\u0041'; // 'A',因为十六进制0041 = 十进制65 char c4 = '\u4e2d'; // '中',因为十六进制4e2d = 十进制20013
字符串
字符串类型String是引用类型,用双引号""表示字符串。一个字符串可以存储0个到任意个字符:
String s = ""; // 空字符串,包含0个字符 String s1 = "A"; // 包含一个字符 String s2 = "ABC"; // 包含3个字符 String s3 = "中文 ABC"; // 包含6个字符,其中有一个空格
连接字符串
可以用+来连接两个字符串,或者将一个字符串与其它任意类型连接:
String s1 = "Hello"; String s2 = "world"; String s = s1 + " " + s2
与其它类型连接时,会首先将其转为字符串:
int age = 25; String s = "age is " + age; System.out.println(s);
连接字符串
用+来表示多行字符串:
String s = "first line \n"
+ "second line \n"
+ "end";
从Java 13开始,可以用...来表示多行字符串(Text Blocks):
String s = """
SELECT * FROM
users
WHERE id > 100
ORDER BY name DESC
""";
不可变特性
对于以下代码来说:
public class Main {
public static void main(String[] args) {
String s = "hello";
System.out.println(s); // 显示 hello
s = "world";
System.out.println(s); // 显示 world
}
}
JVM工作过程是:
也就是说,其是引用类型,不能改变原内存的内容,而只能将其指定新的内存地址。
空值null与空字符串""
引用类型的变量可以指向一个空值null,它表示不存在,即该变量不指向任何对象;而指向""时表示指向一个空字符串。
String s1 = null; // s1是null String s2; // 没有赋初值值,s2也是null String s3 = s1; // s3也是null String s4 = ""; // s4指向空字符串,不是null
数组类型
Java中的数组是一组相同类型变量的列表,定义形式为:类型[],数组必须使用new来初始化,如:new int[5]表示创建一个可容纳5个int元素的数组。
Java数组有以下特点为:
要访问数组中元素使用索引。数组索引从0开始,如:5个元素的数组,其索引范围是0~4。
可以通过赋值语句,对数组元素进行修改,如:ns[1] = 79;
可以通过.length属性获取数组长度:
int[] ns = new int[5]; System.out.println(ns.length); // 5
数组是引用类型,使用索引访问数组元素时,如果索引超过数组范围,将报错。
创建数组时可以指定数组元素,这时可以不指定数组长度:
int[] ns = new int[] {1, 2, 3, 4, 5};
System.out.println(ns.length); // 5
还可以进一度简写为字面量形式:
int[] ns = {1, 2, 3, 4, 5};
数组是引用类型,并且数组大小不可变,但我们可以将变量指向一个新数组:
int[] ns;
ns = new int[] { 68, 79, 91, 85, 62 };
System.out.println(ns.length); // 5
ns = new int[] { 1, 2, 3 };
System.out.println(ns.length); // 3
字符串数组
如果数组元素除了可以是基本类型来,还可以是一个引用类型,如:字符串。
String[] names = {"ABC", "XYZ", "zoo"};
String s = names[1];[
s = "cat";
System.out.println(names[1]); // XYZ]
