丁保国的博客

收集整理工作生活,点点滴滴

  :: :: 博问 :: 闪存 :: :: :: :: 管理 ::

第五讲 类的封装和类的继承

主要内容

软件包的创建和使用

Java访问权限修饰词

类的访问权限修饰词

Java中类的层次结构和类的继承

对象的初始化再讨论

 

软件包的创建和使用

什么是软件包(package)

包的组成:由一组类(class)和接口(interface)组成。

Java允许把多个类收集在一起成为一组,称作包(package)。

 
 


包的作用:包是Java提供的一种类库的封装机制。专有的名字空间,解决了不同包中的类同名的问题。使自己的任务和其他人提供的代码库相分离。

 

软件包的建立

从示例程序理解

编译如下程序,查看所编译文件的位置。

package mylib.simple;

public class List{

   public List(){

        System.out.println("mylib.simple.List");

   }

}

结论

1、包对应着文件系统的目录层次结构。

2、编译生成的字节码文件将置放到包中,即包名所指定的目录中。

 

软件包的创建

package packagename;

几个要点:

package语句必须是文件中的第一条语句。

用“.”作为分隔符来指明包(目录)的层次。

包名由小写字母组成。

没有注明放入到某个包中去的类,自动地归在一个无名包中

 

软件包的使用

设置环境变量classpath

在Jcreator中添加classpath

使用如下两种方法之一:

² 用import加载包中的类:import 包名; import 包名.类名;

² 直接用包名.类名去访问类

 

说明

² import语句必须放在package语句和类的定义之间。

² 某个类若用到其他类,会优先在所在软件包中查找,继而在classpath指定的路径下查找。

 

例:创建一个newjw目录,在此新目录下创建如下java文件。

import mylib.simple.List;

class TestList{

   public static void main(String[] aa){

        new List();

   }

}

试用方法二改写并编译执行之。

思考

1.   一个程序的首语句是package a.b.c.d;其意是?

2.   一个程序中可含多个类,它们可分放到不同的软件包吗?

3.   若要使用d:\java07下的软件包,classpath如何设置?

4.   如何用到不同目录下的软件包myclass.lib1中的类?

5.   同一个软件包中的类可否直接使用?

6.   一个类设计成可被到处使用,应声明为public类吗?

7.   一个类用到其他类时,编译时的类查找路径是?

 

软件包的操作练习

练习:建立工具包,并使用之。

1. 设计一个P类置入mylib.tools包中,该P类含rint和rintln方法,可实现字符串的输出。

2. 用mylib.tools中的类P,分别输出字符串和数字。

import                         ;

class TestP{

   public static void main(String[] aa){

 

 

   }

}

3. 创建一个Input类,含有来输入整数或字符串的方法,以使下面的程序能正确编译和执行。

import mylib.tools.Input;

import mylib.tools.P;

class TestInput{

   public static void main(String[] aa){

        int y=Input.aInt();

        P.rintln(y+"");

        String s=Input.aString();

        P.rintln(s);

   }

}

练习

1. 分别构造一个Circle类和Square类,可接受半径(边长),包含求面积的方法。将它们放在myclass.simple包中。

2. 利用上述类,求半径为4.5的圆面积,边长为4.5和6.5的矩形面积。

 

Java访问权限修饰符

决定类成员的访问权限的修饰符有:public 、protected 、private。

权限的设定对于类的封装有着重要的意义。公开需要公开的,隐藏必须隐藏的。这样就让类的继承变得简单。

 

无权限修饰符的成员

允许本类、同一软件包中的类访问即享受“包访问权限”。

 

public成员

public描述的是一个类中可向外公开的信息(属性和方法)。

允许本类、继承类、同一软件包中的类、不同软件包中的类访问。

示例:不同软件包之间一个类访问另一个类的public成员。

package mylib.lib1;    //Base.java

public class Base{

   public int x=5;

   public void print(){

        System.out.println("base"+x);//本类访问

   }

}

 

package mylib.lib2;    //Derive.java

class Derive {

