JAVA-面向对象的程序设计

本文介绍了面向对象的程序设计,特别是JAVA中的实现。重点讨论了对象、类、声明类、属性、方法、构造函数、信息隐藏(封装)以及源文件布局和软件包的概念。通过实例展示了如何声明和使用类,以及类的成员访问。强调了对象和类的关系,以及在JAVA中如何声明和初始化属性、声明方法,并提供了构造函数的使用示例。

第二章  面向对象的程序设计

l  2.1.简介

l   软件工程是艰巨的,难以驾御的学科。在过去的半个世纪里,计算机科学家、软件工程师、系统结构师们反复思考一个问题:如何通过代码重用使开发软件系统变得容易?最初的程序设计是用机器语言进行的,为了解决机器语言的复杂性,人们设计了“高级语言”。设计了系统过程调用,完成常用的相同的操作(如文件的打开、读、写)。

l   与此同时,另外一些开发者将公用的函数、过程收集组织到库中。例如:计算工程结构负荷的NASTRAN,在网络上的计算机之间传输字节流的TCP/IP,通过索引访问数据的ISAM(有序文件系统),在点阵监视器上生成窗口、图形、用户接口的X-WindowsOpenLook。这些函数库中的大部分采用“开放式记录数据结构”管理数据。采用“开放式记录数据结构”会带来这样的问题:函数库的设计者无法将数据从实现过程中隐藏起来。这个问题使得很难在不影响客户端代码的情况下修改实现过程,因为实现过程是与数据结构的细节紧密关联的。

l   上世纪八十年代晚期,面向对象的程序设计(OOP)在C++中流行起来。OOP技术的最大优点就是能够将数据隐藏起来。库的升级,不会对库的使用这造成影响。另一个优点是处理过程与数据结构相关连,将数据当成一个不可分割的整体。这个整体叫做类(class)。

l   上世纪九十年代,原来的函数库改称类库或工具包。新的类库提供的类完成的操作与旧库中的函数相同,而且通过使用子类,客户端程序员可以容易地扩展类库的功能。体系结构定义的APIs可以由许多不同的制造商实现,用户程序员拥有更大的选择余地。

l   Java技术是一个持续扩展的平台,新的APIs和体系结构不断补充进Java技术平台,例如:SwingJavaBeansJDBC等。

2.1.2对象

l     现实社会中一切皆对象。比如:人,树,石头,猫,鸟,汽车,地球等等。任何一种对象都具有静态的属性,但不一定具有动态的行为。比如:石头。一般情况下,对象既有静态的属性,也有动态的行为。对象本身的属性和行为之间可以相互影响,比如:一个人饿了(属性),就会去吃饭(行为)。相反,这个人吃饭(行为)后,就饱了(属性),体重(属性)也增加了。不同的对象之间也可以相互作用。比如:人看到汽车开过来了,就会沿着路边走。如果这个人站在路中间不动(他不怕死),那么汽车就会停下来。那么怎么用JAVA语言来实现上述功能呢??后面有例子的实现。

l    

2.1.3类

l   如同建筑设计师设计建筑图(建筑的蓝图),可以用该图来盖出许许多多这种风格的房子一样。类是软件的蓝图,你可以用类,来实例化许许多多个别的对象。在类中定义了一套数据元素(属性)和一套行为(方法)。行为用来操作对象,以及完成相关对象之间的交互。属性和方法都叫做成员。例如杯子装水的时候:最大盛水量和当前盛水量。盛水的方法要始终跟踪这两个属性。

2.2声明类

l   Java技术中采用下列方法声明类:

l   <modifier>  class  <name>{

l      <attribute_declaration>

l      <constructor_declaration>

l      <method_declaration>

l   }

l   说明:

l   <name>:任何合法的标识符。它代表所声明类的名称。

l   <modifier>:暂时只用“public”,含义为:可以被所有其它类访问。

l   <attribute_declaration>:声明属性。也就是说用变量表示事物的状态。

l   <constructor_declaration>:声明构造函数。

l   <method_declaration>:声明方法。

l   注意:属性,方法,构造函数在类中的顺序没有固定的约束。一般习惯性地先声明属性,后声明方法(构造函数也叫构造方法,习惯性地把构造方法写普通方法的前面)

2.2.1声明属性

l   句法:

l   <modifier>  <type>  <name>  [ = <default_value> ];

l    

l   说明:

l   <name>:任何合法的标识符。它代表所声明属性的名称。

l   <modifier>:暂时只用“private”,含义为:仅能被所属类中的方法访问。

l   <type>:可以是任何原始类型或其它类。

