JAVA学习脚印5: 继承特性及特殊类
来源:互联网 发布:java编写中文软件 编辑:程序博客网 时间:2024/04/29 08:52
JAVA学习脚印5: 继承特性及特殊类
本节将学习类的继承特性及一些特殊类,本节所述实例中的类设计参考自《java核心技术》。
1.java继承特点
· java中使用关键字extends表示继承,所有的继承都是公有public继承(区别于c++中的三种继承方式即public、protected、private)。
· 子类中可以增加域、增加方法或者覆盖超类的方法,但是绝对不能删除继承的任何域和方法。因此在设计类的时候应该将通用的方法放在超类中,而将具有特殊用途的方法放在子类中。
· 子类可以通过super关键字类调用超类的方法或者超类的构造器,可以使用this关键字类引用隐式参数或者调用本类的其他构造器。注意super关键字不是一个对象的引用,不能将其赋给另一个对象变量,它只是一个编译器调用超类方法的特有关键字。
经理与雇员类的设计如图1所示:
图1 职员与经理类的继承关系图
测试代码如例5-1:
例5-1 ManagerTest.java
package com.learningjava;import java.util.Date;import java.util.GregorianCalendar;/** * this program demonstrate inheritance * from the book 《Core Java,Volume I:Fundamentals》 */public class ManagerTest {public static void main(String[] args) {Employee[] staffs = new Employee[3];staffs[0] = new Employee("Steve",5000,1985,9,4);staffs[1] = new Employee("Jason",6000,1983,8,12);Manager mgr = new Manager("Jery",8000,1980,11,7);mgr.setBonus(5000);staffs[2] = mgr;for(Employee item : staffs)System.out.println("name= "+item.getName()+",salary= "+item.getSalary());}}/** * a class to descript employee * from the book 《Core Java,Volume I:Fundamentals》 */class Employee {/** * @param name name to set * @param salary salary to set * @param hireday hireday to set */public Employee(String name, double salary, Date hireday) {this.name = name;this.salary = salary;this.hireday = hireday;setId();}/** * * @param name name to set * @param salary salary to set * @param year month day to create a GregorianCalendar */public Employee(String name, double salary, int year,int month,int day) {this.name = name;this.salary = salary;GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);this.hireday = calendar.getTime();setId();}public void raiseSalary(double percent) {double raise = salary*percent/100;salary += raise;}public String getName() {return name;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Date getHireday() {return hireday;}public void setHireday(Date hireday) {this.hireday = hireday;}public int getId() {return id;}private void setId() {this.id = nextId;nextId++;}private String name; private double salary;private Date hireday;private int id;private static int nextId = 1;}/** * a class to descript manager * */class Manager extends Employee {public void setBonus(double b) {bonus = b;}public Manager(String name, double salary, int year,int month,int day) {super(name, salary,year,month,day);bonus = 0;}public Manager(String name, double salary, Date hireday) {super(name, salary, hireday);bonus = 0;}@Overridepublic double getSalary() {double baseSalary = super.getSalary();return baseSalary+bonus;}private double bonus;}
· 检验是否应该使用继承的规则
类之间最常见的有三种关系即,依赖(use-a)、聚合(has-a)、继承(is-a)关系。
is-a表明子类的每个对象也是超类的对象。例如每个经理都是雇员,因此可以将Manager类设计成为Employee类的子类,反之每个雇员却并不都是经理。
2.java中的特殊类
1) final类——阻止继承
如果希望阻止人们继承某个类,可以使用final关键字将该类定义为final类,String类就是一个final类,声明为public final class String。final关键字作用于类的域时称为final域,表明该域在构造对象以后就不能修改其值了;final作用于方法时称为final方法,表明该方法不能被子类覆盖。注意,final类的方法自动地成为final方法,而域不自动为final域。
阻止继承主要是为了确保它们不会在子类中改变语义。
2) abstract类——高层次抽象
抽象类是对类进行高度抽象后形成的类,它比一般类更加通用。
规定,包含一个或多个抽象方法的类本身必须声明为抽象类。
抽象方法起着占位的作用,它的具体实现在它的具体实现子类中。注意,拓展抽象类有两种选择。一种是在子类中定义全部的抽象的方法,这样一来,子类不再抽象;还有一种是子类中定义部分抽象方法或抽象方法也不定义,这样子类也成为抽象类。
注意,类即使不含抽象方法,也可以将其声明为抽象类。
注意,抽象类不能创建出实例,而只作为派生其他类的基类。但是可以定义一个抽象类的 对象引用变量,用于引用非抽象子类的对象。
例如设计一个抽象类层次如下图2所示:
图2 抽象继承关系
具体可参考例5-2:
例5-2 PersonTest.java
package com.learingjava;import java.util.Date;import java.util.GregorianCalendar;/** * this program demonstrates abstract classes * from the book 《Core Java,Volume I:Fundamentals》 */public class PersonTest {public static void main(String[] args) {Person[] people = new Person[2];//fill arraypeople[0] = new Employee("Steven",5000,1985,9,4);people[1] = new Student("Jobs","computer science");//print infofor(Person item : people)System.out.println(item.getName()+","+item.getDescription());}}/** * an abstract class * with abstract method getDescription() */abstract class Person {public Person(String name) {super();this.name = name;} public String getName() { return name; } //abstract method public abstract String getDescription();private String name;}/** * a class to descript employee * from the book 《Core Java,Volume I:Fundamentals》 */class Employee extends Person{/** * @param name name to set * @param salary salary to set * @param hireday hireday to set */public Employee(String name, double salary, Date hireday) {super(name);this.salary = salary;this.hireday = hireday;setId();}/** * * @param name name to set * @param salary salary to set * @param year month day to create a GregorianCalendar */public Employee(String name, double salary, int year,int month,int day) {super(name);this.salary = salary;GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);this.hireday = calendar.getTime();setId();}public void raiseSalary(double percent) {double raise = salary*percent/100;salary += raise;}@Overridepublic String getDescription() {return String.format("an employee with a salary of ¥%.2f", salary);}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Date getHireday() {return hireday;}public void setHireday(Date hireday) {this.hireday = hireday;}public int getId() {return id;}private void setId() {this.id = nextId;nextId++;}private double salary;private Date hireday;private int id;private static int nextId = 1;}/** * a class to descript student * */class Student extends Person {/** * * @param name the student's name * @param major the student's major */public Student(String name,String major) {super(name);//pass the name to the superclass constructorthis.major = major;}@Overridepublic String getDescription() {// TODO Auto-generated method stubreturn "a student majoring in "+major;}private String major;}
3) Object类——所有类的超类
java中每个类都是由Object类派生而来的,如果没有明确指出某个类的超类,则该类的超类就是Object。
注意,Object类作为所有类的超类,这种类型的引用变量可以引用任何类型的对象。
但是要想对其引用的对象进行具体的操作,还需要清楚该对象该的原始类型,并进行相应的类型转换。如:
Object obj = new Student("Jobs","computer science");
Student stu = (Student) obj;//change to the origin type
还要注意,所有的数组类型,不管是对象数组还是基本数据类型的数组都拓展于Object类。
Student[] students = new Student[10];
Object obj = students;//ok
Object类有四个关键方法,需要我们注意,参见《JAVA学习脚印7: Object类的四个关键方法》。
4)enum枚举类
java中所有的枚举类型都是Enum类的子类,定义简单的枚举类如下:
public enum Size {SMALL,MEDIUM,LARGE,EXTRAL_LARGE};可以给枚举类增加构造函数、方法和域。
获取枚举常量时使用Enum类的静态方法valueOf,其原型为:
public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name)
例如: Size size = Enum.valueOf(Size.class, "SMALL");构造了枚举变量
注意,在比较两个枚举类型的值时,不要使用equals,而是直接使用"=="就可以了。
5)Class类
java运行时系统始终为所有的对象维护一个被称为运行时的类型标识,这个信息保存着每个对象所属的类足迹,保存着些信息的类被称为Class类。例如如下代码:
Manager mgr = new Manager("Jery",8000,1980,11,7);Class<? extends Manager> cl = mgr.getClass();System.out.println(cl.getName());System.out.println(cl.getClass().getName());
输出:com.learningjava.Manager
java.lang.Class
Class对象表示一个特定类的属性,例如这里的cl表示com.learningjava.Manager类的属性。
Class类是java语言提供的反射库中的一个类,能够分析类能力的程序被称为反射(reflective)。反射机制主要应用在工具构造上,反射机制可参考:《java学习脚印:Class类与反射机制》。
- JAVA学习脚印5: 继承特性及特殊类
- java学习脚印: java异常处理机制及实践方法
- java学习脚印:几种迭代方式
- java学习之路 之 高级类特性1-面向对象特征之二:继承及方法重写(override)
- JAVA学习脚印9:外部类与嵌套类
- java学习脚印:集合(Collection)之实现类
- java学习脚印:Class类与反射机制
- JAVA学习脚印4: 对象与类的概念
- JAVA学习脚印7 : Object类的四个关键方法
- JAVA学习脚印8: 类及其成员的访问权限
- JAVA学习脚印 1:开篇——初识java语言及开发环境
- java学习脚印:深入java绘图机制
- java学习脚印:深入java绘图机制
- java学习脚印:xml中空白文本结点(whitespace TextNode)处理及验证方法
- java学习脚印:xml中空白文本结点(whitespace TextNode)处理及验证方法
- java学习脚印 : 错误列表 Errorlist
- JAVA学习脚印 :日志文件的使用
- java学习脚印: 泛型(Generic)认识之一
- dev_t
- Android 开源框架ActionBarSherlock 和 ViewPager 仿网易新闻客户端
- 体验时间类的成员函数、友元函数和一般函数的区别
- POJ 3126 Prime Path
- Mysql-存储过程和存储函数笔记
- JAVA学习脚印5: 继承特性及特殊类
- fatal error LNK1120:error LNK2001: 无法解析的外部符号
- 有时候,你难免多心。心眼一多,许多小事就跟着过敏
- 动物统计加强版
- 中断处理
- Cassandra源码学习:数据读取
- MongoDB学习之旅三:MongoDB体系结构
- 七周 项目3 成员函数,友元函数,和一般函数的区别
- [ACM] hdu 2177 取(2堆)石子游戏(威佐夫博弈)