   public static void main(String args[]){

        mylib.lib1.Base b = new mylib.lib1.Base();

        b.x=5; //不同软件包的类访问

        b.print();

   }

}

思考

1.   程序编译后,磁盘上新增的目录结构?

2.   Base类中,可以公开的信息是?

3.   public的公开范围?

4.   如果Base类中的成员变量x前无public,会在何环节产生问题?

 

 

private成员

private修饰的成员变量和成员方法都只能在本类中访问

修饰不希望被其它类访问的变量和方法。有两种限制:

² 其它类中的该类对象不能访问private成员。

² 派生子类时,子类不能继承父类的private成员

class Base1{

   private int x=1;

   private void print(){

        System.out.println("base"+x);

   }

   void doprint(){

        print();

   }

}

class Derive1{

   public static void main(String args[]){

        Base1 b = new Base1();

        b.doprint(); //直接调用b.print();试试!

   }

}

观察JCreator中的数据视图(ctrl+alt+c),加深对private成员的认识。

 

假如构造方法是private的,类就不可直接实例化成对象:

class Sundae{

   private Sundae(){

        System.out.println("Here is a sundae");

   }

   static Sundae getASundae(){

        return new Sundae();

   }

}

class TestSundae{

   public static void main(String[] aa){

        Sundae s=Sundae.getASundae();

   }

}

protected成员

这是受保护成员。其修饰的数据和方法对继承它的子类公开。

protected成员允许本类、继承类和同一软件包中的类访问

包权限访问

class Base1{

   protected int x=1;

   protected void print(){

        System.out.println("base"+x);

   }

}

class Derive1{

   public static void main(String args[]){

        Base1 b = new Base1();

        b.print();

   }

}

继承类对protected成员的访问

package mylib.simple;//Cookie.java

public class Cookie{

   public Cookie(){

        System.out.println("Cookie constructor");

   }

   protected void bite(){System.out.println("bite");}

}

 

import mylib.simple.Cookie; //Chocolatechip.java

class Chocolatechip extends Cookie{

   Chocolatechip(){

        System.out.println("Chocolatechip");

   }

   public static void main(String[] aa){

        Chocolatechip c=new Chocolatechip();

        c.bite();    

   }

}

思考

1.   何谓类的封装?

2.   从封装角度比较以上不同的权限修饰?

3.   一个public成员向谁公开信息?

4.   一个protected成员向谁公开信息?

5.   一个private成员向其它类公开信息吗?

6.   private有何意义?

 

练习:试填表说明不同访问修饰符的访问权限

访问修饰符

本类

同软件包

不同包中子类

不同包且无继承

public

 

 

 

 

protected

 

 

 

 

无修饰词

 

 

 

 

private

 

 

 

 

 

类的访问权限

无访问修饰符

即为缺省类。可以被同一个软件包中的类访问。

 

public

通过import导入(配合classpath的设置),可以被任何其它的类访问。

public class 类名

思考

假如某一程序中定义了一个public类,框架如下:

package mylib.abc;

public class Abc{…}

 

1.   该程序应命名为?

2.   在另一个程序中如何能访问到Abc类?

3.   如果该类有显式的构造方法,并允许在其它类中创建该类的对象,构造方法的权限设置应是?

 

private类

专用于修饰内部类,内部类常用于处理本类中的事件。

 

类的继承

类的层次结构

指的是继承关系可以层次地递延下去。

在Java程序中创建的所有类都是类层次结构的部件

每个类都有父类

如果没有使用extends关键字,则Object类就是缺省的父类。

Object类包含在java.lang包中。所有的类都是从这个类继承而来的。

Object类定义和执行了在Java系统需要的所有类的行为。

 

类的层次结构图

 

思考

 

1.   根据层次结构图,每个类都有父类吗?

2.   如果类定义时无extends部分,该类的父类是?

3.   多个子类可以继承自一个父类吗?

4.   一个类可以同时继承多个父类吗?

5.   Object类在哪个软件包中?

 

 

类的继承(inheritance)