l   [=<default_value>]是给属性初始化为给定的值。如果没有的话初始化为默认的值。(基本类型的初始化相应的值:比如:intshortbytelongcharUnicode码值)初始化为0floatdouble初始化为0.0boolean初始化为false,所有的引用类型都初始化为null)。

l   注意:JAVA语言与其它语言不同,在JAVA中声明属性和初始化属性值必须一句完成。不能分开写:先声明,再另起一行初始化;

l   例如: int a ;

l          a=5;   是错误的

l   在类里面除了声明语句之外,是不能直接写其它执行语句的。 a=5 是赋值语句。执行语句放在块(方法块,初始化块等)里执行。

2.2.2声明方法

l   句法:

l   <modifier>  <return_type>  <name>  ( <parameter> ){

l      <statement>

l   }

l    

l   说明:

l   <name>:任何合法的标识符(已经被使用的除外)

l   <modifier>:可以是public,指明可以被任何其它代码访问。

l   protected:指明可以被同一个包中的其它代码访问。

l   private:指明仅能被同一个类中的其它代码访问。

l   < return_type>:指明方法返回值的类型。假如方法不返回值,应被声明为void

l   <parameter>:向方法传递参数。传递多个参数时,参数之间用逗号分开。每个参数由参数类型和标识符组成。

l   注意:方法必须有返回类型(构造方法除外),返回类型为void和没有返回类型是不一样的。除了返回类型void外,有其它返回类型的方法块里必须有return语句。

l    

l   例如:

l   public class Person //声明类

l   {

l      private int  weight;  //声明属性,初始化为默认值0

l  

l      public int getWeight() //声明方法

l             {

l         return weight;   //由于返回类型不是void,所以必须有return语句。

l      }

l    

l         public void  setWeight(int new_w)

l  {

l         weight = new_w; //该方法的返回类型是void的,所以方法块里可以没有return语句。

l      }

l   }

l    

l   说明:

l   Person有一个实例变量weight 。方法getWeight返回weight这个数据属性,方法getWeight没有参数。Return语句反回这个值。方法setWeight用参数new_w修改weight的值,它不返回任何值。

l   下面说明如何使用这个方法:

l   public class TestPerson{

l      public static void     main(String[ ] args){

l         Person  person = new Person( );

l    

l         person.setWeight(56);

l         System.out.println(“person.weight is “ + person.getWeight() );

l      }

l   }

l   输出结果为:

l         person.weight is 56

2.3访问对象的成员

l   在前面的例子中有下面的代码:

l   person.setWeight(56);

l   在方法的使用中,这行代码告诉对象person执行它的setWeight方法。这叫做点符号。它允许程序访问类的非私(non-private )有成员(属性和方法)

l   在方法的定义中,不需要使用点符号访问本地成员。例如Person类中的setWeight方法没有用点符号访问weight属性。

2.4信息隐藏(封装)

l   信息的封装其实就是在类里面把属性定义成私有,也就是把属性的访问权限定义成private。也就是说你不能直接在这个类的外面来操作这个属性。比如人这个对象,你只能通过吃饭来增加体重,或者做运动来减少体重,而不能直接修改体重(比如:不能把一斤猪肉粘在你的背上就是你的肉了,同样为了减肥,也不能直接从身上割块肉下来。)

l   如下事例:

l   public class Person

l   {

l      private int weight;//人的体重

l      public void eat(int w)//吃饭的方法

l      {

l           weight=weight+w;//体重增加

l             }

l   }

l   在使用中:

l   public class TestPerson

l   {

l       public static void main(String[] args)

l       {

l           Person p=new Person();

l           p.weight+=2 ;//错误,不能在类的外面访问类的私有成员(封装的好处)

l         p.eat(2);//正确,通过方法来改变对象的状态

l             }

l   }

2.5声明构造函数

l   我们经常要用类来实例化新的对象,一个新对象的初始化的最终步骤是去调用一个叫做构造函数的方法。构造函数是一套指令,用来初始化类的实例。可以向构造函数传递参数,其格式与向方法传递参数相同。构造函数用下列语法声明:

l   [<modifier>] <class_name> (<parameter>){

l      <statement>

l   }

l   声明构造函数的时候应该注意以下两点:

n       构造函数的名称必须与类名相同。

n       构造函数没有返回类型。

l   <modifier>:可以是public, protected, private

l   <parameter>:与方法的声明相同。

l   例如:

l   public class Person

l   {

l      private int weight;//人的体重

l    

l      public Person() //不带参数的构造函数,也就是默认的构造器

l      {}

l      

l       public Person(int w) //带参数的构造器,初始化属性weight 的值为 w

l             {

l                 weight=w;

l             } 

l    

l      public void eat(int w)//吃饭的方法

l      {

l           weight=weight+w;//体重增加

l             }

l              

l             public int getWeight()

l             {

l                 return weight;

l             }

l   }

