程序清单 11-1 GeometricObject.java
public class GeometricObject { private String color = "white"; private boolean filled; private java.util.Date dateCreated; /** * Construct a default geometric object */ public GeometricObject(){ dateCreated = new java.util.Date(); } /** * Construct a geometric object with the specified color and filled value */ public GeometricObject(String color, boolean filled){ dateCreated = new java.util.Date(); this.color = color; this.filled = filled; } /** * Return color */ public String getColor(){ return color; } /** * Set a new color */ public void setColor(String color){ this.color = color; } /** * Return filled. Since filled is boolean * its getter method is named ifFilled */ public boolean isFilled() { return filled; } /** * Set a new filled */ public void setFilled(boolean filled) { this.filled = filled; } /** * Get dataCreated */ public java.util.Date getDateCreated() { return dateCreated; } /** * Return a string representation of this object */ public String toString(){ return "created on " + dateCreated + "\ncolor: " + color + " and filled: " + filled; } }
程序清单 11-2 Circle.java
public class Circle extends GeometricObject { private double radius; public Circle() { } public Circle(double radius) { this.radius = radius; } public Circle(double radius, String color, boolean filled) { this.radius = radius; setColor(color); setFilled(filled); } /** * Return radius */ public double getRadius() { return radius; } /** * Set a new radius */ public void setRadius(double radius) { this.radius = radius; } /** * Return area */ public double getArea() { return radius * radius * Math.PI; } /** * Return diameter */ public double getDiameter() { return 2 * radius; } /** * Return perimeter */ public double getPerimeter() { return 2 * radius * Math.PI; } /** * Print the circle info */ public void printCircle() { System.out.println("The circle is created " + getDateCreated() + " and the radius is " + radius); } }
关键字extends(第1行)告诉编译器,Circle 类继承自GeometricObject类,这样,它就继承了getColor、setColor、isFilled、setFilled 和 toString 方法。
重载的钩爪方法Circle(double radius, String color, boolean filled) 是通过调用setColor 和 setFilled 方法来设置color 和filled 属性的(第14和15行)。这两个公共方法是在父类GeometricObject中定义的,并在Circle 中继承,因此可以在Circle 类中使用它们。
你可能会试图在构造方法中直接使用数据域color 和filled ,如下所示:
public Circle(double radius, String color, boolean filled){ this.radius = radius; this.color = color; //Illegal this.filled = filled; //Illegal }
这是错误的,因为GeometricObject类中的私有数据域color 和 filled是不能被除了GeometricObject类本身之外的其他任何类访问的。唯一读取和改变color 与 filled 的方法就是通过它们的获取方法和设置方法。
Rectangle 类(程序清单11-3)使用下面的语法继承GeometricObject类(程序清单11-1);
关键字extends(第1行)告诉编译器Rectangle 类继承自GeometricObject类,也就是继承了getColor、setColor、isFilled、setFilled 和toString 方法
程序清单 11-3 Rectangle.java
public class Rectangle extends GeometricObject { private double width; private double height; public Rectangle() { } public Rectangle(double width, double height) { this.width = width; this.height = height; } public Rectangle(double width, double height, String color, boolean filled) { this.width = width; this.height = height; setColor(color); setFilled(filled); } /** * Return width */ public double getWidth() { return width; } /** * Set a new width */ public void setWidth(double width) { this.width = width; } /** * Return height */ public double getHeight() { return height; } /** * Set a new height */ public void setHeight(double height) { this.height = height; } /** * Return area */ public double getArea() { return width * height; } /** * Return perimeter */ public double getPerimeter() { return 2 * (width + height); } }
程序清单 11-4 TestCircleRectangle.java
public class TestCircleRectangle { public static void main(String[] args) { Circle circle = new Circle(); System.out.println("A circle " + circle.toString()); System.out.println("The color is " + circle.getColor()); System.out.println("The radius is " + circle.getRadius()); System.out.println("The area is " + circle.getArea()); System.out.println("The diameter is " + circle.getDiameter()); Rectangle rectangle = new Rectangle(2,4); System.out.println("\nA rectangle " + rectangle.toString()); System.out.println("The area is " + rectangle.getArea()); System.out.println("The perimeter is " + rectangle.getPerimeter()); } }
构造方法用于构建一个类的实例。不同于属性和普通方法,父类的构造方法不会被子类继承。它们只能使用关键字super从子类的构造方法中调用。
调用父类构造方法的语法是:
super() 或者 super(arguments);
语句super( ) 调用父类的无参构造方法,而语句super(argument) 调用与arguments 匹配的父类的构造方法。语句super( ) 或super(arguments) 必须出现在子类构造方法的第一行,这是显式调用父类构造方法的唯一方式。例如,在程序清单11-2中的第11~16行的构造方法可以用下面的代码替换:
public Circle(double radius, String color, boolean filled){ super(color, filled); this.radius = radius; }
要调用父类的构造方法就必须使用关键字super,而且这个调用必须是构造方法的第一条语句。在子类中调用父类构造方法的名字会引起一个语法错误。
构造方法可以调用重载的构造方法或父类的构造方法。如果它们都没有被显式地调用,编译器就会自动地将super( ) 作为构造方法的第一条语句。例如:
在任何情况下,构造一个类的实例时,将会调用沿着继承链的所有父类的构造方法。当构造一个子类的对象时,子类的构造方法会在完成自己的任务之前,首先调用它的父类的构造方法。如果父类继承自其他类,那么父类的构造方法又会在完成自己的任务之前,调用它自己的父类的构造方法。这个过程持续到沿着这个继承层次结构的最后一个构造方法被调用位置。这就构造方法链(construct chaining)。
思考下面的代码:
public class Faculty extends Employee{ public static void main(String[] args){ new Faculty(); } public Faculty(){ System.out.println("(4) Performs Faculty's tasks"); } } class Employee extends Person{ public Employee(){ this("(2) Invoke Employee's overloaded constructor"); System.out.println("(3) Performs Employee's tasks"); } public Employee(String s){ System.out.println(s); } } class Person{ public Person(){ System.out.println("(1) Performs Person's tasks"); } }
程序清单 11-5 PolymorphismDemo.java
public class PolymorphismDemo { /** * Main method */ public static void main(String[] args) { //Display circle and rectangle properties displayObject(new Circle(1, "red", false)); } /** * Display geometric object properties */ private static void displayObject(GeometricObject object) { System.out.println("Created on " + object.getDateCreated() + ".Color is " + object.getColor()); } }
程序清单 11-6 DynamicBindingDemo.java
public class DynamicBindingDemo { public static void main(String[] args) { m(new GeometricObject()); m(new Student()); m(new Person()); m(new Object()); } public static void m(Object x) { System.out.println(x.toString()); } } class GraduateStudent extends Student { } class Student extends Person { @Override public String toString() { return "Student"; } } class Person extends Object { @Override public String toString() { return "Person"; } }
程序清单 11-7 CastingDemo.java
public class CastingDemo { /** * Main method */ public static void main(String[] args) { //Create and initialize two objects Object object1 = new Circle(1); Object object2 = new Rectangle(1, 1); //Display circle and rectangle displayObject(object1); displayObject(object2); } /** * A method for display an object */ public static void displayObject(Object object) { if (object instanceof Circle) { System.out.println("The circle area is " + ((Circle) object).getArea()); System.out.println("The circle diameter is " + ((Circle) object).getDiameter()); } else if (object instanceof Rectangle) { System.out.println("The rectangle area is " + ((Rectangle) object).getArea()); } } }
程序清单 11-8 TestArrayList.java
import java.util.ArrayList; public class TestArrayList { public static void main(String[] args) { //Create a list to store cities ArrayList<String> cityList = new ArrayList<>(); //Add some cities in the list cityList.add("London"); //cityList now contains [London] cityList.add("Denver"); //cityList now contains [London,Denver] cityList.add("Paris"); //cityList now contains [London,Denver,Paris] cityList.add("Miami"); //cityList now contains [London,Denver,Paris,Miami] cityList.add("Seoul"); //cityList now contains [London,Denver,Paris,Miami,Seoul] cityList.add("Tokyo"); //cityList now contains [London,Denver,Paris,Miami,Seoul,Tokyo] System.out.println("List size? " + cityList.size()); System.out.println("Is Miami in the list? " + cityList.indexOf("Denver")); //Print false System.out.println("Is the list empty? " + cityList.isEmpty()); //Insert a new city at index2 cityList.add(2, "Xian"); //Contains [London,Denver,Xian,Paris,Miami,Seoul,Tokyo] //Remove a city from the list cityList.remove("Miami"); //Contains [London,Denver,Xian,Paris,Seoul,Tokyo] //Remove a city from the list cityList.remove(1); //Contains [London,Xian,Paris,Seoul,Tokyo] //Display the contents in the list System.out.println(cityList.toString()); //Display the contents in the list in reverse order for (int i = cityList.size() - 1; i >= 0; i--) { System.out.print(cityList.get(i) + " "); } System.out.println(); //Create a list to store two circles ArrayList<Circle> list = new ArrayList<>(); //Add two circles list.add(new Circle(2)); list.add(new Circle(3)); //Display the area of the first circle in the list System.out.println("The area of the circle? " + list.get(0).getArea()); } }
程序清单 11-9 DistinctNumbers.java
import java.util.ArrayList; import java.util.Scanner; public class DistinctNumbers { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); Scanner input = new Scanner(System.in); System.out.print("Enter integers (input ends with 0): "); int value; do { //Read a value from the input value = input.nextInt(); if (!list.contains(value) && value != 0) { //Add the value if it is not in the list list.add(value); } } while (value != 0); //Display the distinct numbers for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i) + " "); } } }
程序清单 11-10 DistinctNumbers.java
import java.util.ArrayList; public class MyStack { private ArrayList<Object> list = new ArrayList<>(); public boolean isEmpty() { return list.isEmpty(); } public int getSize() { return list.size(); } public Object peek() { return list.get(getSize() - 1); } public Object pop() { Object o = list.get(getSize() - 1); list.remove(getSize() - 1); return o; } public void push(Object o) { list.add(o); } @Override public String toString() { return "stack: " + list.toString(); } }