返回列表 发帖

[转帖]====JAVA初学教程进阶====

第一次:Java的语言基础
Java语言是目前最受欢迎的程序语言之一,与传统的程序语言相比(比如C、C++),Java语言简单易学,使用它编程时间短、功能强,人们接受起来也更快、更简便。Java主要具有以下三个特点:
第一, 跨平台,不管Windows还是Unix或者其他平台,它都可以使用;
第二, 面向对象;
第三, 动态域的控制。
1.1 初识Java语言
像其它编程语言一样,Java编程语言也被用来创建应用程序。那,首先我们还是从一个最普遍的小应用程序范例来切入——在屏幕上显示字串“Hello World!”。下列代码给出了这个Java应用程序。
1.1.1 HelloWorldApp
代码:
   1.//
   2.// Sample HelloWorld application
   3.//
   4.public class HelloWorldApp{
   5.public static void main (String args[]) {
   6.System.out.println ("Hello World!");
   7.}
   8.}


以上程序行是在你的屏幕上打印“Hello World!”所需的最少组件。接下来,我们就针对上面给出的这段程序来简单解释一下,并且来实际编译、运行它。
1.1.2 描述HelloWorldApp
第1-3行
程序中的1-3行是注释行
1 //
2 // Sample HelloWorld application
3 //
第4行
第4行声明类名为HelloWorldApp。类名(Classname)是在源文件中指明的,它可在与源代码相同的目录上创建一个classname.class文件。在本例题中,编译器创建了一个称为HelloWorldApp.class的文件, 它包含了公共类HelloWorldApp的编译代码。
4 public class HelloWorldApp{
第5行
第5行是程序执行的起始点。Java技术解释器必须发现这一严格定义的点,否则将拒绝运行程序。
其它程序语言(特别是C和C++)也采用main ()声明作为程序执行的起始点。此声明的不同部分将在本课程的后几部分介绍。
如果在程序的命令行中给出了任何自变量,它们将被传递给main()方法中被称作args的String数组。在本例题中,未使用自变量。
5 public static void main (String args[]) {
- public-方法main()可被任何程序访问,包括Java技术解释器。
- static- 是一个告知编译器main()是用于类HelloWorldApp中的函数的关键字。为使main()在程序做其它事之前就开始运行,这一关键字是必要的。
- void- 表明main()不返回任何信息。这一点是重要的,因为Java编程语言要进行谨慎的类型检查,包括检查调用的方法确实返回了这些方法所声明的类型。
- String args [] - 是一个String数组的声明,它将包含位于类名之后的命令行中的自变量。
java HelloWorldApp args[0]args[1]····
第6行
第6行声明如何使用类名、对象名和方法调用。它使用由System类的out成员引用的PrintStreamout对象的println()方法,将字串“Hello World!”打印到标准输出上。
6 System.out.println (“Hello World!”);
在这个例子中,println()方法被输入了一个字串自变量并将其写在了标准输出流上。
第7-8行
本程序的7-8行分别是方法main()和类HelloWorldApp的下括号。
7 }
8 }
1.1.3 编译并运行HelloWorldApp
编译
当你创建了HelloWorldApp.java源文件后,用下列程序行进行编译:
c:\student\javac HelloWorldApp.java
如果编译器未返回任何提示信息,新文件HelloWorldApp.class则被存储在与源文件相同的目录中,除非另有指定。
运行
为运行你的HelloWorldApp应用程序,需使用Java解释器和位于bin目录下的java:
c:\student\ java HelloWorldApp
Hello World!
1.1.4 严格的约定
通过上面实际编写、编译和运行这个简单的例子,我们会发现Java是一种限制很严格的语言。我们在编写Java程序的时候,一定要严格遵从它的约定,以后你会发现这些约定对维护和组织程序,使你养成一种优良的编程风格都很有帮助。
-> 源文件的类型
在Java中,一个源程序文件被称为一个编译单元。它是一个包含一个或多个类定义的文本文件。Java编译器要求源程序文件必须使用.java文件扩展名。这里可以注意到这个文件的扩展名是4个字符,所以,你的操作系统必须要有支持长文件名的能力。
-> 源文件的命名
如果.java文件包括一个公共类,那么它必须使用与那个公共类相同的文件名。例如在前例中的类的定义是
public class HelloWorldapp
源文件名则必须是HelloWorldapp.java
-> 类的数量
在源文件中,可以定义多个类,但每次只能定义一个公共类。
-> 标识符
Java中使用的标识符可以是大写和小写字母、数字、下划线(_)、美元符号($)的任意组合。以下是一些有效的标识符:
Year99 count this_is_ok $some
以下是一些无效的标识符:
99year hello# not/ok
这里需要提醒大家注意的是,Java是一种大小写敏感的语言,所以大家在书写代码的时候一定要注意大小写的运用。
1.2 结构与构件
现在,我们从一个典型的Java源文件来了解一下Java程序涉及到的一些重要的构件,以及这些构件的结构。
代码:
1 package trades;
2 import java.util.Math;
   3 public class Quote extends Thread implements Tradable {
4   // Code goes in here
5 }