l    

l   构造函数的调用方法如下:

l   public class TestPerson

l   {

l       public static void main(String[] args)

l       {

l           Person p1=new Person();    //调用不带参数的构造函数

l           Person p2=new Person(120); //调用带参数的构造函数

l           p1.eat(2);

l           p2.eat(2);

l           System.out.println(“person1’s weight is ”+p1.getWeight());

l           System.out.println(“person2’s weight is”+p2.getWeight());

l             }

l   }

l   输出结果为:

l   person1’s weight is 2

l   person2’s weight is 122

2.6默认的构造函数

l   每个类至少要有一个构造函数,如果你没有编写构造函数,Java编程语言会为你提供一个默认的构造函数。这个构造函数不带参数,函数体是空的。

2.7 源文件布局

l   Java技术源文件采用下面的布局:

l   [<package_declaration>]

l    

l   <import_declaration>

l    

l   <class_declaration>

l   以上条目的顺序不能改变。声明包的语句必须写在源文件的第一行。

l   源文件的名字必须与文件中声明的公有类的名字相同。一个源文件中可以包含多个类,但是最多只能包含一个公有类。如果源文件中不含公有类,源文件的名字不受限制。

l   例如,源文件TestDate.java的内容如下:

l   package shenzhen.luohu;

l            

l   import  java.util.Date;

l   import  java.io.*;

l    

l   public class TestDate{

l     

l        public static void main(String[] args)

l        {

l            System.out.println(new Date());

l        }

l   }

2.8软件包

l   多数软件系统是庞大的。为了方便管理,通常要将类组织成包。在包中可以存放类,也可以存放子包,从而形成具有层次结构的包。包可以根据需要任意组织,通常,要按照类的用途、含义来组织包。

l    

l  

l                                          2-2

l    

l   如图2-2所示,深圳市的软件系统可以组织如下:

l   nanshan:保存南山区的所有公司类。

l   futian :保存福田区的所有公司类。

l   luohu:保存罗湖区的所有公司类。

2.8.1声明包

l   Java技术提供了包的机制,以次来组织相关的类。声明包的句法如下:

l    

l   package <top_pkg_name> [.<sub_pkg_name>].*;

l    

l   你可以使用package命令指明源文件中的类属于某个特定的包。例如:

l   package shenzhen.luohu;

l   public class YuanBiao{

l     

l   }

l    

l   package命令必须放在源文件的最前面。一个源文件最多只能有一条package命令。一条package命令对源文件中的所有类起作用。如果你的源文件中没有package命令,你的类将会保存在当前目录。

2.8.2导入包

l   当你想要使用包中的类的时候,可以用import命令告诉编译器类在哪里。import命令的句法如下:

l   import  <pkg_name>[.<sub_pkg_name>].<class_name | *>;

l   例如:

l   import  shenzhen.nanshan.*;

l   import  shenzhen.futian.*;

l    

l   import  java.util.List;

l   import  java.io.*;

l   当你使用import指令时,你并没有将那个包或那个包中的类拷贝到当前文件或当前包中。你仅仅是将你在import指令中选择的类加入到你的当前名字空间。无论你是否导入当前包,当前包都是你的名字空间的一部分。

l   import命令指明你要访问的类。例如,你需要访问Writer类,你需要下面的命令:

l      import  java.io.Writer;

l   如果你需要访问一个包中的所有类,你需要下面的命令:

l      import  java.io.*;

2.9包与目录布局

l   2.9.1   包保存在目录结构中,包的名字就是目录的名字。例如,shenzhen.luohu包中的Company.class文件应该在 path/shenzhen/luohu目录中。

l   *运行的时候进入到path目录下:

l   path>java  shenzhen.luohu.Company 或者

l   path>java  Shenzhen/luohu/Company

l   注意:

l     不能把 shenzhen.luohu.Company或者shenzhen/luohu/Company写开运行!例如:你不能进入到shenzhen目录下运行:path/shenzhen>java luohu.Company或者path/shenzhen>java luohu/Company

l   也不能进入到上一及目录运行。假如你把shenzhen 放在daima文件夹里,你也不能进入到daima 那个文件所在目录下运行:path>java daima/shenzhen/luohu/Company 或者path>java daima.shenzhen.luohu.Company

l   上面是运行时的目录结构。在编译的时候用下面两种方式把包的结构生成出来。

1.             手动建立文件夹。把包的结构创建出来

l     例如:上面的两个包结构,可以在path目录下先建立个文件夹叫shenzhen ,打开shenzhen 文件夹,在该文件夹下再建立个文件夹叫luohu 然后进入luohu文件夹,编译Company.java

l     path/shenzhen/luohu>javac Company.java

