JAVA学习脚印5: 继承特性及特殊类
Posted The fool
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA学习脚印5: 继承特性及特殊类相关的知识,希望对你有一定的参考价值。
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;
@Override
public 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 array
people[0] = new Employee("Steven",5000,1985,9,4);
people[1] = new Student("Jobs","computer science");
//print info
for(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;
@Override
public 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 constructor
this.major = major;
@Override
public String getDescription()
// TODO Auto-generated method stub
return "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: 继承特性及特殊类的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL学习脚印: 视变换(view transformation)