那我们从上面的例子中可以发现源文件的结构主要包含三个要素:
-> 一个包声明(可选)
程序的第1行就是声明了一个包(package),把该程序放在这个包中间。
-> 任意数量的包引入语句(可选)
程序的第2行是要求该程序引入系统提供的一个包java.util.Math。
-> 任意数量的类的声明
程序的3-5行则是声明了一个public的类Quote,它是从它的超类Thread扩展得到,并且实现Tradable的接口。
该三要素必须以上述顺序出现。即,任何包引入语句出现在所有类定义之前;如果使用包声明,则包声明必须出现在类和引入语句之前。
结合上面的例子,我们接下来简单的讨论一下涉及到的这些构件,包package、包引入import、类class、方法method和变量variable。
1.2.1 包package
包实际上就是一个组织类class和接口interface的集合。通过包的这种机制,来把类名空间划分成更多易于管理的块。这样做其主要目的就是可以避免类名的冲突,在不同的包里的类,其名字相同也不会发生冲突。包的主要功能如下:
-> 依照功能来组织和划分类。例如:java.awt包含了构成抽象窗口工具包(AWT)的类,这个包被用来构建和管理应用程序的图形用户界面。
-> 有助于定义变量和方法的访问控制。
-> 通过这种包和包引入的机制,也可以保持程序的相对独立性,有利于模块化程序设计的实现。
声明包的定义语句必须放在源文件的顶端。如果你没有显式的声明一个包,那么Java会把你的类放入缺省包(default package)里面,这个包没有名字。
Java使用文件系统目录来存储包,目录名必须和包严格的匹配。另外,这里还要简单谈论一下类路径(CLASSPATH)环境变量的问题。Java编译器使用参考的包层次的根是由类路径决定的。例如,你可以在DOS系统环境下使用如下的命令来指定类路径:
set CLASSPATH=C:\Mysource;C:\Mypackages
如果我们在源文件类的声明前有以下语句:
Package trades.quotes
那么,这个源文件就放在下面这个目录里面:
c:\Mypackages\trades\quotes
最后,需要提醒的是,如果你定义的类已经指定到了某个包中,那么在运行的时候你也需要指定相应的包名和类名一起使用。
同学们可以结合实验二来加深对包概念的理解。
1.2.2 类class
类是面向程序设计中最小的抽象单元,它就像是一个数据和代码的容器。它也是Java里面最重要的一个要件。它通过实例化转变为对象,在实例化的时候自动调用构造函数来初始化对象。
对于类的声明比较复杂,它可以使用很多的修饰符,我们以下面的例子来简单谈论一下这些修饰符。
public abstract class Myclass extends Parent implements A,B {}
首先我们看到的public修饰符,是定义的类的访问控制属性,这个我们在下一章会有详尽的介绍。
然后我们看到的abstract修饰符是表示该类是个抽象类,需要其他类来扩展。这里再介绍一个final修饰符,它与abstract修饰符的意义正好相反,它表示该类不能扩展。所以abstract和final不能在声明类的时候同时使用。
在Java中所有的类都扩展一个超类,如果我们没有指定一个超类,那么系统会把Object类作为它要扩展的超类,Object类就是所有类的超类。这里需要注意的是,在C++中我们使用基类(base class)和继承类(derived class)的称谓,而在Java中我们一般称为超类(super class)和子类(subclass)。
另外,需要提一下的是一个特殊的关键字this,它用来引用正在被调用方法的所属当前对象。
1.2.3 接口interface
接口是一个非功能性、抽象的类,它包含常量和没有功能性的方法声明。也就是说,用interface,你可以指定一个类必须做什么,而不是规定它如何去做。接口在语句的构成上与类十分相似,但是它们缺少实例变量,而且它们定义的方法是不含有方法体的。
接口中声明的变量,一般是final和static型的,意思是它们的值不能通过实现类而改变,也就是说它们被看作是常量,而且它们还必须以常量值初始化。
对于接口来说,它们定义以后都是需要类来实现implement的。也就是说,使用具体的类来实现上面的“如何做”。一个类可以实现多个接口,一个接口也可以被多个类来实现。
另外,接口也可以扩展其他接口来实现继承。如:
interface MyInterface extends YourInterface, Runnable {}
1.2.4 方法method
方法声明的是被调用执行的代码,它可以使用传递的参数并且返回一定类型的返回值。对于方法的修饰符也比较复杂和繁多。我们仍然以一个例子来简单谈论以下其中的一些修饰符。
public static final synchronized double getPrice ( final int itemCode, Color itemColor ) throw Exception { /* code here */}
首先,Public是定义的方法的访问控制属性,这个我们在下一章会有详细介绍。
然后,static、final和synchronized是特殊的修饰符。同样需要注意的是其中final和abstract修饰符不能同时使用的。
最后,我们可以看到该方法getPrice返回一个double数据类型的返回值,而且里面定义了两个参数(itemCode和itemColor)。
另外,我们还注意它通过throw修饰符,表示它会抛出一个Exception的异常,关于异常我们在后面的章节会介绍到。
接下来我们会介绍两种比较特殊的方法。
-> Main方法
Main()方法是Java程序的入口起点,它和其他方法的定义类似,只是它包含一个字符串数组用来传递命令行方式执行程序时所跟的参数。如下的例子它把命令行方式所跟的参数全部显示出来:
代码:
public class MainTest {
    public static void main ( String [] args ) {
       for ( int i = 0 ; i < args.lenth; i++ ) {
           System.out.println(“Argument ” + i + “: ” + args );
       }
}
}

