Java 学习笔记
dos 环境下(Windows 即 cmd)的 Java 命令
- 先用
javac 文件名.java;
命令,编译 java 文件,生成一个后缀为 class、名与类名相同的文件。 - 再用
java 类名
命令,执行文件。
当类名前的修饰符为 public 时,类名必须和源文件名一致。并且以上操作不能执行带 package 的 java 文件。
注释
和 C 语言一样。
//
:单行注释。
/**/
:多行注释。
编译后生成的 class 文件里没有注释里的内容,即写再多的注释,class 文件的大小也不会变。
/** *...*/
:文档注释,用javadoc -encoding UTF-8 -d mydir -version -author HelloWorld.java
命令后,会生成一个类似 API 文档的网页,注释里的内容会成为网页的一部分。
javadoc 和 java 文件间的内容都是命令行参数。
注意文档注释写的位置,有些在类外,有些在类里面。
输出
System.out.println()
:输出数据之后,会换行。
当括号里不填内容时,相当于换行操作,等价于
System.out.print("\n")
。
System.out.print()
:输出数据后,不换行。
pubilc 修饰符
同一源文件中可定义多个类,每个类都会生成一个 class 文件(字节码文件),且 class 文件名与类名相同。
public 修饰的类在每个源文件中最多一个,且类名必须与源文件名相同。
包(package)
包(类似于文件夹,用于管理class文件)的命名采用域名倒置的规则;
标识符
命名规则
标识符可以包含字母,数字,_,$,但是不能以数字开头,不能包含空格;
命名习惯
包名
多单词组成时所有字母都小写。
例如:java.lang、com.atguigu.bean 等。
类名、接口名
多单词组成时,所有单词的首字母大写。
例如:HelloWorld、String、System 等。
变量名、方法名
多单词组成时,第一个单词首字母小写,第二个单词开始每个单
词首字母大写。
例如:age、name、bookName、main、binarySearch、getName 等。
在同一作用域下,不能声明 2 个同名的变量。
常量名
所有字母都大写。多单词时每个单词用下划线连接。
例如:MAX_VALUE、PI、DEFAULT_CAPACITY 等。
基本数据类型
整型
Java 各整数类型有固定的表数范围和字段长度,不受具体操作系统的影响,以保证 Java 程序的可移植性。
类型 | 占用存储空间 | 表示范围 |
---|---|---|
byte | 1 字节 | -128 ~ 127 |
short | 2 字节 | -215 ~ 215-1 |
int | 4 字节 | -231 ~ 231-1(约21.4亿) |
long | 8 字节 | -263 ~ 263-1 |
定义 long 类型的变量,赋值时需要以"l"或"L"作为后缀。
开发过程中,整型变量通常声明为 int 型。
整型常量默认为 int。
浮点型
浮点型有固定的表数范围和字段长度,不受具体操作系统的影响。
类型 | 占用存储空间 |
---|---|
float | 4 字节 |
double | 8 字节 |
定义 float 类型的变量,赋值时需要以"f"或"F"作为后缀。
float、double 的数据不适合在不容许舍入误差的金融计算领域。如果需要精确数字计算或保留指定位数的精度,需要使用 BigDecimal 类。
字符型
char 占 2 个字节。值用单引号('')括起来,例子:char a = 'a';
、char b = '中';
char 和 int 、char 和 char 做运算会变为 int。
布尔型
boolean 类型数据只有两个值:true、false,无其它
不可以使用 0 或非 0 的整数替代 false 和 true,这点和 C 语言不同,布尔型不能和其他基本数据类型做运算。
类型转换
自动类型转换
byte ,short,char ==> int ==> long ==> float ==> double
表示范围小的可以转变为表示范围大的,而不是看占用存储空间大小。float 能表示的数比 long 还大。
注:byte 和 byte 运算、byte 和 short 运算、short 和 short 运算,结果需要用 int 存储。
byte a = 10; byte b = a + 12; //会报错,算式里的整数常量 12 默认是 int ,需要用 int 变量接收 //浮点数同理,而浮点数常量默认为 double。
强制类型转换
和 C 语言类似,但 String 类型不能通过强制类型()转换为其他的类型,因为 String 不是基本数据类型。
引用数据类型
字符串
String 和基本数据类型(包括布尔型)可以用“+”拼接。
String a = "abc";
System.out.println(a+1); //结果是abc1,类型为字符串
进制
二进制
以0b
或0B
开头。
int a = 0b110;//或者0B110
System.out.println(a); //输出为:6,以10进制输出
十进制
以0x
或0X
开头,a-f不区分大小写。
int a = 0x110;//或者0X110
System.out.println(a); //输出为:272
计算机数据的存储使用二进制补码形式存储,并且最高位是符号位。
- 正数:最高位是 0。
- 负数:最高位是 1。
正数的补码与反码、原码一样,称为三码合一。
负数的补码与反码、原码不一样:
-
负数的原码:把十进制转为二进制,然后最高位设置为 1。
-
负数的反码:在原码的基础上,最高位不变,其余位取反(0 变 1,1 变0)。
-
负数的补码:反码加 1
最快方法是:除符号位、最后个 1 及以后的位不变,其余位全取反。
补码转原码:最高位不变,其余位取反再加 1,因此也可以使用最快方法。
运算
运算符的细微差异
java 中的 % 是取余,商向 0 靠近。
System.out.print(-5%2); //本身商为 -2.5,但是向0取整则为 -2,余数为 -1
System.out.print(-5/2); //本身商为 -2.5,但是向0取整则为 -2,
python中 % 为取模,商向负无穷靠近。
print(5//2) #地板除,得 2.
print(5/2) #得2.5
print(-5%2) #本身商为 -2.5,但是向负无穷取整得 -3,取模为 1,-5 = 2*(-3) + 1
a+=2;
与a= a+2;
的细微差别,a+=2; int b =1000; a+=b;
中 a 的类型不会改变,比如 a 的类型为 byte,则运算完也为 byte,只是把高位抛弃,只看地位对应哪个值, -=、*=、 /=、%= ++
具有相同的性质。
short s1 = 10;
s1 += 2; //因为在得到 int 类型的结果后,JVM 自动会进行强制类型转换,将 int 类型强转成 short
s1++;
比较运算符
- 比较运算符的结果都是 boolean 型,也就是要么是 true,要么是 false。
-
> < >= <=
:只适用于基本数据类型(除 boolean 类型之外)。 -
== !=
:适用于基本数据类型和引用数据类型。
逻辑运算符
&
和 &&
:表示“且”。
|
和 ||
:表示“或”。
a&b
和a&&b
的区别在于 a 为 false 时,&
仍会判断b,从而执行b中的表达式,比如age++
;而&&
会短路,不再判断 b。|
和||
同理,推荐使用&&
和||
。
^
:表示”异或“。
!
:表示“非”。
位运算符
a<<n
:左移 n 位,低位补0。在一定范围内,相当于乘 2n(正负数都是),这里也涉及到自动类型转换(byte、short 移位后会变为int)。
有可能会移成负数,把数值的 1 移到符号位。是移位时,移的是补码。当左移的位数 n 超过该数据类型的总位数时,相当于左移(n % 总位数)位。
a>>n
:右移 n 位,高位补与符号位相同的值。在一定范围内,相当于除 2n,然后向下取整(正负数都是),这里也涉及到自动类型转换(byte、short 移位后会变为int)。
a>>>n
::右移 n 位,高位补 0。(正数、负数都适用),这里也涉及到自动类型转换(byte、short 移位后会变为int)。
负数会变成正数。
a&b、a|b、a^b、~a
:都是用二进制补码运算,运算时也包括了符号位。
条件运算符
c = 条件表达式 ? A : B;
表达式为true
执行 c = A
,表达式为false
执行 c = B
。也可以syetem.out.println(条件表达式 ? "我是A" : "我是B");
switch-case
写法和 C 语言一样,case 子句中的值必须是常量,不能是变量名或不确定的表达式值或范围。
break 和 continue
break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块,continue 类似。
label1: for(...){ //for1
label2:for(...){ //for2
label3:for(...){ //for3
break label2; //跳出紧跟 label2 的这个循环,即for2,再执行for1。
}
}
}
continue 结束此次循环,然后再次进入所属循环语句的下轮循环。 若上面 break 换成 continue,则是跳出 for2,再进入 for2。
标签语句只能用在循环的头部。
Scanner
步骤:
-
导包:
import java.util.Scanner;
。 -
创建 Scanner 对象:
Scanner scan = new Scanner(System.in);
。 -
next() / nextXxx()
,来获取指定类型的变量,如nextInt()
获取一个 Int 型整数,nextDouble()
获取一个 Double 型浮点数。-
我们把 Scanner 看为 2 个过程,扫描和键入,扫描是去输入缓冲区取数据;键入是从键盘输入数据,以“换行符”作为结束的标志,即按下“Enter”键后才会结束。
-
next()
和nextLine()
都是读取字符串的方法。 -
next()
和nextLine()
的键入过程相同,扫描过程不同。-
nextLine()
会读入空格,即将空格看为字符串的一部分,只把“换行符”作为扫描结束的标志,并且把光标移到“换行符”后。 -
next()
会忽略掉有效字符之前遇到的空格,把有效字符后的“空格”以及“换行符”作为扫描结束的标志,并且光标停在结束符之前。nextInt()、nextDouble()
等和next()
扫描过程相同,只有nextLine()
很特殊。
-
-
这就会出现一个问题,先使用
nextInt()
,光标停在结束符之前,nextLine()
可能会读到空字符串或者带空格的脏数据。解决办法:使用nextInt()
后,先调用nextLine()
把脏数据读走,将光标移到“换行符”后,再用nextLine()
读取需要的数据,也就是使用 2 次nextLine()
。
-
-
释放资源:
scan.close();
。
Math.random()
Math.random()
会返回范围在 [0,1) 的 double 浮点数。
获取 [a,b] 范围内的随机整数:(int)(Math.random() * (b - a + 1))+a
,取整使得范围从 [a,b+1) 变成[a,b]。
包(package)
在 IDEA 中,一个 Project 可以有多个 module,一个module 下可以有多个 package,一个 package 下可以有多个 class。
实际上就是把不同功能的 class 放到不同的文件夹下,package 的命名采用域名倒置的规则,比如 www.lc.com
下的包可以写成 com.lc.包名
数组
数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
一维数组
声明数组
类型[] 数组名;
,例如int[] arr;
。
Java 中声明数组时,不能指定长度。
未初始化的数组不能直接使用。
初始化
-
静态初始化
初始化的同时赋初值。
- 写法 1:
int[] arr = new int[]{1,2,3,4,5};
- 写法 2:
int[] arr = {1,2,3,4,5};
,这种不能写成int[] arr; arr = {1,2,3,4,5};
,因为编译器识别出不来。
- 写法 1:
-
动态初始化
-
int[] arr = new int[5];
,[] 中指定数组长度,但不赋初值。指定长度后,无法修改长度。arr.length 可以得到数组 arr 的长度。
当使用动态初始化创建数组时,元素值是默认值。
-
一维数组内存存储
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);
}
只有在 new 数组对象时,才会在堆中分配。声明数组只会在栈中分配。
二维数组
声明二维数组
可以理解为一维数组的元素也是一维数组。
元素的数据类型[][] 二维数组的名称;
,例如int[][] grades;
。
初始化
-
静态初始化
int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
int[][] arr = {{1,2,3},{4,5,6},{7,8,9,10}};
-
动态初始化
- 指定内层一维数组长度,
int[][] arr = new int[3][2];
- 不指定内层一维数组长度,
int[][] arr = new int[3][]; arr[i] = new int[长度];
,在使用时,才具体指定 arr[i] 的长度。
arr.length 得到的是
new int[3][2];
中的 3,即二维数组能存储3个一维数组;arr[0].length 得到的是第一个一维数组的长度,即 2。不指定内层一维数组长度时,若没进行
arr[i] = new int[长度];
操作,直接使用 arr[i].length 会报错。System.out.println(arr[i]);
打印的是 arr[i] 地址,若没进行arr[i] = new int[长度];
操作,则打印:null,且System.out.println(arr[i][j]);
会报错。 - 指定内层一维数组长度,
二维数组内存
Arrays 工具类
java.util.Arrays 类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。