「Java」程序基础
程序基本结构
因为Java是面向对象的语言,一个程序的基本单位就是class
,class
是关键字
1 | public class Hello { // 类名是Hello |
类名要求:
- 类名必须以英文字母开头,后接字母,数字和下划线的组合
- 习惯以大写字母开头
在class
内部,可以定义若干方法。方法定义了一组执行语句,方法内部的代码将会被依次顺序执行。
Java入口程序规定的方法必须是静态方法,方法名必须为main
,括号内的参数必须是String数组。
方法命名要求:
- 首字母小写
Java的每一行语句必须以分号结束
注释:和c语言一样
还有一种特殊的多行注释,以/**
开头,以*/
结束,如果有多行,每行通常以星号开头:
1 | /** |
这种特殊的多行注释需要写在类和方法的定义处,可以用于自动创建文档。
变量 && 数据类型
变量的默认值总是0
, 使用方法和C语言相同。
基本数据类型是CPU可以直接进行运算的类型。Java定义了以下几种基本数据类型:
- 整数类型:byte,short,int,long
- 浮点数类型:float,double
- 字符类型:char
- 布尔类型:boolean
计算机内存的最小存储单元是字节(byte),一个字节就是一个8位二进制数,即8个bit。 换算成十进制是0
255,换算成十六进制是00
ff
。
基本数据类型占用的字节数:
1 | ┌───┐ |
整型
各种整型能表示的最大范围如下:
- byte:-128 ~ 127
- short: -32768 ~ 32767
- int: -2147483648 ~ 2147483647(10位)
- long: -9223372036854775808 ~ 9223372036854775807
1 | long l = 9000000000000000000L; // long型的结尾需要加L |
注意:同一个数的不同进制的表示是完全相同的,例如15
=0xf
=0b1111
。
浮点型
因为小数用科学计数法表示的时候,小数点是可以“浮动”的,如1234.5可以表示成$ 12.345\times10^2 $,也可以表示成$ 1.2345\times10^3 $ ,所以称为浮点数。
1 | float f1 = 3.14f; // float类型,需要加上f后缀。 |
float
类型可最大表示$3.4\times10^{38}$,而double
类型可最大表示$1.79\times10^{308}$。
布尔类型
1 | boolean b1 = true; |
字符类型
字符类型char
表示一个字符。Java的char
类型除了可表示标准的ASCII外,还可以表示一个Unicode字符
**注意char
类型使用单引号'
,且仅有一个字符,要和双引号"
的字符串类型区分开。 **
引用类型
除了上述基本类型的变量,剩下的都是引用类型。例如,引用类型最常用的就是String
字符串:
1 | String s = "hello"; |
引用类型的变量类似于C语言的指针,它内部存储一个“地址”,指向某个对象在内存的位置
输出某个位置的字符:
1 | System.out.println(str.charAt(i)) |
常量
定义变量的时候,如果加上final
修饰符,这个变量就变成了常量:【 常量名通常全部大写 】
1 | final double PI = 3.14; // PI是一个常量 |
字符和字符串
因为Java在内存中总是使用Unicode表示字符,所以,一个英文字符和一个中文字符都用一个char
类型表示,它们都占用两个字节。要显示一个字符的Unicode编码,只需将char
类型直接赋值给int
类型即可。
还可以直接用转义字符\u
+Unicode编码来表示一个字符:
1 | // 注意是十六进制: |
字符串类型String
是引用类型,我们用双引号"..."
表示字符串。
注意要区分空值null
和空字符串""
,空字符串是一个有效的字符串对象,它不等于null
。
字符串连接
可以使用+
连接任意字符串和其他数据类型,这样极大地方便了字符串的处理。 如果用+
连接字符串和其他数据类型,会将其他数据类型先自动转型为字符串,再连接 。
从Java 13开始,字符串可以用"""..."""
表示多行字符串(Text Blocks):
1 | String s = """ |
如果多行字符串的排版不规则,那么总是以最短的行首空格为基准。
最后,由于多行字符串是作为预览特性(Preview Language Features)实现的,编译的时候,我们还需要给编译器加上参数:
1 | javac --source 14 --enable-preview Main.java |
字符串数组
1 | String[] names = { |
$var$ 关键字
如果类型名字太长写起来会比较麻烦,如果想省略变量类型可以使用var
关键字:
1 | StringBuilder sb = new StringBuilder(); |
数组
1 | int[] ns = new int[5]; |
多维数组
1 | int[][] ns = { |
1 | int[][][] ns = { |
运算
整数除法的结果只保留整数部分。
+=
,-=
,*=
,/=
,++
,--
这些运算操作Java都有。
类型自动提升与强制转型
在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。例如,short
和int
计算,结果总是int
,原因是short
首先自动被转型为int
1 | int i = 12345; |
溢出
整数运算在除数为0
时会报错,而浮点数运算在除数为0
时,不会报错,但会返回几个特殊值:
NaN
表示Not a NumberInfinity
表示无穷大-Infinity
表示负无穷大
输入和输出
println
是print line的缩写,表示输出并换行。因此,如果输出后不想换行,可以用print()
1 | System.out.print(".."); |
格式化输出
如果要把数据显示成我们期望的格式,就需要使用格式化输出的功能。格式化输出使用System.out.printf()
,通过使用占位符%?
,printf()
可以把后面的参数格式化成指定格式
1 | double d = 3.1415926; |
输入
一个从控制台读取一个字符串和一个整数的例子:
1 | import java.util.Scanner; |
System.out
代表标准输出流,而System.in
代表标准输入流。直接使用System.in
读取用户输入虽然是可以的,但需要更复杂的代码,而通过Scanner
就可以简化后续的代码。
有了Scanner
对象后,要读取用户输入的字符串,使用scanner.nextLine()
,要读取用户输入的整数,使用scanner.nextInt()
。Scanner
会自动转换数据类型,因此不必手动转换。
输入字符串 遇到空格或者换行结束 :
1 | Scanner sc=new Scanner(System.in); |
输入一行字符串,可以包括空格:
1 | Scanner sc=new Scanner(System.in); |
判断
1 | if (条件) { |
判断值类型的变量是否相等,可以使用==
运算符。但是,判断引用类型的变量是否相等,==
表示“引用是否相等”,或者说,是否指向同一个对象。
1 | String s1 = "hello"; |
要判断引用类型的变量内容是否相等,必须使用equals()
方法:
1 | if (s1 != null && s1.equals(s2)) { // 避免NullPointerException错误 |
switch
1 | String fruit = "apple"; |
从Java 12开始,switch
语句升级为更简洁的表达式语法,使用类似模式匹配(Pattern Matching)的方法,保证只有一种路径会被执行,并且不需要break
语句:
1 | String fruit = "apple"; |
还可以直接返回值:
1 | String fruit = "apple"; |
如果需要复杂的语句,我们也可以写很多语句,放到{...}
里,然后,用yield
返回一个值作为switch
语句的返回值:
1 | String fruit = "orange"; |
循环
1 | while (条件表达式) { |
1 | do { |
1 | for (初始条件; 循环检测条件; 循环后更新计数器) { |
命令行参数
Java程序的入口是main
方法,而main
方法可以接受一个命令行参数,它是一个String[]
数组。
这个命令行参数由JVM接收用户输入并传给main
方法:
1 | public class TestArgs { |
命令行执行:
1 | $ javac Main.java |
如果是vsc的话已经生成了.class
文件,就无需第一行命令了。