执行如下:
c:\java project\Main> java MainTest Philip K Dick
Argumet 0: Philip
Argumet 1: K
Argumet 2: Dick
这里需要注意的是,如果Main()方法没有使用static修饰符,那么编译不会出错,但是如果你试图执行该程序将会报错,提示main()方法不存在。这是因为你如果这样使用命令行的形式直接执行该程序,MainTest类并没有实例化,所以其main()方法也不会存在,而使用static修饰符则表示该方法是静态的,不需要实例化即可使用。
-> 构造函数Constructor Method
当类被实例化的时候,第一个被调用的方法就是构造函数。构造函数的主要作用就是初始化变量。如果没有定义构造函数,那么Java会使用其超类的默认构造函数。
构造函数与其他方法相比,主要具有以下的特点:
-> 构造函数的名字和其类名相同。
-> 没有返回值。
-> 构造函数不能像其他超类的方法那样被继承。
-> 不能使用final、abstract、synchronized、native或者static修饰符。
有时候,我们在编写构造函数的时候,可能需要首先调用其超类的构造函数,这里我们使用super的关键字,实际上它同this关键字的作用类似,只是它指的是其超类。如下的例子:
代码:
class DataServer extends Server {
    public String serverName;
    public DataServer ( int startCode ) {
       super ( startCode );
       serverName = “Customer Service”;
    }
}

需要注意的是,调用超类构造函数super()的语句必须放在其构造函数定义的前面,否则编译器会报错。
1.2.5 变量variable
变量是Java程序的一个基本存储单元。变量由一个标识符、类型及一个可选初始值的组合定义。此外,如同定义方法一样,它也有各种的修饰符。比如访问控制属性的修饰符public、private、protected和final、static等。这里需要注意的是,变量不能使用synchronized、abstract和native修饰符。
在定义变量的时候需要指明其类型,除了常用的基本类型(比如int型、Boolean型等)以外,也可以使用对象类型。
1.2.6 引入语句import
使用import引入语句是允许你选择某个包中的某个类或者所有类,使之能在你当前的代码中能方便的使用。例如:
import java.util.Dictionary; //引入java.util包中的Dictionary类
import javax.swing.*; //引入javax.swing包中的所有的类
当然如果你不使用引入语句也可以使用其他包中的其他的类,只要你指定引用对象的全名。比如:
java.util.Date now = new java.util.Date();
另外,java.lang包是会被自动引入到源程序中的。