2.             自动把包的目录结构生成出来。

l     例如进入到path目录下编译:path>javac –d  . Company.java 就自动把包的结构生成出来了。(.是代表当前目录也可以改成其他目录)

l     运行的步骤如*所述。

2.9.2  classpath环境变量的作用。

classpath 顾名思义,是classpath。是用来找类的。比如我把上面的shenzhen 目录指定一下。指定到d:/path/ ,就可以用下面代码来描述 :任意目录>set classpath=%classpath%;d:/path

那么就可以在任意目录下运行上面代码了。例如:在e:/test目录下运行

e:/test>java shenzhen/luohu/Company

也可以动态的指定到某一目录下:

例如:任意目录>java –classpath %classpath%;d:/path shenzhen.luohu.Company

或者:任意目录>javaw –classpath %classpath%;d:/path shenzhen.luohu.Company    

javaw表示运行完主线程退出程序,JBuilder工具就用此操作运行。                        

l    

2.10使用Java API文档

 Java API是扩展的Java类库。它为程序员提供了几千个类,包括基本的数学函数、数组和字符串、窗口,图形用户界面,输入/输出,联网等任何你需要的内容。

类库被组织成许多包,每个包都包含多个类。下面列举了一些重要的包:

·         java.lang:包含一些形成语言核心的类,如StringMathIntegerThread

·         java.awt:包含了构成抽象窗口工具包(AWT)的类,这个包被用来构建和管理应用程序的图形用户界面。

·         java.applet:包含了可执行applet特殊行为的类。

·         java.net:包含执行与网络相关的操作的类和处理接口及统一资源定位器(URLs)的类。

·         java.io:包含处理I/O文件的类。

·         java.util:包含为任务设置的实用程序类,如随机数发生、定义系统特性和使用与日期日历相关的函数。

 

Java API文档详细说明了Java API的使用方法。Java API文档是一组等级制布局的HTML文件,因而主页列出所有的包为超链接。如果选中了一个特殊包的热链接,作为那个包成员的类将被列出。从一个包页选中一个类的热链接将提交一页有关那个类的信息。

 

下载Java2 SE Version 1.4的文档并解压缩,打开 /api/Index.html 文件。

 

l   一个类文档的主要部分包括:

-          类层次

-          类和类的一般目的描述

-          成员变量列表

-          构造函数列表

-          方法列表

-          变量详细列表及目的和用途的描述

-          构造函数详细列表及描述

-          方法详细列表及描述

2.11事例代码

1PersonApp.java

class Person

{

private int weight;  //人的体重

private boolean hungry; //饥饿的属性

 

public Person(int w) //带参数的构造器,初始化人的体重

{

   weight=w;

}

   

public void setHungry() //用来设置饥饿这个属性,如果原来为true

{                       //就改为false,否则改为true

   if(hungry)

         hungry=false;

   else

         hungry=true;

}

 

public boolean getHungry()

{

    return hungry;

}

   

    public int getWeight()

    {

    return weight;

}

 

public void eat(int i)

{

      if(i>=2)                //东西多的时候,最多只能吃两斤。

      {

        weight=weight+2;    //体重增加2

            hungry=true ;       //表示吃饱了

      }

      else

            if(i>0&&i<2)        //当有东西吃的时候,并且少于2

          {

               weight=weight+i; //吃多少,体重就增加多少,但是返回false

               hungry=false;     //但是返回false,表示没吃饱

            }

        else

            hungry=false ;     //直接没东西吃,返回false

}

}

public class PersonApp

{

public static void main(String[] args)

{

     Person zhangsan=new Person(120);

         zhangsan.setHungry();

       if(zhangsan.getHungry()) //属性影响行为

             zhangsan.eat(2);     //行为改变属性

        System.out.println(zhangsan.getWeight());

}

};

2CarPersonApp.java

public class CarPersonTest

{

   public static void main(String[] args)

   {

      Person p=new Person();

      Car    c=new Car();

      c.move(true);   //车在行驶

      p.walk(c.getMoving());//测试人是否能行走,也就是说车的行为,影响了人的行为

   }

}

class Car

{

   private boolean moving;

   public boolean getMoving()

   {

       return moving;

   }

   public void move(boolean side)

   {

      if(side)

      {

          System.out.println("车继续行驶");

        moving=true;

      }

      else

      {

         System.out.println("车停下来");

         moving=false;

      }

   }

};

class Person

{

   boolean side; //表示人是否在路边

   public boolean walk(boolean car)

   {

      if(car)  //如果有车的话,人往路边走

      {

        System.out.println("人往路边走");

       side=true;

       return side;

      }

 

      else

      {

          System.out.println("人直着走");

         side=false;

         return side;

       }

        

   }

};

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值