`
strong_fee
  • 浏览: 175879 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

读《Java核心技术卷I 》Java继承<第五章>

    博客分类:
  • Java
阅读更多

1.      继承

(1)     继承格式

         class Manager extends Employee{

                  

}

Java用关键字代替C++中的:,在Java中,所有的继承都是公有继承,而没有C++中的私有继承和保护继承。

(2)     子类不能直接访问超类的私有成员,调用超类的方法时,可以使用关键字super,如super.getSalary()thissuper不是类似的概念,因为super不是对象的引用,不能将super赋值给一个对象变量,它只是一个指示编译器调用超类方法的特有关键字。

C++中调用超类的方法为超类名加上::操作符,如Employee::getSalary

(3)     super可以用来调用超类的构造器,如super(n, s, month, day);使用super调用构造器的语句必须是子类构造器的第一条语句。如果子类的构造器没有显示地挑用超类的构造器,则将自动地调用超类默认(没有参数)的构造器。如果此时超类没有默认的构造器,则Java编译器将报告错误。

C++中,使用初始化列表语法调用超类的构造函数,而不调用super,如:

Manager::Manager(String n, double s):Employ(n, s){

         bonus=0;

}

(4)       一个对象变量可以引用多种实际类型(Employee对象引用EmployeeManager对象),在运行时它能够自动地选择调用的是适当的方法。Java不支持多继承。可以将一个子类对象的引用赋值给一个超类变量,但是不能用这个引用调用子类的方法,不能将一个超类的引用赋给子类变量。

(5)       Manager[] managers=new Manager[10];

staff[0]=new Employee(…);编译器能够接纳这个赋值操作,此时,staff[0]managers[0]引用的是用一个对象,当调用managers[0].setBonus(1000)的时候,将会导致访问一个不W在的实例域,进而搅乱邻近存储空间的内容。W

(6)     过程在重载解析时,由于存在类型转化(int可以转化为double型,Manager可以转化成Employee),所以,如果编译器没有找到与参数类型匹配的方法,或者发现经过类型转化后又多个方法与之匹配,就会报告错误。如果在子类中定义了一个与超类签名相同的方法,那么子类中的这个方法就覆盖了超类的这个同签名的方法,但是子类方法的返回类型必须是原返回类型的子类型。如:

父类:public Employee getBuddy(){

}

子类:public Manager getBuddy(){

}

(6)       动态绑定

如果是privatestaticfinal或者构造器,编译器可以准确地知道应该调用哪个方法即静态绑定。采用动态绑定时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类方法。如果调用super.f(param),编译器将对隐式参数超类的方法表进行搜索。

Employee e;

e引用的是它的子类的一个实例时,如果子类覆盖了父类的方法,则用e调用这个方法时,调用的将是相应子类的方法。

2.      阻止继承:final类和final方法

(1)     声明格式如:

         final class Executive extends Manager{

        

}

final类不允许扩展,其中的方法自动成为final方法,不包括域。对于final域,创建对象后酒不孕需改变它们的值。类中的方法可以被声明为final,子类就不能覆盖这个方法。

         (2)     如果一个方法没有被覆盖并且很短,编译器就能够对它进行优化处理及内联,如e.getName()被替换为e.name

3.      将一个子类的引用赋值给一个超类变量编译器是允许的,但是将一个超类的引用赋值给一个子类变量,必须进行强制转换。在进行类型转换之前,先察看以下是否能够成功地转化,如:

         if(staff[1] instanceof Manager){

                   boss=(Manager) staff[1];

}

如果xnull,那么 x instanceof C不会产生异常,而是返回false

其处理过程类似于C++中的dynamic_cast操作,如:

Manager boss=(Manager) staff[1];等价于

Manager * boss=(dynamic_cast)<Manager *>(staff[1]);

当类型转化失败时,Java不会生成一个null对象,而是抛出一个异常。

4.          抽象类

(1)     格式如:

abstract class Person{

         public abstract String getDescription();

}

抽象类除了抽象方法之外,还可以包含具体数据和具体方法。在抽象类的子类中,仍然可以不定义抽象方法,而仍保持抽象性。即使不含抽象方法,也可以将类声明为抽象类。抽象类不能被实例化,但可以定义一个抽象类的对象变量,但是它只能饮用非抽象子类的对象,如:

Person p=new Student(“Vince Vu”);

C++中,只要有一个纯虚函数,这个类就是抽象类,没有提供用于表示抽象类的特殊关键字。纯虚函数的表示方法如:

class Person{

         public:

                   public string getDescription()=0;

}

(2)       由于不能构造抽象类Person的对象,所有变量p永远不会指向Person对象,而是引用诸如Employ这样的具体子类对象。如果Person超类中不定义抽象函数getDescription,则p就不能调用该方法了。

5.          Java用于控制可见性的4个访问修饰符

1)         仅对本类可见:private

2)         对所有类都可见:public

3)         对本包和所有子类都可见:protected

4)         对本报可见:默认。

6.          Object类型的变量只能用于作为各种值得通用持有者,要想对他们进行特定操作,需要清楚对象的原始类型,并进行相应得类型转换:Employee e=(Employee) obj.

Java中,只有基本类型不是对象,而所有的数组类型都扩展于Object类的类型,如:

Employee[] staff=new Employee[10];

obj=staff;

obj=new int[10];

C++中,没有根类,但是每个指针都可以转化为void

7.          Object

(1)     equals:在Object类中,这个方法将判断两个对象是否具有相同的引用。

         class Employee{

                   public boolean equals(Object otherObject){

                                     if(this==otherObject) return true;

                                     if(otherObject==null) return false;

                                     if(getClass()!=otherObject.getClass())

                                               return false;

                                     Employee other=(Employee)otherObject;

                                     return name.equals(other.name) && salary==other.salary

&& hireDay.equals(other.hireday)

}

}

getClass方法返回一个对象所属的类。比较子类是否相等的方法:

class Manager extends Employee{

         ...

         public boolean equals(Object otherObject){

                   if(!super.equals(otherObject)) return false;

                   Manager other=(Manager) otherObject;

                   return bonus==other.bonus;

}

}

一个完美的equals方法的建议

(1)       检测thisotherObject是否引用同一个对象

if(this==otherObject) return true;

(2)       检测otherObject是否为null

if(otherObject==null) return false;

比较thisotherObject是否属于同一个类,如果equals的语义在每个类种有所改变,则使用getClass检测,如:

if(getClass()!=otherObject.getClass()) return false;

如果所有的子类都拥有同一的语义,就是用instanceof检测,如:

if(!(otherObject instanceof ClassName)) return false;此时,可以将这个equals方法设置为final,因为它有超类确定相等概念,子类不拥有自己的相等概念。

(3)       otherObject转换位相应得类型变量,对所需要比较的域进行比较,如:

ClassName other=(ClassName) otherObject;

return filed=other.fild&&field.equals(other.field)…)

 

如果子类重新定义equals,就要在其中包含调用super.equals(other)

使用@Override对覆盖超类的方法进行标记,如:

@Override public Boolean equals(Object other)

如果子类定义了一个新的方法,编译器就会给出错误报告。

(2)       hashCode方法:

散列码:由对象导出的一个整形数。

String类的散列码计算方法:

int hash=0;

for(int i=0;i<length();i++){

         hash=31*hash+charAt(i);

}

 

String s=”OK”;

StringBuffer sb=new StringBuffer(s);

System.out.println(s.hashCode()+” ”+sb.hashCode());

String t=new String(“OK”);

StringBuffer tb=new StringBuffer(t);

System.out.println(t.hashCode() + “” + tb.hashCode());

 

st拥有相同的散列码,缓冲sbtb却有着不同的散列码,因为StringBuffer类中没有定义hashCode方法,它的散列码是由Object类的默认hashCode方法导出的对象存储地址。

equalshashCode的定义必须一致,如果x.equals(y)返回true,那么x.hashCode就必须与y.hashCode具有相同的值。

         (3)     toString()

                   绝大多数(但不是全部)toString方法都遵循这样的格式:类的名字,随后是一对方括号括起来的域值,如EmployeetoString的实现:

         public String toString(){

                   return getClass().getName()

                            +”[name=” +name

                            +”,salary=”+salary

                            + “,hireDay=”+hireDay

                            + “]”;

}

其中,getClass().getName()得到类名的字符串。

子类可以通过调用super.toString()来写自己的toString方法。随处可见toString方法的原因是:只要对象与一个字符串通过“+”链接起来,Java编译就会自动调用toString方法,以便获得这个对象的字符串描述。在调用x.toString()的地方可以用“”+x替代。System.out.println(x);println方法将直接调用x.toString()方法。

         Object类定义的toString方法,用来打印数出对象所属的类名和散列码,如System.out.println(System.out);输出内容为:java.io.PrintStream@2f6684

(4)     Class getClass() 返回包含对象信息的类对象,Java提供了类运行时的描述,它的内容被封装在Class类中。

         Class类的两个方法为:getName()返回该类的名字,getSupperclass()返回该类的超类信息。

(5)     Object clone() 创建一个对象的副本。

8.      泛型数组列表:

         (1)     Java中,允许在运行时确定数组的大小,如:

                   int actualSize= …;

                   Employee[] staff=new Employee[actualSize];

         (2)     构造一个保存Employee对象的数组类表:ArrayList<Employee> staff=new ArrayList<Employee>();

5.0后,没有后缀<…>仍然可以使用,它将被认为是一个删去了类型参数的“原始”类型。

         ArrayListVector更加有效。

         数组列表的容量与数组的大小有一个非常重要的区别,数组具有实际的空间,而数组列表只是由相应空间的潜力,完成初始化构造之后,数组列表可能不含有任何元素。

         C++中的赋值操作是值拷贝,而Java是引用拷贝。

         常用方法:

         <1>   构造方法

                   构造一个空数组列表 ArrayList<T>()

                   构造一个指定容量的空数组列表 ArrayList<T> (int initialCapacity)

         <2>   添加元素 add(T obj)

                                add(int index, T obj);在指定索引处插入值

         <3>   设置指定索引处的元素       void set(int index, T value);

         <4>   获得指定索引处的元素值 T get(int index);

         <5> 删除指定索引处的元素值,后面的元素前移 T remove(int index);

         <6> 返回存储在数组列表中的当前的元素数量 int size()

         <7>   ensureCapacity(int capacity) 确保数组列表在不重新分配内部存储空间的情况下就能够保存给定数量的元素

         如:访问数组类表的元素

                   Employee e=staff.get(i);

                   staff.set(i,harry)

                   ArrayList转换成数组,如:

X[]a =new X[list.size()];

list.toArray(a);

(3)       类型化参数与原始列表的兼容性

如下类:

         public class EmployeeDB{

                   public void update(ArrayList list){…}

                   pubic ArrayList find(String query){…}

}

可以将一个类型化的数组列表传递给update方法,而不需要任何类型转换,如:

ArrayList<Employee> staff=…;

employeeDB.update(staff); 此时编译器不会给出任何错误信息或警告。

将一个原始ArrayList赋值个一个类型化ArrayList会得到一个警告,如:

ArrayList<Empployee> result=(ArrayList<Employee>) employeeDb.find(query);此时会得到一个警告。

编译器在对类型进行检查后,如果没有发现违反规则的现象,就将所有的类型化数组类编转换成原始ArrayList对象,在程序运行时,所有的数组列表都是一样的。

8.          对象包装器

(1)     泛型变量要求传入的是对象类型,因此需要将基本类型转换成相应的对象类型,如:

         ArrayList<Integer> list=new ArrayList<Integer>();

         list.add的参数可以传入基本类型int,编译器将自动打包成Integer对象。

         将一个Integer对象赋给一个int值时,将会自动地拆包,如:

         int n=list.get(i);将自动翻译成int n=list.get(i).intValue();

         如果将经常出现的值包装到同一个对象中,那么这种比较就有可能相等。但是这种比较应该用equesl函数。Integer对象是不可变的,包含在包装器中的内容不会改变。

(2)       基本方法:

1)         int的形式返回Interger对象的值,如int intValue();

2)         int类型转化为String类型,如:

static String toString(int i)

static String toString(int i, int radix);其中radix为进制数

3)         String类型转化为int型,如:

static int parseInt(String s);

static int parseInt(String s);

4)         String类型转化为Integer类型

static Integer valueOf(String s);

static Integer valueOf(String s, int radix);

9.          参数数量可变的方法,如:

public class PrintStream{

         public PrintStream printf(String fmt, Object… args){

                   return format(fmt, args);

}

}

允许将一个数组传递给可变参数方法的最后一个参数,如:

System.out.println(“%d%s”, new Object[]{new Integer(1),widgets});

public static double max(double… values){

        

}

调用方法为:double m=max(3.1,6.2);

分享到:
评论
3 楼 zhangyou1010 2009-08-13  
zhangyou1010 写道
1.继承中的:
"(4)       一个对象变量可以引用多种实际类型(如Employee对象引用Employee和Manager对象),在运行时它能够自动地选择调用的是适当的方法。Java不支持多继承。可以将一个子类对象的引用赋值给一个超类变量,但是不能用这个引用调用子类的方法,不能将一个超类的引用赋给子类变量。"

有问题。父类引用可以指向子类对象,这个没错,但是"但是不能用这个引用调用子类的方法" 这里恰恰说反了,只能引用子类的方法,但不能引用子类的属性。


不好意思,我看错了,我以为楼主说的是不能调用子类override的方法。
2 楼 bubill 2009-08-13  
当打字员抄书?
1 楼 zhangyou1010 2009-08-12  
1.继承中的:
"(4)       一个对象变量可以引用多种实际类型(如Employee对象引用Employee和Manager对象),在运行时它能够自动地选择调用的是适当的方法。Java不支持多继承。可以将一个子类对象的引用赋值给一个超类变量,但是不能用这个引用调用子类的方法,不能将一个超类的引用赋给子类变量。"

有问题。父类引用可以指向子类对象,这个没错,但是"但是不能用这个引用调用子类的方法" 这里恰恰说反了,只能引用子类的方法,但不能引用子类的属性。

相关推荐

    java核心技术卷Ⅰ (高清中文版)

    第5章介绍了继承;第6章解释了接口和内部类;第7章概述了图形用户界面程序设计知识;第8章讨论AWT的事件模型;第9章探讨了SwingGUI工具箱;第10章讲解如何部署自己的应用程序或applet;第11章讨论异常处理;第12章...

    Java核心技术 卷1 基础知识 原书第9版

    《Java核心技术·卷1:基础知识(原书第9版)》共14章。第1章概述了Java语言与其他程序设计语言不同的性能;第2章讲解了如何下载和安装JDK及本书的程序示例;第3章介绍了变量、循环和简单的函数;第4章讲解了类和...

    Java核心技术 卷1 基础知识 原书第10版--中文版

    java核心技术第10版,基础卷,英文原版,《Java核心技术·卷1:基础知识》共14章。第1章概述了Java语言与其他程序设计语言不同的性能;第2章讲解了如何下载和安装JDK及本书的程序示例;第3章介绍了变量、循环和简单的...

    Thinking in java(中文)

    &lt;br&gt;6.8 final关键字&lt;br&gt;6.8.1 final数据&lt;br&gt;6.8.2 final方法&lt;br&gt;6.8.3 final类&lt;br&gt;6.8.4 final的注意事项&lt;br&gt;6.9 初始化和类装载&lt;br&gt;6.9.1 继承初始化&lt;br&gt;6.10 总结&lt;br&gt;6.11 练习&lt;br&gt;&lt;br&gt;第7章 多形性&lt;br&gt;7.1 上溯...

    Java基础教程

    Java基础教程&lt;br&gt;第1章 Java系统环境概述&lt;br&gt;第2章 Java语言基础&lt;br&gt;第3章 程序流程控制&lt;br&gt;第4章 类 与 对 象&lt;br&gt;第5章 消息、继承与多态&lt;br&gt;第6章 java数组&lt;br&gt;第7章 java字符串String&StringBuffer&lt;br&gt;第8章 java...

    软件工程思想

    &lt;br&gt;&lt;br&gt;第五章 系统设计&lt;br&gt;&lt;br&gt;5.1 体系结构设计&lt;br&gt;&lt;br&gt;5.1.1 层次结构&lt;br&gt;&lt;br&gt;一、上下级关系的层次结构&lt;br&gt;&lt;br&gt;二、顺序相邻关系的层次结构&lt;br&gt;&lt;br&gt;三、其它的层次结构&lt;br&gt;&lt;br&gt;5.1.2 Client/Server结构&lt;br&gt;&lt;br&gt;...

    JAVA程序设计教程电子教案

    &lt;br&gt;第1章 Java和面向对象概述&lt;br&gt;第2章 Java概述&lt;br&gt;第3章 Java语言基础&lt;br&gt;第4章 类和对象&lt;br&gt;第5章 继承&lt;br&gt;第6章 字符、字符串、数组&lt;br&gt;第7章 图形用户界面的设计与实现&lt;br&gt;第8章 Applet&lt;br&gt;第9章 Java高级编程...

    JAVA核心技术(卷1)基础知识(中文第8版)-part1

    第5章 继承 第6章 接口与内部类 第7章 图形程序设计 第8章 事件处理 第9章 Swing用户界面组件 第10章 部署应用程序和applet 第11章 异常、日志、断言和调试 第12章 泛型程序设计 第13章 集合 第14章 多线程

    Java学习教程课件

    第1章 Java系统环境概述&lt;br&gt;第2章 Java语言基础&lt;br&gt;第3章 程序流程控制&lt;br&gt;第4章 类与对象&lt;br&gt;第5章 消息、继承与多态&lt;br&gt;第6章 数组&lt;br&gt;第7章 字符串类&lt;br&gt;第8章 文字与图形GUI设计&lt;br&gt;第9章 常用组件GUI设计&lt;br&gt;第...

    Java核心技术卷一-完整书签-pdf

    第5章介绍了继承;第6章解释了接口和内部类;第7章概述了图形用户界面程序设计知识;第8章讨论AWT的事件模型;第9章探讨了SwingGUI工具箱;第10章讲解如何部署自己的应用程序或applet;第11章讨论异常处理;第12章...

    Java核心技术 卷Ⅰ:基础知识 【中文】(第八版)

    Java核心技术 卷Ⅰ:基础知识 【中文】 第1章概述Java与其他程序设计语言不同的性能。解释这种语言的设计初衷,以及在哪些方 面达到了预期的效果。然后,简要叙述Java诞生和发展的历史。 第2章详细地论述如何下载和...

    JAVA2核心技术(第二版中文PDF).part2.rar

    JAVA2核心技术(第二版中文PDF)本书一共17章。 目录见下: 第一章 java简介 第二章 java编程环境 第三章 java基本编程结构 第四章 对象与类 第五章 进一步介绍OOP:继承 第六章 用AWT进行图形程序设计 第七章 用AWT...

    JAVA2核心技术(第二版中文PDF).part1.rar

    JAVA2核心技术(第二版中文PDF)本书一共17章。 目录见下: 第一章 java简介 第二章 java编程环境 第三章 java基本编程结构 第四章 对象与类 第五章 进一步介绍OOP:继承 第六章 用AWT进行图形程序设计 第七章 用AWT...

    Java基础教程教学ppt

    &lt;br&gt;Java基础教程第五单元《对象生命周期》ppt+例程捆绑&lt;br&gt;Java基础教程第四单元ppt下载 第四单元例程包 &lt;br&gt;Java基础教程第三单元教学ppt &lt;br&gt;Java基础教程第二单元教学ppt&lt;br&gt;Java基础教程第一单元教学 word文档...

    Java JDK实例宝典

    13 Properties属性文件 &lt;br&gt;第5章 字符串 &lt;br&gt;5. 1 使用String &lt;br&gt;5. 2 基本数据类型与字符串的转化 &lt;br&gt;5. 3 判断Java标识符 &lt;br&gt;5. 4 使用StringBuffer &lt;br&gt;5. 5 IP地址转化成整数 &lt;br&gt;5. 6 18位身份证格式验证 ...

    Java核心技术卷一基础知识第10版

    第5章介绍继承;第6章解释接口和内部类;第7章讨论异常处理,并给出大量实用的调试技巧;第8章概要介绍泛型程序设计;第9章讨论Java平台的集合框架;第10章介绍GUI程序设计,讨论如何建立窗口、如何在窗口中绘图、...

    Java测试题2答案

    &lt;br&gt; }&lt;br&gt;}&lt;br&gt;&lt;br&gt;答案::填空第1题&lt;br&gt;x=10,a=3,b=4,c=5&lt;br&gt;填空第2题&lt;br&gt;java.util&lt;br&gt;填空第3题&lt;br&gt;(public )(static )(void)(main)(String args[])&lt;br&gt;填空第4题&lt;br&gt;1&lt;br&gt;填空第5题&lt;br&gt;

    Java核心技术 卷I(原书第8版).Part1 pdf

    第5章 继承 第6章 接口与内部类 第7章 图形程序设计 第8章 事件处理 第9章 Swing用户界面组件 第10章 部署应用程序和applet 第11章 异常、日志、断言和调试 第12章 泛型程序设计 第13章 集合 第14章 多线程

Global site tag (gtag.js) - Google Analytics