【Java精品源码栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了Java精品源码-【精品文档】Java语言规格说明1程序结构Java语言的源程序代码由一个或多个编译单元 - 其它管理文献的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
Java语言规格说明 1.程序结构
Java语言的源程序代码由一个或多个编译单元compilation unit组成每个编译单元只能包含下列内容空格和注释除外 一个程序包语句package statement 引入语句import statements 类的声明class declarations 界面声明interface declarations 每个
Java的编译单元可包含多个类或界面但是每个编译单元却至多有一个类或者界面是公共的。
Java 的源程序代码被编译之后便产生了
Java字节代码bytecode。
Java的字节代码由一些不依赖于机器的指令组成这些指令能被
Java的运行系runtime system有效地解释。
Java的运行系统工作起来如同一台虚拟机。
在当前的
Java实现中每个编译单元就是一个以.
java为后缀的文件。
每个编译单元有若干个类编译后每个类生成一个.class文件。
.class文件是
Java虚机器码。
2. 词法问题 在编译的过程中
Java源程序代码中的字符被划分为一系列的标记token。
Java编译器可以识别五种标记: 标识符、关键字、字面量、运算符以及特殊分隔符。
注释以及诸如空格、制表符、换行符等字符 都不属于标识之列但他们却常被用来分隔标记。
Java程序的编写采用泛代码Unicode字符集若采用其它的字符集则需在编译前转换成Unicode。
2.1 注释
Java语言提供了3种形式的注释 //text 从//到本行结束的所有字符均作为注释而被编译器忽略。
/ text / 从/到/ 间的所有字符会被编译器忽略。
/ text / 当这类注释出现在任何声明之前时将会作特殊处理它们不能再用在代码的任何地方。
这类注释意味着被括起来的正文部分应该作为声明项目的描述而被包含在自动产生的文档中。
2.2 标识符 标识符的首字符必须是一个字母下划线quot_quot或美元符号quotquot。
后面的字符也可是数字0-9。
Java使用泛代码字符集为了便于识别好一合法标识符下面列出它的“字母” 大写字母“A”“Z” 小写字母“a”“z” 泛代码Unicode 中所有字符编码在十六进制数00C0之前的字符。
标识符中首字母后的字符可以是任意的。
当然Unicode区段中那些被保留作特殊字符的除外。
由此“garton”及“MjΦlner”都是合法标识符但是包括诸如“π”的字符串却不是合法的。
2.3 关键字 下面的标识符被保留用作关键字他们不能作任何其它的用途。
abstract default goto null synchronized boolean do if package this break double implements private threadsafe byte else import protected throw byvalve extends instanceof public transient case false int return true catch final interface short try char finally long static void class float native super while const for new switch continue 其中加标记后是被保留但当前却未使用的。
2.4 字面量 字面量literal是某些类型值的基本表述这些类型包括整型浮点型布尔量字符及字符串。
2.4.1 整型字面量 整数可有三种表示形式 十进制八进制和十六进制。
一个十进制整型字面量由一系列的数字组成但它的第一个数字不能是0有时十进制数字也可象下面讲的那样加后缀。
整数也可表达成八进制或十六进制形式。
以0开头的整型字面量意味着它是一个十六进制的。
十六进制整数可以包括数字0-9以及字母a-f及A-F。
八进制整数中则只能是出现数字0-7。
在超过32位所能表示的范围之前整型字面量的类型即为int否则为long型。
一个整型字面量可通过加后缀L或l而强迫成long型。
下面的均为合法的整型字面量。
2 2L 0777 2.4.2 浮点字面量 一个浮点字面量可包括以下部分: 一个十进制整数一个小数点“.”小数部分另外一个十进制整数指数部分一个类型后缀。
指数部分是一个e或E后跟一个整数。
浮点字面量至少包含有一个数字外加或者一个小数点或者一个e或E下面举一些浮点字面量的例子 3.1415 3.1E12 .1e12 2E12 就象在后面描述的那样
Java语言有两种浮点类型 float 及double用户可按以下写法区分 2.0d或2.0D double 型 2.0f或2.0F或2.0 float型 2.4.3 布尔字面量 布尔boolean字面量有两个值 true及false。
2.4.4 字符字面量 字符字面量是一个由单引号括起的字符或者是由一组字符来表述一个字符。
字符属于char类型并且均从泛代码字符集中得来。
而下面列出的转义序列则用来描述一些非图形字符它们以反斜杠“”开始以作转义用。
续行符头 换行 NLLF n 垂直制表符 HT t 退格 BS b 回车 CR r 走纸换页 FF f 反斜杠 单引号 双引号 quot quot 八进制数 0ddd ddd 十六进制数 0xdd xdd 泛代码字符 0xdddd udddd 2.4.5 串字面量 串字面量是双引号引起的零个或多个字符的序列。
每个串字面量被看作是一个串对象而并非是一个字符的数组例如“abc”创建了一个新的串类的实例。
下面的都是合法的串字面量 quot quot 空串 quotquot quot 只包含一个双引号的串 quotThis is a stringquot quotThis is a two-line stringquot 2.5 运算符及特殊分隔符 下面这些字符在
Java源程序中作运算符或分隔符用 — amp / gt lt : · 另外下面这些复合字符被用作运算符 -- gt gtgtgt - / amp / gt gtgtgt ‖ ampamp 后面还要在运算符一节中作详细介绍。
3. 类型 任何一个变量或表达式都有一个类型类型决定变量可能的取值范围决定对这些值允许的操作以及这些操作的意义是什么。
Java语言中提供了内置定义类型程序员也可以利用类及界面interface机制构造新类型。
Java语言有两种类型 简单类型和复合类型。
简单类型指那些不能再分割的原子类型。
如整型、浮点型、布尔型、字符型均为简单类型。
复合类型建立在简单类型的基础上。
Java语言有三种复合类型数组、类及界面。
3.1 数值类型 3.1.1 整数类型 整数与C及C中相似但有两点区别 其一所有的整数类型均是独立于机器的其二对某些传统的定义作出改变以反映自C问世以来所带来的变化四种整数类型分别具有8位、16位、32位及64位的宽度并且均是有符号的signed。
如下所示 宽度 类型名 8 byte 16 short 32 int 64 long 一个变量的类型不会直接影响它的存储的分配类型仅仅决定变量的算术性质以及合法的取值范围。
如果把一个超出合法范围的值赋给一变量那么这个值将是对合法值域取模后的值。
3.1.2 浮点类型 关键字float表示单精度32位而double则表示双精度64位两个float型数运算的结果仍是float型若有其中之一为double型则结果为double型。
3.1.3 字符类型
Java全部使用泛代码字符集因此char类型数据被定义成一个16位的无符号整数。
3.2 布尔类型 当一个变量的取值或为ture或为false或者是当一个方法的返回值为ture或false时它nbsp嵌际遣级嘈偷摹硗猓叵翟怂愕慕峁嗍遣nbsp尔型的。
布尔值不是数值型因此不能用强制类型转换把它们转化成数值。
3.3 数组 数组在
Java语言中属第一类对象。
由它们代替了指针运算所有的对象包括数组都可通过标识来引用。
即使被当作数运算标识的值也不应被破坏。
通过new运算符可创建一个数组。
char snew char30 数组第一元素的下标为0在声明中指定维数是不允许的。
每次都必须显式地用new分配数组 int i new int 3
Java语言不支持多维数组但是程序员却可以创建数组的数组。
int i new int 34 至少有一维要明确给定而其它维则可在以后再确定。
例如 int i new int 3 是一个合法的声明。
除了在变量名及方法名后跟方括号这种C风格的声明之外
Java语言允许方括号跟在数组类型之后下面两行是等价的 int iarray int iarray 同样地方法声明也一样 byte fint n byte fint n 运行时检查下标保证它们是合法的 int a new int 10 a51 a1a0a2 a-14 // 运行时引发一个ArrayIndexOutOfBoundsException数组下标越界异常 a102 //运行时引发一个ArrayIndexOutOfBoundsException数组下标越界异常 数组的大小必须使用整数表达式 int n float arr new floatn1 数组的长度可通过.length 查找 int a new int 103 println a.length //打印出10 println a0.length //打印出3。
3.3.1 数组细节 定义的数组都是Object类的一个子类的实例在类的层次结构中有一个被称为Array的子类它有一个实例变量“length”。
对每一个基本类型都有一个相应的Array的子类。
同理每一个类也都有一个相应的Array子类存在。
例如 new Threadn 创建一个Thread 的实例。
如果类A是类B的超类那么A是B的超类见下图 Object Array A int float A B B 因此可以把数组赋给一个Object变量。
Object o int anew int 10 oa 并且可通过强制类型转换把object变量赋给一数组变量。
aint o Array类本身不能显式地产生子类。
4. 类 类class是传统面向对象编程模型的象征。
它们支持数据抽象以及实现对数据的约束在
Java中每一个新的类创建一个新类型。
要想得到一个新的类程序员必须首先找到一个已有的类新类即在这个已有类的基础上构造称之为派生derived。
派生出的类亦称为原来类的子类而这个类我们称为超类super class。
类的派生具有传递性 如果B是A的子类C是B的子类则C 是A的子类。
一个类的直接超类以及指示这个类如何实现的界面interface在类的声明中由关键字extends及implements标出。
如下示黑体表示关键字 doc_ comment modifer class ClassName extends Superclassname implements interface interface class body 举例 / 2 dimension point / public class Points float xy ...... / printable point / class PinttablePoint extends Points implements Printable ...... public void Print 所有的类均从一个根类 Object中派生出来。
除Object之外的任何类都有一个直接超类。
如果一个类在声明时未指明其直接超类那么缺省即为Object。
如下述 class Point float xy 与下面写法等价 class Point extends Object float x y
Java语言仅支持单继承通过一个被称作“界面”的机制来支持某些在其它语言中用多继承实现的机制详见“界面”一节。
Java之所以没有采用C的多继承机制是为了避免多继承带来的诸多不便例如可能产生的二义性编译器更加复杂程序难以优化等问题。
4.1 类类型之间的强制转换
Java语言支持在两个类型之间的强制转换因为每个类即是一个新的类型。
Java支持类类型之间的强制转换如果B是A的子类那么B的一个实例亦可作为A的实例来使用虽然不需要显式的转换但显式转换亦是合法的这被称作拓宽widening。
如果A的一个实例想当作B的实例使用程序员就应写一个类型转换叫作削窄narrowing的强制。
从一个类到其子类的强制转换在运行时要作例行的检查以确保这个对象就是其子类的一个实例或其子类之一。
兄弟类之间的强制类型转换是一个编译错误类的强制转换的语法如下nbsp nbsp classname ref 其中classname是要转换的目的类而ref是被转换的对象。
强制转换仅仅影响到对象的引用而不会影响对象本身。
然而对实例变量的访问却受到对象引用的类型的影响。
一个对象从一个类型到另一类型的强制转换后可以使同一变量名对不同的实例变量访问。
class ClassA String name quotClassAquot class ClassB extends ClassA //ClassB是ClassA的子类 String namequotClassBquot class AccessTest void test ClassB bnew ClassB println b.name //打印 ClassB ClassA a aClassAb println a.name //打印 ClassA 4.2 方法 方法method是可施于对象或类上的操作它们既可在类中也可在界面中声明。
但是他们却只能在类中实现
Java中所有用户定义的操作均用方法来实现。
类中的方法声明按以下方式 Doc_ comment Access Specifiers ReturnType methodNameparameterList method body本地的native及抽象的方法没有体部分 除构造函数可以无返回类型外其余的方法都有一个返回类型。
如果一个不是构造函数的方法不返回任何值那么它必须有一个void的返回类型。
参数表由逗号分隔的成对的类型及参数名组成如果方法无参数则参数表为空。
方法内部定义的变量局部变量不能隐藏同一方法的其它变量或参数。
例如 如果一个方法带以名为i的参数实现且方法内又定义一个名为i的局部变量则会产生编译错误例如 class Rectangle void vertex int iint j for int i0 i … 方法体内循环语句中声明的i是一个编译错误。
Java语言允许多态方法命名即用一个名字声明方法这个名字已在这个类或其超类中使用过从而实现方法的覆盖overriding及重载overloadding。
所谓覆盖是对继承来的方法提供另一种不同的实现。
而重载是指声明一个方法 它与另外一个方法有相同的名字但参数表不同。
注 返回类型不能用来区别方法即在一个类的范围内具有相同的名字相同的参数表包括个数、位置及类型的方法必须返回相同的类型。
若这样的两个方法有不同的返回类型将会产生一个编译错误。
4.2.1 实例变量 实例变量instance variables是指那些在类内声明但在方法的作用域之外尚未被static标记的变 参照 “静态方法变量及初始化”段。
而在一个方法的作用域之内声明的变量是局部变量。
实例变量可以有修饰符见修饰符。
实例变量可以是任何的类型并且可以有初始值。
如果一个实例变量无初始值它将被初始化成0。
布尔型变量被初始化成flase对象被初始化成null。
下面是一个实例变量j具有初始化值的例子 class A int j 23 …… 4.2.2 this 和super变量 在一个非静态方法的作用域内this这个名字代表了当前对象。
例如一个对象可能需要把自己作为参数传给另一个对象的方法 class MyClass void Method OtherClass obj … obj.Method this … 不论何时一个方法引用它自己的实例变量及方法时在每个引用的前面都隐含着“this”。
如 class Foo int abc ...... void myPrint print a quotnquot // aquotthis.aquot ...... super变量类似于this变量。
this变量实际上是对当前对象的引用它的类型就是包含当前正在处理的方法的类。
而super变量则是对其超类类型对象的引用。
4.2.3 设置局部变量 方法都要经过严格的检查以确保所有的局部变量在方法内声明的变量在被引用之前已设初被初始化之前就使用局部变量是一个编译错误。
4.3 覆盖方法 要想覆盖overiding一个方法必须在声明这个方法的类的子类中声明一个与它具有相同名字相同返回类型以及相同参数表的方法。
当子类的实例调用这个方法时被调用的是新定义的方法而不是最初的那个。
被覆盖了的方法可通过super变量来调用如下 setThermostat… //指覆盖的方法 super. setThermostat… //指被覆盖的方法 4.4 重载的认定 重载overload的方法与已有的某个方法同名但是变元的个数及/或类型不同重载的认定是要决定调用的是哪一个方法在认定重载的方法时不考虑返回类型。
方法可以在同一类的内部重载类内部方法声明的顺序并不重要。
可同时改变变元个数和类型来实现方法的重载。
编译器认定相匹配的方法时以最低的类型转换开销为准。
只有具有相同名字及相同变元个数的方法才会优先考虑。
所有变元都必须转换是匹配方法时的最大开销。
有两种变元类型是必需考虑的对象类型和基本类型。
对象类型间转换的开销的大小指类树上实在参数的类与原型参数的类之间连线的个数。
只考虑拓宽型转换对象类型转换的详细信息请参 阅“类之间的强制类型转换”。
对于类型完全匹配的变元无须进行转换它们的开销为零。
基本类型的转换开销按下表计算开销为零是严格匹配。
to byte short char int long float double byte 0 1 2 3 4 6 7 short 10 0 10 1 2 4 5 from char 11 10 0 1 2 4 5 int 12 11 11 0 1 5 4 long 12 11 11 10 0 6 5 float 15 14 13 12 11 0 1 double 16 15 14 13 12 10 0 注开销 gt10 易引起数据丢失。
一经认定某一匹配方法是哪种转换开销编译器则选用转换开销最小的匹配。
如果有多于一个方法其最小开销相同则匹配有二义性要出编译时的错误。
例如 class A int method Object o Thread t int methodThread tObject o void gObject oThread t methodot //调用第一个方法 methodto //调用第二个方法 methodtt //有二义性编译出错 4.5 构造函数 构造函数constructor是提供初始化的专用方法。
它和类的名字相同但没有任何返回类型。
构造函数在对象创建时被自动地调用它不能被对象显式调用。
如果你想在包package之外调用构造函数就将构造函数设为“public”。
构造函数也可以用不同个数和类型的参数重载就象其它的方法被重载一样。
class Foo int x float y Foo x0 y0.0 Foo int a xa y0.0 Foo float a x0 ya Foo int afloat b xa yb static void myFoo Foo obj1new Foo //调用Foo Foo obj2new Foo4 //调用Foo int a Foo obj3new Foo4.0 //调用Foo float a Foo obj4new Foo44.0 //调用Fooint a float b 超类的实例变量由调用超类的或当前类的构造函数初始化。
如果在代码中没有指定由谁初始化则调用的是超类中的无参数的构造函数。
如果一个构造函数调用了这个类或其直接超类的另一个构造函数这个调用必须是构造函数体的第一条语句在调用构造函数之前实例变量不引用。
调用直接超类的构造函数如下 class MyClass extends OtherClass MyClass someParamenters / 调用父类构造函数 / superotherParameters … … 调用当前类的构造函数如下示 class MyClass extends OtherClass MyClass someParameters … MyClassotherParameters /调用当前类的构造函数该函数有指定的参数表/ this someParameters … … 下面的Foo和FooSub类的方法中使用构造函数的例子 class Foo extends Bar int a Fooint a //隐含调用Bar this.aa Foo this 42 //调用Foo42代替Bar class FooSub extends Foo int b FooSub int b super13 //调用Foo13 去掉此行将调用Foo this.bb 4.6 用new运算符创建对象 类是用来定义对象的状态和行为的模板对象是类的实例。
类的所有实例都分配在可作无用单元回收的堆中。
声明一个对象引用并不会为该对象分配存储程序员必须显式地为对象分配存储但不必显式删除存储无用单元回收器会自动回收无用的内存。
分配对象存储用new运算符。
除了分配存储之外new还初始化实例变量调用实例的构造函数。
构造函数是初始化对象的一种方法见“构 造函数”下面的例子是分配并初始化ClassA的一个实例 a new ClassA 以下构造函数是带有参数的例子 b new ClassA32 分配的第三种形式允许以串表达式形式提供类名字字符串在运行时刻求值new返回一个Object类型的对象再转换成所希望的类型。
b new quotclassquotquotAquot 这种情况下调用构造函数时无需参数。
4.6.1 无用单元收集 无用单元收集器Garbage Collector使存储管理的许多方面变得简单、安全。
程序不需要显式释放内存它是自动处理的。
无用单元收集器不会释放正在被引用的内存只释放那些不再被引用的空间。
这就防止了悬挂指针和存储漏洞leak。
它也使设计人员从系统的存储管理中解脱出来。
4.6.2终止
Java的构造函数完成一个对象初始化工作
Java的终止finalization方法则完成和析构函数类似的功能但与C不同之处是它可显式调用。
虽然
Java的无用单元的回收功能可以自动地释放对象所占有的资源.