[转帖]====JAVA初学教程进阶====

第三次:JAVA运算符 3 运算符 同大多数的编程语言一样,Java语言也包含了许多的运算符。如果大家学习过C或者C++,会发现下面介绍的各种Java的运算符都与之类似。 3.1.1 赋值运算符 = 这是任何编程语言的最基本的运算符,它用来给变量指定一个值。对于基本类型来说,赋值都便于理解,将新的值赋给变量并保存在变量中供使用。但对于对象类型来说,这里就有一点区别,特别需要提醒大家注意。 对象类型并不是把实际的值(这里是实例)赋给了对象类型的变量,而是赋给的一个参考指针。这样,源对象类型的变量和新的这个变量实际上是指向的同一个实例,如果使用其中一个让实例改变,那么相应的另一个所指向的实例也会改变。这里我们可以借用C里面的指针的概念来方便理解,但实际上Java是不具有指针的概念和定义的。 我们通过下面的例子可以进一步来理解这个概念。 代码: import java.awt.Dimension; class ReferenceTest { Dimension a = new Dimension ( 5,10 ); System.out.println (“a.height = ” + a.height ) ; Dimension b = a ; b.height = 30 ; System.out,println (“a.height = ” + a.height + “after change to b ”); } } 运行结果: c:\java Project\Reference>java ReferenceTest a.height = 10 a. height = 30 afer change to b 另外,赋值运算符还可以和其他的运算符,联合组成新的赋值符。如*=、/=、+=、-=等等,这于C或者C++类似。 3.1.2 比较运算符 比较运算符是用来对相同数据类型的变量进行大小或者是否相等、相同的比较,返回的是Boolean类型的值。因此也就大概分为两类。 n >、>=、<、<= 这是比较变量的大小关系,与我们学过的任何编程语言相同,就不再介绍了。 n = = 、! = 这是比较变量是否相等或相同。这对于平常的比较基本类型的变量容易理解,只是我们要强调一下对对象类型的比较。与我们前面介绍的赋值运算符类似的是,它也是进行的对其参考指针的比较,而并不是比较两个内容上的差别。我们可以借助下面的例子来理解。 代码: import java.awt.Button class CompareRefernce { public static void main ( String [ ] args ) { Button a = new Button ( “Exit”); Button b = new Button ( “Exit”); Button c = a; System.out.println ( “Is refernce a = = b ? ” + ( a = = b) ) ; System.out.println ( “Is refernce a = = c ? ” + ( a = = c) ) ; } } 运行结果: Is refernce a = = b ? false Is refernce a = = c ? true 3.1.3 instanceof运算符 这个是Java语言特殊的一个运算符,它是用来测试其对象是否属于某类或其超类。但是这里需要提醒大家的是,如果你使用instanceof来比较不是一个继承关系树上的类,Java能够编译通过,但运行的时候会报错。另外,你可以对null对象使用这个运算符,只是无论对于什么类测试的结果都是false。 3.1.4 算术运算符 加+、减-、乘*、除/和取模%运算,这与其他的编程语言类似,不再详述。 3.1.5 自增++、自减--运算符 Java的自增和自减运算符,与C语言类似,同样需要注意的是其放置的位置不同,可能的结果也不同。如果放置在变量的前面,表示先自增(减)再参与下步运算,而如果放置在后面则表示先参与运算再自增(减)。如下的例子说明了自增运算符的使用: 代码: class IncDec{ public static void main ( String [ ] args ) { int a = 1; int b = 1; int c; int d; c = ++b; d = a++; c++; System.out.println ( “a = ” + a ); System.out.println ( “b = ” + b ); System.out.println ( “c = ” + c ); System.out.println ( “d = ” + d ); } } 运行结果: a = 2 b = 2 c = 3 d = 1 3.1.6 字符串连接运算符 + Java语言与C语言类似,也使用+作为连接字符串的运算符,这实际是对String类重载了+运算符。 3.1.7 位运算符 包括位移运算和位逻辑运算,这也与C语言相似。 -> 位移运算 >>右移、<<左移、>>>无符号右移。 -> 位逻辑运算 &与、|或、^异或、~非运算,这于其他的编程语言类似,不再详述。 3.1.8 逻辑运算符 与&&、或||,这于其他的编程语言类似,不再详述。只是需要提醒大家不要把它们和位逻辑运算符混淆,这也是初学者最容易犯的错误。 3.1.9 条件运算符 ?: 这与C语言完全相同,具体不再解释。 3.1.10 类型转换 我们在编写程序的时候经常需要对变量的类型进行转换,Java语言与其他的编程语言类似,也提供两种类型转换方式,即显式转换和隐式转换。转换的对象可分为两类,一是基本类型,二是对象类型。 这里需要掌握这样一个要点。对于基本类型来说,凡是大转小(以类型的宽度考虑)需要使用显式转换,也就是需要在变量前面强制给出需要转换成的类型。而对小转大来说,系统会自行进行隐式转换。 对于对象类型来说,也与之类似。凡是超类转子类则需要使用显式强制转换,而子类转超类系统可自行进行隐式转换。另外还需要注意的一点是,对于不在一个继承关系树上的类要进行强制转换,Java编译可通过,但实际运行会出错。 3.2 equals()方法 equals()方法实际与= =运算符作用相同,也是用来比较相同类型的两个变量是否相同或相等。只是有点区别的是,对于String类来说,它重载equals()方法,使用它不是比较两个参考指针的区别,而是实际对所指向的具体内容进行比较,这也满足了平时我们对比较字符串的实际需求。当然,对其他类来说,你也可以重载equals()方法,使其满足你的实际需要,来比较两个对象类型的变量。 3.3 优先级 与其他编程语言类似的,Java语言的运算符同样涉及到优先级别的问题,书上130页从高到低给出了所有运算符的优先级。建议大家,如果对某些运算符之间的优先级不是很清楚的时候,可以使用()来改变它们的优先级关系。 3.4 方法的参数传递 最后,简单讨论一下方法的传递的问题。Java语言的参数传递类型主要可以分为两种,值传递和引用传递。借助C语言的概念,我们知道,第一种就是把参数值直接复制成方法体的参数,这样对方法体中的参数的改变不会影响到调用它的参数。而对于第二种,参数的引用(或者说是个指针)被传递给了方法体的参数,该引用用来访问调用中指定的实际参数。这样,对方法体参数的改变将会影响到调用方法体的参数。 由于没有指针的概念,Java的参数传递相对比较简单。对于一般的基本类型来说,都采用的是值传递;而对于对象类型则是使用的引用传递。

