Java 是一门面向对象的语言,其语法结构包括了类、对象等概念。
简单的 Java 程序
下面是一个最简单的 Java 程序:
public class KnowledgeDict {
public static void main(String[] args) {
System.out.println("Hello KnowledgeDict");
}
}
这个程序虽然很简单,但所有的 Java 应用程序都具有这种结构,还是值得花一些时间来研究。
- 首先,Java 区分大小写。如果出现了大小写拼写错误(例如,将 main 拼写成 Main),程序将无法运行。
- 关键字 public 称为访问修饰符(access modifier),这些修饰符用于控制程序的其他部分对这段代码的访问级別。
- 关键字 class 表明 Java 程序中的全部内容都包含在类中。
- 关键字 class 后面紧跟类名。
- 类名的命名规范是以大写字母开头的名词。如果名字由多个单词组成,每个单词的第一个字母都应该大写(这种在一个单词中间使用大写字母的方式称为骆驼命名法。以其自身为例,应该写成 CamelCase)。
- 源代码的文件名必须与公共类的名字相同,并用 .java 作为扩展名。因此,存储这段源代码的文件名必须为 KnowledgeDict.java(再次提醒大家注意,大小写是非常重要的,千万不能写成 knowledgedict.java)。
- 根据 Java 语言规范,main 方法必须声明为 public。
- Java 中任何方法的代码都用“{”开始,用“}”结束。
- 在 Java 中,每个句子必须用分号结束。特别需要说明,回车不是语句的结束标志,因此,如果需要可以将一条语句写在多行上。
注释
与大多数程序设计语言一样,Java 中的注释也不会出现在可执行程序中。因此,可以在源程序中根据需要添加任意多的注释,而不必担心可执行代码会膨胀。
在 Java 中,有 3 种标记注释的方式:
- 最常用的方式是使用
//
,其注释内容从//
开始到本行结尾。 - 当需要长篇的注释时,既可以在每行的注释前面标记
//
,也可以使用/*
和*/
将一段比较长的注释括起来。 - 第 3 种注释可以用来自动地生成文档。这种注释以
/**
开始,以*/
结束。
示例如下:
/**
* This is KnowledgeDict Class
*/
public class KnowledgeDict {
public static void main(String[] args) {
System.out.println("Hello KnowledgeDict");// print Hello
/*
* print multi row
*/
System.out.println("study hard");
System.out.println("day day up");
}
}
数据类型
Java 是一种强类型语言。这就意味着必须为每一个变量声明一种类型。在 Java 中,一共有 8 种基本类型(primitive type),其中有 4 种整型、2 种浮点类型、1 种用于表示 Unicode 编码的字符单元的字符类型 char 和 1 种用于表示真值的 boolean 类型。
注释:Java 有一个能够表示任意精度的算术包,通常称为“大数值”(big number)。虽然被称为大数值,但它并不是一种新的 Java 类型,而是一个 Java 对象。
整型
整型用于表示没有小数部分的数值,它允许是负数。
Java 提供了 4 种整型,具体内容如下表:
类型 | 存储需求 | 取值范围 |
---|---|---|
byte | 1 字节 | -128~127 |
short | 2 字节 | -32 768~32 767 |
int | 4 字节 | -2 147 483 648~2 147 483 647(正好超过 20 亿) |
long | 8 字节 | -9 223 372 036 854 775 808~9 223 372 036 854 775 807 |
在通常情况下,int 类型最常用。但如果表示星球上的居住人数,就需要使用 long 类型了。byte 和 short 类型主要用于特定的应用场合,例如,底层的文件处理或者需要控制占用存储空间量的大数组。
在 Java 中,整型的范围与运行 Java 代码的机器无关。这就解决了软件从一个平台移植到另一个平台,或者在同一个平台中的不同操作系统之间进行移植给程序员带来的诸多问题。
长整型数值有一个后缀 L 或 l(如 4000000000L)。十六进制数值有一个前缀 0x 或 0X(如 0xCAFE)。八进制有一个前缀 0,例如,010 对应八进制中的 8。很显然,八进制表示法比较容易混淆,所以建议最好不要使用八进制常数。
从 Java 7 开始,加上前缀 0b 或 0B 就可以写二进制数。例如,0b1001 就是 9。另外,同样是从 Java 7 开始,还可以为数字字面量加下划线,如用 1_000_000(或 0b1111_0100_0010_0100_0000)表示一百万。 这些下划线只是为了让人更易读。Java 编译器会去除这些下划线。
浮点类型
浮点类型用于表示有小数部分的数值。
在 Java 中有两种浮点类型,具体内容如下:
类型 | 存储需求 | 取值范围 |
---|---|---|
float | 4 字节 | 大约 ± 3.402 823 47E+38F(有效位数为 6 ~ 7 位) |
double | 8 字节 | 大约 ± 1.797 693 134 862 315 70E+308(有效位数为 15 位) |
double 表示这种类型的数值精度是 float 类型的两倍(有人称之为双精度数值)。绝大部分应用程序都采用 double 类型。在很多情况下,float 类型的精度很难满足需求。实际上,只有很少的情况适合使用 float 类型,例如,需要单精度数据的库,或者需要存储大量数据。
float 类型的数值有一个后缀 F 或 f(例如,3.14F)。没有后缀 F 的浮点数值(如 3.14)默认为 double 类型。当然,也可以在浮点数值后面添加后缀 D 或 d(例如,3.14D)。
警告:浮点数值不适用于无法接受舍入误差的金融计算中。例如,命令 System.out.println(2.0-1.1) 将打印出 0.8999999999999999,而不是人们想象的 0.9。这种舍入误差的主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确地表示分数 1/10。这就好像十进制无法精确地表示分数 1/3 —样。如果在数值计算中不允许有任何舍入误差,就应该使用 BigDecimal 类。
char 类型
char 类型原本用于表示单个字符。不过,现在情况已经有所变化。如今,有些 Unicode 字符可以用一个 char 值描述,另外一些 Unicode 字符则需要两个 char 值。
char 类型的字面量值要用单引号括起来。例如:'A'是编码值为 65 所对应的字符常量。它与"A"不同,"A"是包含一个字符 A 的字符串,char 类型的值可以表示为十六进制值,其范围从 \u0000 到 \Uffff。例如: \u2122 表示注册符号(™),\u03C0 表示希腊字母 π。
除了转义序列 \u 之外,还有一些用于表示特殊字符的转义序列,具体如下表:
转义序列 | 名称 | Unicode 值 |
---|---|---|
\b | 退格 | \u0008 |
\t | 制表 | \u0009 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
\" | 双引号 | \u0022 |
\' | 单引号 | \u0027 |
\\ | 反斜杠 | \u005c |
boolean 类型
boolean(布尔)类型有两个值:false 和 true,用来判定逻辑条件。整型值和布尔值之间不能进行相互转换。
变量
在 Java 中,每个变量都有一个类型(type)。在声明变量时,变量的类型位于变量名之前。每个声明以分号结束。
变量名必须是一个以字母开头并由字母或数字构成的序列。
变量初始化
声明一个变量之后,必须用赋值语句对变量进行显式初始化,千万不要使用未初始化的变量。
要想对一个已经声明过的变量进行赋值,就需要将变量名放在等号(=)左侧,相应取值的 Java 表达式放在等号的右侧。
int weekDay;
weekDay = 3;
也可以将变量的声明和初始化放在同一行中。
int weekDay = 3;
常量
在 Java 中,利用关键字 final 指示常量。
关键字 final 表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。习惯上,常量名使用全大写。
在 Java 中,经常希望某个常量可以在一个类中的多个方法中使用,通常将这些常量称为类常量。可以使用关键字 static final 设置一个类常量。
public class KnowledgeDict {
public static final double CTR = 0.54;
public static void main(String[] args) {
double cvr = 0.07;
System.out.println("value:" + CTR * cvr);
}
}
需要注意,类常量的定义位于 main 方法的外部。因此,在同一个类的其他方法中也可以使用这个常量。而且,如果一个常量被声明为 public,那么其他类的方法也可以使用这个常量。
运算符
在 Java 中,使用算术运算符 +、-、 *、/ 表示加、减、乘、除运算。当参与 / 运算的两个操作数都是整数时,表示整数除法;否则,表示浮点除法。整数的求余操作(有时称为取模)用 % 表示。例如,15/2 等于 7,15%2 等于 1,15.0/2 等于 7.50。
需要注意,整数被 0 除将会产生一个异常,而浮点数被 0 除将会得到无穷大或 NaN 结果。
数学函数与常量
在 Math 类中,包含了各种各样的数学函数。在编写不同类别的程序时,可能需要的函数也不同。
要想计算一个数值的平方根,可以使用 sqrt 方法:
double x = 4;
double y = Math.sqrt(x);
System.out.println(y);
在 Java 中,没有幂运算,因此需要借助于 Math 类的 pow 方法。
double x = 4;
double y = Math.pow(x, 2.0);
System.out.println(y);
将 y 的值设置为 x 的 2次幂。pow 方法有两个 double 类型的参数,其返回结果也为 double 类型。
数值类型之间的转换
经常需要将一种数值类型转换为另一种数值类型。
下图给出了数值类型之间的合法转换。
在下图中有 6 个实心箭头,表示无信息丢失的转换;有 3 个虚箭头,表示可能有精度损失的转换。
强制类型转换
在上一小节中看到,在必要的时候,int 类型的值将会自动地转换为 double 类型。但另一方面,有时也需要将 double 转换成 int。在 Java 中,允许进行这种数值之间的类型转换。当然,有可能会丢失一些信息。在这种情况下,需要通过强制类型转换(cast)实现这个操作。强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。
结合赋值和运算符
可以在赋值中使用二元运算符,这是一种很方便的简写形式。
int x = 0;
x += 4;
等价于:
int x = 0;
x = x + 4;
注释:如果运算符得到一个值,其类型与左侧操作数的类型不同,就会发生强制类型转换。
自增与自减运算符
当然,程序员都知道加 1、减 1 是数值变量最常见的操作。在 Java 中,借鉴了 C 和 C++ 的做法,也提供了自增、自减运算符。
int n = 12;
n++;
如上示例,n 值变为 13。
关系和 boolean 运算符
Java 包含丰富的关系运算符:要检测相等性,可以使用两个等号 ==。
另外可以使用 != 检测不相等。
最后,还有经常使用的 <(小于)、>(大于)、<=(小于等于)和 >=(大于等于)运算符。
Java 沿用了 C++ 的做法,使用 && 表示逻辑“与”运算符,使用 || 表示逻辑“或”运算符。从 != 运算符可以想到,感叹号 ! 就是逻辑非运算符。&& 和 || 运算符是按照“短路”方式来求值的:如果第一个操作数已经能够确定表达式的值,第二个操作数就不必计算了。
位运算符
处理整型类型时,可以直接对组成整型数值的各个位完成操作。这意味着可以使用掩码技术得到整数中的各个位。
位运算符包括:
&("and"),|("or"),^("xor"),~("not")
括号与运算符级别
下表给出了运算符的优先级。
运算符 | 结合性 |
---|---|
[] . ()(方法调用) | 从左向右 |
! ~ ++ -- +(一元运算)-(一元运算)()(强制类型转换)new | 从右向左 |
* / % | 从左向右 |
+ - | 从左向右 |
<< >> >>> | 从左向右 |
< <= > >= instanceof | 从左向右 |
== != | 从左向右 |
& | 从左向右 |
^ | 从左向右 |
| | 从左向右 |
&& | 从左向右 |
|| | 从左向右 |
?: | 从右向左 |
= += -= *= /= %= &= |= ^= <<= >>= >>>= | 从右向左 |
枚举类型
有时候,变量的取值只在一个有限的集合内。
针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。
enum Size {
SMALL,
MEDIUM,
LARGE
}