接著前面的學習:
java學習筆記6--類的繼承、Object類
java學習筆記5--類的方法
java學習筆記4--類與對象的基本概念(2)
java學習筆記3--類與對象的基本概念(1)
java學習筆記2--數據類型、數組
java學習筆記1--開發環境平臺總結
本文地址:http://m.survivalescaperooms.com/archimedes/p/java-study-note7.html,轉載請注明源地址。
1、終結類與終結方法被final修飾符修飾的類和方法,終結類不能被繼承,終結方法不能被當前類的子類重寫
終結類的特點:不能有派生類
終結類存在的理由:
安全: 黑客用來攪亂系統的一個手法是建立一個類的派生類,然后用他們的類代替原來的類
設計: 你認為你的類是最好的或從概念上你的類不應該有任何派生類
終結方法的特點:不能被派生類覆蓋
終結方法存在的理由:
對于一些比較重要且不希望子類進行更改的方法,可以聲明為終結方法。可防止子類對父類關鍵方法的錯誤重寫,增加了代碼的安全性和正確性
提高運行效率。通常,當java運行環境(如java解釋器)運行方法時,它將首先在當前類中查找該方法,接下來在其超類中查找,并一直沿類層次向上查找,直到找到該方法為止
final 方法舉例:
class Parent{ public Parent() { } //構造方法 final int getPI() { return Math.PI; } //終結方法}說明:getPI()是用final修飾符聲明的終結方法,不能在子類中對該方法進行重載
2、抽象類抽象類:代表一個抽象概念的類
沒有具體實例對象的類,不能使用new方法進行實例化
類前需加修飾符abstract
可包含常規類能夠包含的任何東西,例如構造方法,非抽象方法
也可包含抽象方法,這種方法只有方法的聲明,而沒有方法的實現
抽象類是類層次中較高層次的概括,抽象類的作用是讓其他類來繼承它的抽象化的特征
抽象類中可以包括被它的所有子類共享的公共行為
抽象類可以包括被它的所有子類共享的公共屬性
在程序中不能用抽象類作為模板來創建對象;
在用戶生成實例時強迫用戶生成更具體的實例,保證代碼的安全性
舉個例子:
將所有圖形的公共屬性及方法抽象到抽象類Shape。再將2D及3D對象的特性分別抽取出來,形成兩個抽象類TwoDimensionalShape及ThreeDimensionalShape
–2D圖形包括Circles、Triangles、Rectangles和Squares
–3D圖形包括Cube、Sphere、或Tetrahedron
–在UML中,抽象類的類名為斜體,以與具體類相區別:

抽象類聲明的語法形式為
abstract class Number { . . .}3、抽象方法聲明的語法形式為:
public abstract <returnType> <methodName>(...);
僅有方法頭,而沒有方法體和操作實現,具體實現由當前類的不同子類在它們各自的類聲明中完成,抽象類可以包含抽象方法
需注意的問題:
一個抽象類的子類如果不是抽象類,則它必須為父類中的所有抽象方法書寫方法體,即重寫父類中的所有抽象方法
只有抽象類才能具有抽象方法,即如果一個類中含有抽象方法,則必須將這個類聲明為抽象類
抽象方法的優點:
隱藏具體的細節信息,所有的子類使用的都是相同的方法頭,其中包含了調用該方法時需要了解的全部信息
強迫子類完成指定的行為,規定其子類需要用到的“標準”行為
舉一個繪圖的例子:

各種圖形都需要實現繪圖方法,可在它們的抽象父類中聲明一個draw抽象方法
abstract class GraphicObject { int x, y; void moveTo(int newX, int newY) { . . . } abstract void draw();}然后在每一個子類中重寫draw方法,例如:
class Circle extends GraphicObject { void draw() { . . . }}class Rectangle extends GraphicObject { void draw() { . . . }}舉一個例子:
首先定義一個抽象類:
abstract class Person { PRivate String name; //具體數據 public Person(String n) { //構造函數 name = n; } public String getName() { //具體方法 return name; } public abstract String getDescription(); //抽象方法}下面通過抽象類Person擴展一個具體子類Student:
class Student extends Person { private String major; public Student(String n, String m) { super(n); major = m; } public String getDescription() { //實現抽象類中的getDescription方法 return "a student majoring in " + major; }}通過抽象類Person擴展一個具體子類Employee:
class Employee extends Person { private double salary; private Date hireDay; public Employee(String n, double s, int year, int month, int day) { super(n); salary = s; GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day); hireDay = calendar.getTime(); } public double getSalary() { return salary; } public Date getDate() { return hireDay; } public String getDescription() { //實現抽象類中的getDescription方法 return String.format("an employee with a salary of $%.2f", salary); } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; }}測試程序如下:
public class javatest { public static void main(String[] args) { Person[] people = new Person[2]; people[0] = new Employee("Hary Hacker", 50000, 1989, 10, 1); people[1] = new Student("Maria Morris", "Computer science"); for(Person p : people) System.out.println(p.getName() + ", " + p.getDescription()); }}運行結果如下:
Hary Hacker, an employee with a salary of $50000.00Maria Morris, a student majoring in Computer science
再舉一個例子:
先定義一個幾何抽象類GeometricObject:
import java.util.*;public abstract class GeometricObject { private String color = "write"; private boolean filled; private Date dateCreated; //構造函數(protected類型) protected GeometricObject() { dateCreated = new Date(); } protected GeometricObject(String color, boolean filled) { dateCreated = new Date(); this.filled = filled; this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public boolean isFilled() { return filled; } public void setFilled(boolean filled) { this.filled = filled; } public Date getDateCreated() { return dateCreated; } public String toString() { return "created on" + dateCreated + "/ncolor: " + color + " and filled: " + filled; } public abstract double getArea(); //抽象方法 public abstract double getPerimeter(); //抽象方法}定義一個具體類Circle繼承抽象類:
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); //繼承基類 } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } public double getArea() { //實現抽象類中的抽象方法getArea() return radius * radius * Math.PI; } public double getPerimeter() { //實現抽象類中的抽象方法getPerimeter() return radius * 2 * Math.PI; }}定義一個具體類Rectangle繼承抽象類:
public class Rectangle extends GeometricObject { private double width; private double heigth; public Rectangle() { } public Rectangle(double width, double heigth) { this.width = width; this.heigth = heigth; } public Rectangle(double width, double heigth, String color, boolean filled) { this.width = width; this.heigth = heigth; setColor(color); setFilled(filled); } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getHeigth() { return heigth; } public void setHeigth(double heigth) { this.heigth = heigth; } public double getArea() { return width * heigth; } public double getPerimeter() { return 2 * (width + heigth); }}3、類的組合面向對象編程的一個重要思想就是用軟件對象來模仿現實世界的對象,現實世界中,大多數對象由更小的對象組成
與現實世界的對象一樣,軟件中的對象也常常是由更小的對象組成,Java的類中可以有其他類的對象作為成員,這便是類的組合
組合的語法很簡單,只要把已存在類的對象放到新類中即可,可以使用“has a”語句來描述這種關系
例如,考慮Kitchen類提供烹飪和冷藏食品的功能,很自然的說“my kitchen 'has a' cooker/refrigerator”。所以,可簡單的把對象myCooker和myRefrigerator放在類Kitchen中。格式如下:
class Cooker{ // 類的語句 }class Refrigerator{ // 類的語句}class Kitchen{ Cooker myCooker; Refrigerator myRefrigerator;}一條線段包含兩個端點:
public class Point //點類 { private int x, y; //coordinate public Point(int x, int y) { this.x = x; this.y = y;} public int GetX() { return x; } public int GetY() { return y; }}class Line //線段類{ private Point p1,p2; // 兩端點 Line(Point a, Point b) { p1 = new Point(a.GetX(),a.GetY()); p2 = new Point(b.GetX(),b.GetY()); } public double Length() { return Math.sqrt(Math.pow(p2.GetX()-p1.GetX(),2) + Math.pow(p2.GetY()-p1.GetY(),2)); }}組合與繼承的比較:
“包含”關系用組合來表達
如果想利用新類內部一個現有類的特性,而不想使用它的接口,通常應選擇組合,我們需在新類里嵌入現有類的private對象
如果想讓類用戶直接訪問新類的組合成分,需要將成員對象的屬性變為public
“屬于”關系用繼承來表達
取得一個現成的類,并制作它的一個特殊版本。通常,這意味著我們準備使用一個常規用途的類,并根據特定需求對其進行定制
舉個例子:
car(汽車)對象是一個很好的例子,由于汽車的裝配是故障分析時需要考慮的一項因素,所以有助于客戶程序員理解如何使用類,而且類創建者的編程復雜程度也會大幅度降低
class Engine { //發動機類 public void start() {} public void rev() {} public void stop() {}}class Wheel { //車輪類 public void inflate(int psi) {}}class Window { //車窗類 public void rollup() {} public void rolldown() {}}class Door { //車門類 public Window window = new Window(); public void open() {} public void close() {}}public class Car { public Engine engine = new Engine(); public Wheel[] wheel = new Wheel[4]; public Door left = new Door(),right = new Door(); public Car() { for(int i = 0; i < 4; i++) wheel[i] = new Wheel(); } public static void main(String[] args) { Car car = new Car(); car.left.window.rollup(); Car.wheel[0].inflate(72); }}許多時候都要求將組合與繼承兩種技術結合起來使用,創建一個更復雜的類
舉個例子(組合與繼承舉例):
class Plate { //聲明盤子 public Plate(int i) { System.out.println("Plate constructor"); }}class DinnerPlate extends Plate { //聲明餐盤為盤子的子類 public DinnerPlate(int i) { super(i); System.out.println("DinnerPlate constructor"); }}class Utensil { //聲明器具 Utensil(int i) { System.out.println("Utensil constructor"); }}class Spoon extends Utensil { //聲明勺子為器具的子類 public Spoon(int i) { super(i); System.out.println("Spoon constructor"); }}class Fork extends Utensil { //聲明餐叉為器具的子類 public Fork(int i) { super(i); System.out.println("Fork constructor"); }}class Knife extends Utensil { //聲明餐刀為器具的子類 public Knife(int i) { super(i); System.out.println("Knife constructor"); }}class Custom { // 聲明做某事的習慣 public Custom(int i) { System.out.println("Custom constructor");}}public class PlaceSetting extends Custom {//聲明餐桌的布置 Spoon sp; Fork frk; Knife kn; DinnerPlate pl; public PlaceSetting(int i) { super(i + 1); sp = new Spoon(i + 2); frk = new Fork(i + 3); kn = new Knife(i + 4); pl = new DinnerPlate(i + 5); System.out.println("PlaceSetting constructor"); } public static void main(String[] args) { PlaceSetting x = new PlaceSetting(9); }} 運行結果:
Custom constructor
Utensil constructor
Spoon constructor
Utensil constructor
Fork constructor
Utensil constructor
Knife constructor
Plate constructor
DinnerPlate constructor
PlaceSetting constructor
參考資料:《java程序設計》--清華大學
新聞熱點
疑難解答