使用extends关键字实现继承

class SubClass extends SuperClass {

    ClassBody

}

 

父类和子类

继承另一个类的类称为子类,被继承的类称为父类。

在Java中一个类只能直接继承一个父类。

 

 

继承的意义

一个类能从其它类继承行为与属性。

 

例:通过对Person类的继承,定义Children类

class Person{

 int salary;

 void employed(){

       System.out.print("Work state:");

       if (salary==0) System.out.println("no job");

       else System.out.println("job");

 }

}

class Children extends Person{

 int age;

 void printAge(){

       System.out.println("Age:"+age);

 }

}

 

class Test{

 public static void main(String[] aa){

       Children c=new Children();

       c.salary=560;

       c.age=12;

       c.printAge();

       c.employed();

 }

}

思考

1.   一个类如何去继承另一个类?

2.   示例中Children继承了Persons类的什么?

3.   Children的实例化对象与Persons的实例化对象区别在哪里?

4.   若希望父类中的某成员不被子类所继承,如何实现?

 

练习:阅读和分析程序,理解继承。

import javax.swing.*;

class Test extends JFrame{

 public static void main(String[] aa){

       Test t=new Test();

       t.setVisible(true);

       t.setSize(300,200);

 }

}

 

对象的初始化再讨论

基本的初始化过程

² 初始化时涉及到成员变量和构造方法;

² 实例变量的初始化在构造方法之前。

class Tag{

   Tag(int m){

        System.out.println("Tag("+m+")");

   }

}

class Card{

   Tag t1=new Tag(1);

   Card(){

        System.out.println("Card()");

        t3=new Tag(33);

   }

   Tag t2=new Tag(2);

   void f(){

        System.out.println("f()");       

   }

   Tag t3=new Tag(3);

}

class TestInit2{

   public static void main(String[] aa){

        Card t=new Card();

        t.f();

   }

}

 

静态变量的初始化

类中的静态成员变量的初始化在编译时进行

静态变量只初始化一次

class Bow{

 Bow(int m){

       System.out.println("Bow("+m+")");

 }

 void f(int m){

       System.out.println("f("+m+")");      

 }

}

class Table{

 Bow b1=new Bow(1);

 Table(){

       System.out.println("Table()");

       b2.f(1);

 }

 static Bow b2,b3;

 static{

       b2=new Bow(2);

       b3=new Bow(3);

 }   

}

class TestInit{

 public static void main(String[] aa){

       System.out.println("Creating new Table()");

       new Table();

       System.out.println("Creating new Table()");

       new Table();

 }

}

 

思考

1. 对象的初始化在什么时候进行?

2. 静态变量和实例变量的初始化时机?

3. 实例变量和构造方法哪个先初始化?

4. 除了构造方法外,通常的成员方法会自动初始化吗?

5. 类有多个成员变量,这些变量的初始化顺序?

 

带有继承时的初始化过程

² 静态变量初始化

² 运行父类的无参数构造方法(按级别高到低)

² 本类实例变量初始化

² 运行本类的构造方法

class GrandParent{

 GrandParent(){

       System.out.println("GrandParent");

 }

}

class Parent extends GrandParent{

 Parent(){

       System.out.println("Parent");

 }

}

class Children extends Parent{

 Children(){

       System.out.println("Children");

 }

 public static void main(String[] a){

       new Children();

 }

}

问题:若类GrandParent类定义如下,程序运行结果?

class GrandParent{

 GrandParent(){}

 GrandParent(String s){

       System.out.println("GrandParent "+s);

 }

}

思考

1. 对象的初始化时,父类的什么样的构造方法能自动执行?

2. 父类构造方法的执行时机?

 

有关对象初始化的结论

继承时,初始化的顺序(包括构造方法):

主类中的静态成员初始化

运行父类的默认构造方法

(按级别高到低的顺序)

主类中非静态成员初始化

调用主类的构造方法

 

 

posted on 2010-12-08 09:58  丁保国  阅读(415)  评论(0编辑  收藏  举报