TOP

[转帖]====JAVA初学教程进阶====

第二次:修饰符
2.1 访问控制
封装将数据和处理数据的代码连接起来。同时,封装也提供了另外一个重要属性:访问控制。通过封装你可以控制程序的某个部分可以访问类的成员,防止对象的滥用,从而保护对象中数据的完整性。对于所有的面向对象的语言,比如C++,访问控制都是一个很重要的方面。由于Java语言使用了包的概念,使它的访问控制相对来说更复杂一些。我们把控制访问控制权限的修饰符主要分为两类,类和它的方法及变量,下面我们分别简单介绍。
-类的访问控制
-> Default:当类不使用任何访问控制修饰符时,即采用的默认的访问控制权限。它允许同一个包内的类访问,而对于它所在包以外的类则不能访问。
-> Public:允许任何包中的任何类访问,对Java里面的所有类开放。
-方法和变量的访问控制
-> Public:所有类均可以访问。
-> Private:只能被它所在的类中的成员访问,使该定义的成员对外在的类不可见。
-> Protected:可以被同一个包的类访问,另外其所有子类也可以访问。
-> Default:当成员不使用任何访问控制修饰符时,即采用默认的访问控制权限。它和Protected类似,唯一的区别在于子类访问权限,它仅允许同一个包的子类访问,而其他包中的子类则不可以访问。
2.2 其他修饰符
除了访问控制修饰符,Java还有其他繁多的修饰符来声明类、方法和变量,下面分别针对所修饰的对象来简单介绍一下主要的修饰符。
-类修饰符
-> final:用来指定该类不能被其他类扩展,从而阻止继承。
-> abstract:表示该类是不允许被实例化的类,也就是说该类需要被扩展继承。被这样声明的类也称为抽象类。
显而易见,final和abstract不能同时使用。
-方法修饰符
-> abstract:被声明的方法称为抽象方法,不含任何代码,需要其继承的子类的相应方法覆盖重载。这里需要注意的是被声明有abstract方法的类必须被声明为abstract。
-> final:声明的方法不允许被覆盖重载。
-> static:声明的方法被成为类方法,不依赖于任何的对象,不需要实例化对象即可直接使用类名来调用该方法。注意的是在该方法体内不可访问实例变量。
-> 变量修饰符
-> static:被声明为static的变量实际可以看作就是全局变量,同样不需要实例化对象即可直接使用类名来引用之。
-> final:被声明的变量的内容不可以被修改,实际可以被看作是一个常量,类似于C或者C++中的const。
2.3 缺省构造函数
我们都知道当对象被实例化的时候,构造函数总是被调用。如果我们在定义类的时候不指定一个构造函数,Java会自行创建一个不带参数的缺省构造函数。而如果我们定义有了一个构造函数,则Java不会再创建缺省构造函数。
更值得注意的是,如果子类的超类不含有不带参数的构造函数,那么子类在使用缺省构造函数就会出错,Java不会为子类创建不带参数的缺省构造函数。因此,我们在使用缺省构造函数的时候要比较小心。我们可以看如下的例子:
代码:
class Fruit {
    public Fruit ( String color ) {
       System.out.print ( “color = ” + color ) ;
    }
}
class Apple extends Fruit {
    public static void main ( String [ ] args ) {
       Apple m = new Apple () ;
       }
}

