|
第二章 语言基础
对Java有了一个整体的认识之后,我们来详细介绍一下Java的语言基础。虽然Java语言在语言基础方面与C/C++有很多类似之处,但作为一种新型的独立的语言,Java在很多地方有其独特之处。本章将介绍Java的基本数据类型,表达式、操作符以及控制流。对于熟悉C/C++的读者,可以着重注意一下Java语言在语言基础方面与C/C++的区别,这对于以后书写Java的程序将大有好处。若你不熟悉C/C++语言,请仔细阅读本章。本章的内容是书写Java程序的基础,而且有益于你以后学习其它语言。
2.1 Java的词符集(Token Set)
Java语言中词符(Token)是指由Unicode字符集中的字符组成的具有独立含义的最小的语法单位。 Java语言使用16位的Unicode字符集代替了标准8位ASCII字符集。使用Unicode字符集主要目的是为了提供一些非拉丁字符。有关Unicode字符集的详细内容请查阅附录A。在Java语言中词符可以分成标识符(Identifier)、关键字(Keyword)、字面常量(Literal)、操作符(Operand)以及分隔符(Separator)五种类型。 注意,在Java中注释和空白符(包括换行符、制表符和空格符)不属于Token集。
2.1.1 注释
在Java中注释可以采用以下三种形式: (Ⅰ)/* */ 这种方式可以用来标识一行或多行注释。 例 /*
This is a comment. The name of this Application
is Hello.java */ (Ⅱ)// 和C++中相同,这种方式用来标识单行注释。 例
//This is a comment. (Ⅲ)/** */
这是Java语言特有的注释方法,在/** */间的内容均为注释。这种方式仅可在声明之前使用,而且javadoc工具产生自动软件文档时将使用到其中所注释的内容(后面几章将详细介绍javadoc工具)。 在程序中书写注释是一种非常好的习惯。这将方便以后的使用及修改。尤其对于Java这种面向对象的程序设计语言,书写注释可为类的继承和复用节约大量时间。
2.1.2 标识符(Identifier)
标识符是除关键字以外的任意一串以合法字母、下划线(_)或美元符号($)开头的由合法字母、数字、下划线(_)和美元符号($)组成的字符串。 标识符用于对变量、类和方法的命名。对变量、类等作适当的命名,可以大大提高程序的可读性。
在Java中标识符必须使用合法字母、下划线(_)或美元符号($)开头。在Java中合法字母除了大小写的英文字母外,还包括所有位置在00C0以前的Unicode字符集中的字符(参见附录A)。当然,同C/C++中规定一样,使用关键字进行命名是不允许的。 一般标识符用小写字母开头。同一个标识符中,中间的单词以大写字母开头,或用下划线进行分隔。在Java中,与C语言代码相连时会产生'_'及'$'开头的标识符。所以一般情况下请不要使用'_'或'$'
作为标识符的开始。尤其对于'$'符号,除特殊情况请勿使用。
表2.1
|
合法(推荐) |
合法(不推荐) |
不合法 |
|
openOn day_24_hours x value |
OPENON day24hours _name $value
|
24_hours day-24-hours boolean value#
|
2.1.3 关键字(Keyword)
Java中预定义的关键字如表2.2所列。
表2.2 Java的关键字表
| abstract |
boolean |
break |
byte |
case |
cast |
| catch |
char |
class |
cons |
continue |
default |
| do |
double |
else |
extends |
final |
finally |
| float |
for |
future |
generic |
toto |
if |
| implements |
import |
inner |
instanceof |
int |
interface |
| long |
native |
new |
null |
opertor |
outer |
| package |
private |
protected |
public |
rest |
return |
| short |
static |
super |
switch |
synchronized |
this |
| throw |
throws |
transient |
try |
var |
unsigned |
| virtual |
void |
volatile |
while |
false|true |
threadsafe |
由表2.2可知,关键字都由小写字母组成。每一个关键字都有特定的含义和严格的使用规定,编写程序时不能随便挪作他用。如若不按规定使用,就会造成程序出错。关于它们的含义和使用方式将在以后各章节中逐一给出。
2.1.4 字面常量(Literal)
Java中字面常量包括数值型常量、布尔型常量,字符型常量和字符串型常量 *
数值常量包括整数和浮点数 (1)整数包括十进制数、十六进制数和八进制数。在Java中,八进制数一律以0开始,而十六进制数表示时以0X开始。 例
|
十进制 |
八进制 |
十六进制 |
|
2 16 631 |
02 020 0711 |
0X2 0XF 0X3F1 |
(2)浮点数有两种表达方式:标准方式和科学记数法。 例 3.14 0.988 1.25e23
1.7e-3 *
字符常量 它可以是用单引号括起的Unicode字符集中的任何一个字符。在Java中,用“\”后跟某些字符来表示一些不可打印字符,表2.3给出了与这些不可打印的特殊字符对应的表示形式。
表2.3
|
表示形式 |
对应的不可打印的特殊字符的功能 |
|
\n \t \b \r \nf \\ \' \" \ddd \xdd \uddd
|
换行 跳向下一输出区 退格 回车 走纸换页 反斜杠“\” 单引号 双引号" 八位配置 十六位配置 Unicode字符
| * 布尔型常量
在Java中,布尔型常量只有两个值:true和false。请注意:与C/C++中不同,Java中的布尔型常量不可用0或1来代表。 *字符串常量 字符串常量是用双号括号起来的字符序列。值得注意的是,在Java中,字符串是作为Java的一个类存放的,而不像C++中实际上以数组形式存放。每创建一字符串常量实际上就是创建了一个String类的实例。
2.1.5 操作符(Operand)和分隔符(Seperator)
表2.4列出了具体的操作符和分隔符。由于Java的基本类型的某些特殊性,使用操作符需要注意一些特殊问题,在下一节讨论类型时我们将具体提到这个问题。
表2.4 Java的操作符与分隔符
+ - * / ++ -- ! & | ^
&& || == != < >
<= >= << >> >>> % ( )
[ ] { } ; ? : , . |
2.2 Java的基本数据类型
本节介绍Java的基本数据类型及相关的基本操作。 ┌字节型(byte) ├短型(short) ┌整形┼标准型(int) │ └长型(long)
┌基本类型┤
│ │ ┌单精度(float) │ ├浮点型┤ 数据类型┤ │ └双精度(double)
│ ├字符型 │ └布尔型 └构造类型─数组
特别要指出的是,在Java中没有指针类型。这是Java一个重要特征。这一特征避免了程序设计中如滥用内存等许多问题。这对保证Java应用程序的安全性很有好处。
2.2.1 整形
因所占字位的不同,整形分成四种类型:字节型(byte)占8字位,短型(short)占16字位,标准型(int)占32字位,长型(long)占64字位。 在Java中整形常量一般均以标准型即32字位的方式存储,当然,可通过在数值末尾附加l或L而以64位方式存储。 byte
x; short y; int number; long
value; 对于整型可使用的操作符及功能与C语言类似,如X++,++X等,此处不再复述。另在Java中提供了>>>操作符,其功能为右移补零(注意与>>的区别)。
请注意: (1)在Java中,只有当至少一个操作数为long型时,操作结果才为long型,否则均为int型(即使操作数为byte或short)。 (2)在Java中,所有的整形均是有符号的。 (3)运算结果出现下溢,最终结果为0;运算结果上溢时,则产生一个极大数,约为2.1亿。
2.2.2 浮点型
浮点型按IEE754中相关定义分成:单精度(float)型和双精度(double)型。float型占32字位,而double型占64字位。 float
xValue; double yValue; 在Java中,浮点型的数也可以作余运算(%)。 例
double
x,y; x=5.6; y=2.3; x%y=1.0; x/y=2.4347826086956523; Java中定义了inf这一浮点数来代表无穷大,运算结果上溢时则结果为inf。只有两个操作数均为float型时,结果才为float型,否则均为double型。 由于表示结构不同,与整型不同,在浮点数中x==y与x<y||x>y为真并非完全等价。这一点在编程时应加以注意。
2.2.3 字符型
字符串用char声明,用于存放单个字符。 char
ch; 由于Java采用16位的Unicode字符集,因此在Java中字符型是以16位无符号整数的形式存放的。 它与字符串(String)不同,字符串是通过Java类库中的String类实现操作的。
2.2.4 布尔型 布尔型变量使用boolean这一关键字进行声明。它只有true和false两个值。 例
boolean
openOn; 与有些语言不同,Java中布尔型变量不可能通过类型转换而变成数值。 (1)exp1&&exp2
当exp1=false时,不计算exp2的值。 exp1||exp2
当exp1=true时,不计算exp2的值。 (2)同C/C++中类似,Java允许使用?:形式。如 expression?State1:State2 若expression=true,则执行State1。 若expression=false,则执行State2。
表2.5 布尔运算符
|
操作符 |
功能 |
操作符 |
功能 |
|
! & | ^ |
逻辑非 逻辑与 逻辑或 逻辑与或 |
&& || == != |
逻辑与 在不需要时不计算右边 逻辑或
在不需要时不计算右边 相等 相等 |
2.2.5 数组
数组是Java语言中经常使用的类型。灵活运用数组可以适当弥补因Java语言不支持指针而带来的麻烦。 Java中数组的声明方法如下:
int[];//一维数组 float p[][];//二维数组 char
[]f;//Java中允许将[]前置。 在Java中,要真正命名一个变量为数组,必须使用new操作符。 int
i[]=new
int[3]; //创建了一个一维数组,这个数组包含i[0],i[1],i[2]三个整型成员。 对于多维数组至少要给出一维的大小。 int
f[][]=new int[3][]; int f[][]=new
int[3][3]; 与C中类似,数组中下标从0开始。
2.2.6 作用域与类型转换
在Java中用户可以在任何地方声明变量。变量的作用域是从变量的定义点开始到最近一个块的结束。一个块是指用{}括起来的区间。当在内层块与外层块定义了同名变量时,在内层块中将使用本层新定义,而外层定义被隐藏。这与C++是一致的。 例
{ ... int i=9; int
y; ... { ... int
i=3; y=i;//此处y=3,使用内层定义的i ... } y=i;//此处y=9,使用外层定义的i ... } Java支持普通的显式类型转换,但由于Java中不同类型所占字位数不同,转换后可能丢失信息,所以使用显式类型转换时,用户需自己确保赋值号右边的数在类型转换后不会丢失信息。 例 int
a; long b; float
c; a=(int)b;//将b转换成int类型并赋值给a。有可能丢失信息。 b=(long)a;//将a转换成long类型并赋值给b。不会丢失信息。 c=(int)c;//将c转换成int类型并赋值给a。有可能丢失信息。 (1)64位的long型数值若值不超过32位,可安全转换成int型; 若超过32位,强制转换成int型时会出现截位,从而丢失信息。 (2)32位float型浮点数转换成32位int型整数时也会丢失信息。 Java支持与C/C++中相同的隐式转换。这也有可能丢失信息而导致程序出错,所以赋值号左右类型不同时,应特别小心。 安全的类型转换包括: byte → short,char,int,long,float,double short
→ int,long,float,double char → int,long,float,double int →
long,float,double long → float,double float → double
2.3 控制流
Java的控制流语句与C/C++十分相似,它抛弃了容易产生问题的goto语句以提高程序正确率。为了弥补缺少goto语句带来的不便,Java允许在break和continue语句中附加标号(label),以实现goto语句的部分功能。 ■
if-else
语句 基本形式: if(布尔表达式)语句; 或 if(布尔表达式)语句 else 语句; ■ Switch
语句 基本形式: switch(表达式) { case
常量表达式1:语句1 case 常量表达式2:语句2 . . case
常量表达式n:语句n default :语句 } 表达式的值可以是byte,char,short或int型的。 ■label语句 基本形式: label:语句 注意,label不是保留字。它是一个语句标号,可以是一个名字或数字串。 ■break语句 基本形式: break; 或 break
label; 不带label的break语句功能是跳出break所在的这个块,至此块结束后的第一条语句处执行,而带有label则转向label定义处。 ■continue语句 基本形式: continue; 或 continue
label; 其作用为结束本次循环,开始下一轮循环,若有标号,则从标号处开始另一次执行。 ■return语句 基本形式: return 表达式; ■for语句 基本形式: for(表达式1;表达式2;表达式3) 语句功能与C相同。 ■while语句 基本形式: while(表达式)语句 ■do-while语句 基本形式: do 语句 while
(布尔表达式) 这两个语句实现功能及方式与C中同型语句完全一致。 例 下面我们给出了一个简单的例子来说明以上语句的功能。程序中输入一个数num,当num小于20且不能被3整除时,打印某些信息,然后将此数加5后再进行循环测试。 1:import
java.lang.*; 2:import java.io.*; 3: 4:class
Example{ 5: public static void main(String
args[]) 6: throws
java.io.IOException{ 7: System.out.print("Please innput
anumber:"); 8: System.out.flush(); 9: BufferedReader
input=new
BufferedReader(new 10: InputStreamReader(System.in)); 11: String
st=input.readLine(); 12: Integer n=new
Integer(st); 13: int num=n.intValue(); 14: int
i=0; 15: num=num-5; 16: 17: while(true){ 18: num=num+5; 19: if((num>20)&&(num%3)==0)break; //当num小于20且为偶数时,打印相关信息 20: if((num<=20)&&(num%2)==0){ 21: i=i+1; 22: System.out.println("I
am an
even."); 23: continue; 24: } //否则打印数值 25: i=i+1; 26: System.out.println("I
am an odd."); 27: System.out.println("Now num is
"+num); 28: } 29: System.out.println("the test is
end!"); 30: } 31:}
运行结果: D:\julie\tt\Exception>java Example Please
input a number:15 I am an odd. Now num is 15 I am an
even. I am an odd. Now num is 25 the test is
end! 输入15后,进入while语句,执行while语句中的第18、25、26和27行语句,(num=15)继续循环; 第二次循环,执行了执行while语句中的第18、20~24行语句(num=20)继续循环; 第三次循环,执行了执行while语句中的第18、25、26和27行语句,(num=25)继续循环; 第四次循环,执行了执行while语句中的第18、19行语句,(num=30)结束循环。 为方便广大熟悉C编程的程序员学习Java,Java的控制流语句与C/C++雷同。但请注意Java自己的特性,尤其是Java与C不同之处。比如前面已提到过的,在控制流语句中用作判别的布尔表达式,以Java中其值必须为布尔值(true或false),而不是像C/C++中可用0或1来替代。
2.4 面向对象的基本概念
Java作为一种新的程序设计语言,面向对象是它的一大特征。Java与C++不同,它是一个纯面向对象的语言,在后面的章节中将向读者充分显示Java面向对象的特征,为了方便不太熟悉面向对象的程序设计语言的读者的学习,本节介绍有关面向对象的基本概念,这些概念将在后面的章节中被使用。 ■对象 现实世界中的任何东西都可以是对象。它是通过封装的方法来构造的与现实世界具体成分相对的软件模块。对象是一个动态的概念,是对类进行具体实例化后形成的概念。 ■类 类是对对象的抽象及描述,是一些数据元素及其上操作的聚集。类刻划了一组具有公共特性的对象。类是一个静态的概念,它是一个型,而对象则对应一个值。类与对象的关系相当于模式和它的实例的关系。 ■继承 继承性是面向对象语言的一个重要特性。继承允许一个类成为另一个类的子类,从而提供了一种明确描述共性的方法,减少了类似的重复说明。在Java中任何一个类都有父类(除了object类以外)。继承机制提高了软件的利用
性,代码的复用性以及界面的一致性。 ■重载 一个单词代表两个或两个以上的含义则称重载。编译后此单词每个含义后可以对应于不同的代码结构。 例
void f() 与 void f(long
number) { { 代码行1 代码行2 } } 即为重载f这一方法。程序使用f()与f(12)会在编译时自动对应不同代码行,运算符+,-,*,/等都是重载的。 ■多态 多态性指相同的语言结构可以代表不同的实体或对不同类型的实体进行操作。它通过向不同的对象发送相同的信息,根据对象类的不同完成不同的工作。重载也是多态性的一种表现。多态性与动态绑定(dynamic
binding)有关。 ■动态绑定(dynamic
binding) 绑定(binding)指结构成分与其有关性质的确定和关联。如变量与其值、方法调用与相应可执行代码的确定和关联。静态绑定是指能在编译时刻完成的绑定。动态绑定则是在程序运行时刻完成的绑定。继承和动态绑定相结合成为一种特殊的多态性,它使高层代码(算法)也只需写一次,需通过提高不同的低层服务来满足复用的要求。 例
有类层次如下:
Man ┌────┼────┐ China America Japan
类Man中有方法speak。类China,America,Japan为类Man的子类,他们各自重写了继承自Man的方法speak。声明x为类Man的一个对象,则在执行时将根据接收者x的实际类型是什么(China,America或Japan或Man)来决定x.speak的实际执行代码。这就是动态绑定。动态绑定在某种程度上更好地体现了多态的优越性。
[目录][上页][下页]
|