入口程序规定
Java入口程序规定的方法必须是静态方法,方法名必须为main
,括号内的参数必须是String数组。
public class Hello { public static void main(String[] args) { // 方法名是main // 方法代码... } // 方法定义结束 }
注释
// 这是注释... /* 这是注释 blablabla... 这也是注释 */ /** * 可以用来自动创建文档的注释 * * @auther liaoxuefeng */
数据类型
基本数据类型
- 整数类型:byte, short, int, long
- 浮点数类型:float, double
- 字符类型:char
- 布尔类型:boolean
计算机内存的最小存储单元是字节(byte),一个字节就是一个8位二进制数,即8个bit。
注意char
类型使用单引号'
,且仅有一个字符,要和双引号"
的字符串类型区分开。
引用数据类型
除了上述基本类型的变量,剩下的都是引用类型。
- 字符串
- …
引用类型的变量类似于C语言的指针,它内部存储一个“地址”,指向某个对象在内存的位置。
常量
常量在定义时进行初始化后就不可再次赋值,再次赋值会导致编译错误。
常量的作用是用有意义的变量名来避免魔术数字(Magic number),例如,不要在代码中到处写3.14
,而是定义一个常量。如果将来需要提高计算精度,我们只需要在常量的定义处修改,例如,改成3.1416
,而不必在所有地方替换3.14
。
根据习惯,常量名通常全部大写。
整数运算
运算优先级
在Java的计算表达式中,运算优先级从高到低依次是:
()
!
~
++
--
*
/
%
+
-
<<
>>
>>>
&
|
+=
-=
*=
/=
记不住也没关系,只需要加括号就可以保证运算的优先级正确。
浮点数运算
浮点数运算和整数运算相比,只能进行加减乘除这些数值计算,不能做位运算和移位运算。
溢出
整数运算在除数为0
时会报错,而浮点数运算在除数为0
时,不会报错,但会返回几个特殊值:
NaN
表示Not a NumberInfinity
表示无穷大-Infinity
表示负无穷大
double d1 = 0.0 / 0; // NaN double d2 = 1.0 / 0; // Infinity double d3 = -1.0 / 0; // -Infinity
布尔运算
对于布尔类型boolean
,永远只有true
和false
两个值。
布尔运算是一种关系运算,包括以下几类:
- 比较运算符:
>
,>=
,<
,<=
,==
,!=
- 与运算
&&
- 或运算
||
- 非运算
!
关系运算符的优先级从高到低依次是:
!
>
,>=
,<
,<=
==
,!=
&&
||
短路运算
boolean b = 5 < 3;
boolean result = b && (5 / 0 > 0); // false
boolean result = true || (5 / 0 > 0); // true
三元运算符
Java还提供一个三元运算符b ? x : y
,它根据第一个布尔表达式的结果,分别返回后续两个表达式之一的计算结果。
字符和字符串
在Java中,字符和字符串是两个不同的类型。
字符(基本数据类型)
单引号表示字符。
字符类型char
是基本数据类型,它是character
的缩写。一个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
字符串类型(引用数据类型)
和char
类型不同,字符串类型String
是引用类型,我们用双引号"..."
表示字符串。一个字符串可以存储0个到任意个字符。
常见的转义字符包括:
\"
表示字符"
\'
表示字符'
\\
表示字符\
\n
表示换行符\r
表示回车符\t
表示Tab\u####
表示一个Unicode编码的字符
字符串连接
Java的编译器对字符串做了特殊照顾,可以使用+
连接任意字符串和其他数据类型,这样极大地方便了字符串的处理。
如果用+
连接字符串和其他数据类型,会将其他数据类型先自动转型为字符串,再连接。
多行字符串
从Java 13开始,字符串可以用"""..."""
表示多行字符串(Text Blocks)了。
不可变特性
Java的字符串除了是一个引用类型外,还有个重要特点,就是字符串内容不可变。
空值null
引用类型的变量可以指向一个空值null
,它表示不存在,即该变量不指向任何对象。
数组类型
定义一个数组类型的变量,使用数组类型“类型[]”,例如,int[]
。和单个基本类型变量不同,数组变量初始化必须使用new int[5]
表示创建一个可容纳5个int
元素的数组。
Java的数组有几个特点:
- 数组所有元素初始化为默认值,整型都是
0
,浮点型是0.0
,布尔型是false
; - 数组一旦创建后,大小就不可改变。
要访问数组中的某一个元素,需要使用索引。数组索引从0
开始,例如,5个元素的数组,索引范围是0
~4
。
可以修改数组中的某一个元素,使用赋值语句,例如,ns[1] = 79;
。
可以用数组变量.length
获取数组大小。
int[] ns = new int[5];
数组是引用类型,在使用索引访问数组元素时,如果索引超出范围,运行时将报错
也可以在定义数组时直接指定初始化的元素,这样就不必写出数组大小,而是由编译器自动推算数组大小。
int[] ns = new int[] { 68, 79, 91, 85, 62 };
简写
int[] ns = { 68, 79, 91, 85, 62 };
注意数组是引用类型(比如字符串类型),并且数组大小不可变。
数组操作
遍历数组
通过for
循环就可以遍历数组。
int[] ns = { 1, 4, 9, 16, 25 };
for (int i=0; i<ns.length; i++) {
int n = ns[i];
System.out.println(n);
}
第二种方式是使用for each
循环,直接迭代数组的每个元素:
int[] ns = { 1, 4, 9, 16, 25 };
for (int n : ns) {
System.out.println(n);
}
打印数组内容
使用for each
循环来打印它:
for (int n : ns) { System.out.print(n + ", "); }
Java标准库提供了Arrays.toString()
,可以快速打印数组内容:
System.out.println(Arrays.toString(ns));
数组排序
对数组进行排序是程序中非常基本的需求。常用的排序算法有冒泡排序、插入排序和快速排序等。
实际上,Java的标准库已经内置了排序功能,我们只需要调用JDK提供的Arrays.sort()
就可以排序:
int[] ns = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
Arrays.sort(ns);
必须注意,对数组排序实际上修改了数组本身。
多维数组(跳过)
命令行参数
Java程序的入口是main
方法,而main
方法可以接受一个命令行参数,它是一个String[]
数组。
我们可以利用接收到的命令行参数,根据不同的参数执行不同的代码。例如,实现一个-version
参数,打印程序版本号:
public class Main {
public static void main(String[] args) {
for (String arg : args) {
if ("-version".equals(arg)) {
System.out.println("v 1.0");
break;
}
}
}
}
上面这个程序必须在命令行执行,我们先编译它:
$ javac Main.java
然后,执行的时候,给它传递一个-version
参数:
$ java Main -version
v 1.0
这样,程序就可以根据传入的命令行参数,作出不同的响应。