`
strong_fee
  • 浏览: 178610 次
  • 性别: 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核心技术卷I 源代码 (第七版)

    《Java核心技术卷I》是Java开发者的经典参考书籍,它深入浅出地讲解了Java语言的基础和核心概念。第七版的发布,不仅包含了最新的Java版本特性,还对原有的内容进行了更新和完善,使得这本书更适合现代软件开发的...

    Java核心技术 卷 I+卷II 第11版 最新英文版 pdf

    《Java核心技术 卷 I+卷II 第11版 最新英文版》是Java开发者不可或缺的参考书籍,由Cay S. Horstmann和Gary Cornell两位资深Java专家撰写。这套书籍全面覆盖了Java语言的基础和高级特性,对于深入理解和掌握Java编程...

    Java核心技术卷一第10版PDF

    第五章至第七章将带你深入理解面向对象编程的核心概念,如类、对象、封装、继承、多态。这是Java的核心特性,也是区分它与其他编程语言的重要区别。通过实例,你将学会如何设计和使用类,以及如何利用继承和多态性...

    Java核心技术(卷I)基础知识(原书第9版)

    《Java核心技术(卷I)基础知识(原书第9版)》是一部深入讲解Java编程语言基础知识的权威参考书,由Cay S. Horstmann编写。本书自首版发行以来,一直受到广泛的认可和欢迎,是Java学习者必备的经典教材之一。在第九版中...

    Java核心技术卷I和II(第八版)

    《Java核心技术卷I和II(第八版)》是Java编程领域的权威指南,涵盖了从基础到高级的全方位知识。这两本书是Java开发者必备的学习资料,旨在帮助读者深入理解Java语言的本质和应用。 卷I主要侧重于Java的基础知识,...

    Java 核心技术 卷Ⅰ 基础知识 第11版 英文版

    《Java核心技术 卷Ⅰ 基础知识 第11版 英文版》是关于Java编程语言的权威指南,由Cay S. Horstmann撰写。这本书是Java学习者和专业开发者的宝贵资源,提供了Java编程语言的基础知识,并涵盖了许多高级话题。 EPUB是...

    java核心技术 卷1 第十版

    《Java核心技术 卷1 第十版》是一本深入讲解Java编程基础的经典著作,它涵盖了Java语言的核心概念和技术,是初学者和有经验的开发者提升技能的重要参考资料。此PDF版本并非扫描版,这意味着文本清晰可读,且具备目录...

    Java核心技术 卷II 高级特性 原书第10版 中文版

    根据提供的文件信息,“Java核心技术 卷II 高级特性 原书第10版 中文版”,我们可以推测这本书主要涵盖了Java高级特性的相关内容。由于实际的书籍内容无法直接访问,我们将基于标题、描述和部分可见的内容来推断并...

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

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

    Java核心技术卷I基础知识第10版高清完整版

    《Java核心技术卷I基础知识第10版》是Java开发者必读的经典教材,全面覆盖了Java编程的基础知识。这本书深入浅出地介绍了Java语言的核心概念,为读者提供了扎实的理论基础和实践经验。第10版更是对之前的版本进行了...

    JAVA核心技术-卷I 卷II-源代码

    《JAVA核心技术》是Java开发领域的经典著作,分为卷I和卷II,涵盖了Java语言的核心概念和技术。这本书深入探讨了Java编程的各种方面,是初学者和经验丰富的开发者的重要参考资料。源代码部分提供了书中示例和练习的...

    Java核心技术 卷I 基础知识(原书第8版)1

    《Java核心技术 卷I 基础知识》(原书第8版)是一本非常经典的书籍,它系统地介绍了Java语言的基础知识,并将其分为“基础篇”与“高级篇”两个部分进行阐述。本书旨在帮助读者掌握Java的核心概念和技术,无论你是...

    《Java核心技术 卷1 基础知识 原书第8版》 PDF+高清+影印+全书签.rar

    《Java核心技术 卷1 基础知识 原书第8版》是Java开发者必读的经典之作,全面深入地讲解了Java编程的基础概念和技术。这本书涵盖了从Java语言的语法到面向对象编程的核心原理,再到类库的使用,是学习Java开发的权威...

    core Java 11 Edition Java核心技术 卷一卷二

    《核心Java 11版:Java核心技术 卷一卷二》是Java开发人员的重要参考资料,涵盖了从基础到高级的广泛主题。这套书籍深入讲解了Java 11版本的关键概念和技术,旨在帮助读者全面掌握Java编程。 卷一主要关注基础知识...

    java核心技术卷

    本资源为“java核心技术卷(chm)”版本,是Prentice Hall PTR出版的第七版《Core Java 2 Volume I》的电子版,包含丰富的编程知识和实践案例。 在Java编程中,核心知识点涵盖了以下几个方面: 1. **Java基础**:...

    JAVA核心技术卷I源代码(第七版)

    《JAVA核心技术卷I源代码(第七版)》涵盖了Java编程语言的基础和核心概念,是学习和深入理解Java的宝贵资源。这份源代码包含了书中讲解的所有示例和练习,旨在帮助读者通过实践加深对理论知识的理解。 Java是面向...

    java核心技术卷1 mobi

    《Java核心技术卷1》是Java开发者必读的经典之作,它深入浅出地讲解了Java编程的基础概念和技术。这本书主要涵盖了Java语言的核心要素,为初学者和有经验的开发者提供了全面的知识框架。 首先,我们来看看“Core ...

    Java核心技术第九版卷1,2中英高清版及源码

    第九版卷1和卷2分别深入探讨了Java平台的核心概念和技术,包括类库、API和编程实践。以下是这两个卷中涵盖的一些关键知识点: 1. **基础语法**:Java的基础语法是学习的起点,包括变量、数据类型、运算符、流程控制...

Global site tag (gtag.js) - Google Analytics