运行结果出错:
Fruit.java:6: No constructor matching Fruit ( ) found in class Fruit .
Class Apple extends Fruit {
1 error
2.4 合法的返回类型
由于在方法调用的时候,方法返回的类型有可能与实际声明的类型不同,因此我们需要关心什么样的返回类型才是合法的。实际上,系统采用了隐式的类型转换来处理类型的返回。以下几种情况的是合法的:
-> 如果声明的是浮点类型,那么可返回整型类型。
-> 如果声明的是整型类型,那么只要返回的整型类型范围小于或等于声明的类型,返回合法。
-> 如果声明的是对象类型,那么只要返回的是该对象类型,或者是其子类的对象类型,合法。

TOP

[转帖]====JAVA初学教程进阶====

1.3 关键字和标识符
Java语言一共使用了48个保留关键字,他们主要可以分为如下几类。
-> 访问控制
private , protected , public
-> 类、方法和变量修饰符
abstract , class , extends , final , implements , interface , native , new , static , strictfp , synchronized , transient , volatile
-> 程序控制语句
break , case , continue , default , do , else , for , if , instanceof , return , switch , while
-> 错误处理
catch , finally , throw , throws , try
-> 包相关
import , package
-> 基本类型
boolean , byte , char , double , float , int , long , short
-> 变量引用
super , this , void
-> 未使用的关键字
const , goto
这些关键字的具体意义可以参考语法书,这里就不再详细阐述了。
另外,除了这48个关键字以外,还有3个语法保留字,即null、true和false。
1.4 变量的初始化
变量从声明的位置来看可以分为两种类型,一是实例变量instance variable,即声明在类一级;另一种是局部变量local variable,它声明在方法一级。这两类变量除了声明的位置不同,它们最主要的区别在于是否需要初始化的问题。下面我们具体来讨论一下这个问题。
-> 实例变量
类的成员就是定义在类一级的变量。它们实际上是可以不需要初始化的,系统一般会自动给它们赋一个默认值。
-> 基本类型
对于8种基本类型来说,Boolean型默认赋值false,char型会默认为Unicode字符集的/u0000,而其余几种类型都默认为0。
-> 对象类型
对于对象类型,系统不会赋予任何默认值,但会表示为null。
-> 数组类型
数组类型于对象类型类似,当你不初始化它的时候,它也是等于null。但如果你初始化它,则有些不同,它与基本类型相似会默认为0。
-> 局部变量
对于局部变量,一般来说它必须初始化。因为无论是基本类型还是对象类型,系统都不会自动赋于任何默认值,所以你必须指定一定的值。当然,如果你定义了局部变量而不去使用它,编译也是可以通过的。

TOP

返回列表 回复 发帖