物件類別觀念 建構子與類別方法 重載、繼承與複寫 抽象類別與多型 介面與套件 例外處理與執行緒 泛型

Slides:



Advertisements
Similar presentations
主要内容 Java 的常用包 Java 的常用包 “ == ” 和 “ equals ” 的用法 “ == ” 和 “ equals ” 的用法 基本数据类型与引用类型 基本数据类型与引用类型 String 和 StringBuffer String 和 StringBuffer 对象的克隆( clone.
Advertisements

系統分析與設計 楊子青 H-1 H 、物件導向技術 n 物件導向的基本概念 – 物件、類別 – 封裝、繼承 – 同名異式 ( 多型 ) 、超荷 ( 過載 ) n 物件導向分析與設計及塑模工具 n UML 塑模工具.
第6章 对象和类.
单元二:面向对象程序设计 任务二:借书卡程序设计.
第四章 类、对象和接口.
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
JAVA 编 程 技 术 主编 贾振华 2010年1月.
6. 6 Overloading methods and constructors 6
四資二甲 第三週作業 物件導向程式設計.
算法设计与分析 Algorithm Design and Analysis
第一章 面向对象程序设计.
程設一.
第二章 JAVA语言基础.
第二部分 Java语言基础篇 第4章 Java语言与面向对象 (之一).
類別的繼承-一般關係: 繼承是宣告的類別繼承現存類別的部份或全部的成員資料和方法 , 新增額外的成員資料和方法或覆寫和隱藏繼承類別的方法
Ch07 介面與多重繼承 物件導向程式設計(II).
JAVA程序设计 (03) JAVA Programming
第5章 进一步讨论对象和类.
1 Department of Computing.
第5章 Java中类、对象、接口 及包的概念 5.1 类的基本概念 5.2 类的继承概念 5.3 抽象类和接口 5.4 包.
程設一.
Ch08 巢狀類別 物件導向程式設計(II).
程式設計實作.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
第5章 面向对象程序设计 本章要点 5.1 面向对象程序设计概述 5.2 Java语言的面向对象程序设计 5.3 方法的使用和对象数组
控制流程 邏輯判斷 迴圈控制.
H、物件導向技術 物件導向的基本概念 物件、類別 封裝、繼承 同名異式(多型) 、超荷(過載) 物件導向分析與設計及塑模工具 UML塑模工具.
物件導向程式設計 (Object-Oriented rogramming)
第二章 C# 基础知识.
Classes Lecturer: 曾學文.
第六章 类的扩展与继承.
程式敘述執行順序的轉移 控制與重複、方法 Lecturer:曾學文.
第3章 語法入門 第一個Java程式 文字模式下與程式互動 資料、運算 流程控制.
Java 程式設計 講師:FrankLin.
本單元介紹何謂變數,及說明變數的宣告方式。
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
程式設計實作.
抽象类 File类 String类 StringBuffer类
CH09 套件 物件導向程式設計(II).
第2章回顾 标识符:不用记,动手 关键字:if, else, switch, for, while, do, break, continue, void, …… 局部变量和成员变量 ①变量作用域 ②内存布局 基本数据类型 ①4类8种 ②互相转换 流程控制语句 ①分支 if……else, switch.
Java程序设计 第9章 继承和多态.
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
類別的繼承 Vehicle Car.
中国矿大计算机学院杨东平 第5章 接口和包 中国矿大计算机学院杨东平
3.1 数据类型 3.2 标识符与关键字 3.3 常量 3.4 变量 3.5 运算符与表达式 3.6 一个编程实例
2019/1/16 Java语言程序设计-类与对象 教师:段鹏飞.
异常及处理.
Java程序设计 第2章 基本数据类型及操作.
第5讲 使用类和对象编程(三) 内部类 实例 程序控制结构 选择语句.
Ch02-基礎語法.
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
第三章 C# 基础知识.
Multithread 多執行緒 以GUI為例了解物件以及Event
JAVA 编 程 技 术 主编 贾振华 2010年1月.
《JAVA程序设计》 语音答疑 辅导老师:高旻.
實作輔導 2 日期: 3/24(星期六) 09:10~16:00 地點:臺北市立大學 臺北市中正區愛國西路一號 (中正紀念堂站7號出口)
第二章Java基本程序设计.
第二章 Java基本语法 讲师:复凡.
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
第二章 Java语法基础.
龍老師我不會Debug QQ.
第二章 Java基本语法 讲师:复凡.
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
PPT注意事项: 当前PPT课件文件必须和提供的源代码文件夹“代码”在同一目录中即不要移动文件夹“代码”的默认位置。
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
第4讲 类和对象、异常处理 ggao.
對於成員(member)存取權的限制 成員的資料被毫無限制的存取,任誰都可以指定任意值給成員,Java語言為了防止這種現象的產生,規定:有一種成員的資料不能任由類別外部的任何人隨意存取。
第二章 Java基础语法 北京传智播客教育
Summary
Presentation transcript:

物件類別觀念 建構子與類別方法 重載、繼承與複寫 抽象類別與多型 介面與套件 例外處理與執行緒 泛型 物件導向基礎 物件類別觀念 建構子與類別方法 重載、繼承與複寫 抽象類別與多型 介面與套件 例外處理與執行緒 泛型

物件類別觀念 類別的組成-建構子、動態實例方法與靜態類別方法 建構子(Constructors)- 讓類別在被呼叫時可以傳入參數 名稱必須與所屬類別之名稱相同; 無回傳資料(內容無return),宣告中亦不得前置void; 主要功能是在所屬類別產生新物件時作初始化動作。 建構子的數目可以不只一個,亦即可利用相同名稱的建構子賦予不同的傳入引數,讓類別所提供的方法可以更有彈性的使用不同的參數進行各種資料運算。 宣告方式如下,其中參數列可以無任何引數。 public 類別名稱 (參數列) { 程式敘述 ; }

實例方法程序(Instance Methods) 實例方法程序屬於動態方法,當方法程序所屬之物件尚未產生之前,該方法程序無法執行,故須先作物件的宣告方可使用。 例如宣告陣列時必須利用new來產生一個新的陣列物件。 敘述方法如下: 存取敘述 傳回值型態 方法名稱 (參數列) { 程式敘述 ; } 存取敘述-public, private, protected等,定義該方法的生命週期。 若有無傳回值時,僅是利用方法程序進行某種運算,則傳回值型態為void。 若是有傳回值時,傳回值型態使用int或char等數值或字串之類的資料型態,此時的方法便稱為函數(Functions),方法的程式區塊內要利用return指令傳回一個符合方法資料型態的值。

類別方法程序(Class Methods) 類別方法程序或稱為靜態方法(Static Method),宣告時須前置static-利用此修飾子,表示靜置於記憶體中,此方法便屬於此類別本身,不必另作物件的宣告即可直接使用。 例如在main主程式中呼叫的類別內之方法或副程式,或是Math類別物件所提供的數學函數,或是利用System類別的out.println方法列印資料,均不需另外宣告便可直接呼叫使用。 存取敘述 static 傳回值型態 方法名稱 (參數列) { 程式敘述 ; }

this- this在程式應用上、帶來許多方便。其意義為所屬類別之代名詞 this可用於建構子間之呼叫: this之statement必須置於第一行、否則為錯誤編輯。 this可用於成員方法中區別與引數同名的成員資料。 假設成員資料中已經存在一個變數名稱name,而成員方法或建構子中所傳進來的引數也叫作name,此時this.name就代表類別中的成員name,以和引數name做區隔。

class Car { // 定義類別內在成員資料 private long engineNum ; private int color ; final private String[] colorname = {"White","Red","Orange","Yellow","Green","Cyan","Purple","Black"} ; private String model ; private double mileage ; private String brand ; // 不需要傳入引數的建構子 public Car() { } // 需要傳入引數的建構子 public Car(int engineNum, int color, String model, int miles, String brand) { // 利用this賦予和引數同名的內在成員資料初始值 this.engineNum = engineNum ; this.color = color ; this.model = model ; this.mileage = miles ; this.brand = brand ;

// 實例方法:設定引擎號碼 public void setEngineNum(long num) { engineNum = num ; } // 實例方法:設定車款 public void setModel(String id) { model = id ; // 實例方法:設定車殼顏色代碼 public void setColor(int color) { this.color = color ; // 實例方法:設定里程數 public void setMileage(double miles) { mileage = miles ; // 實例方法:設定製造商 public void setBrand(String name) { brand = name ; // 實例方法:取得引擎號碼 public long getEngineNum() { return engineNum; } // 實例方法:取得顏色代碼及名稱 public int getColor() { return color; public String getColorName() { return colorname[color] ; // 實例方法:取得車型款式 public String getModel() { return model; // 實例方法:取得里程數 public double getMileage() { return mileage; // 實例方法:取得製造商 public String getBrand() { return brand;

// 類別方法:傳回出產國 public static String getNation() { String nation = "Made in Japan" ; return nation ; } // 實例方法:列印二手車資訊 public void printVehicle() { System.out.println("The Manufactor is " + getBrand()) ; System.out.println("The Model is " + model) ; System.out.println("Color Number is " + color) ; System.out.println("Color Name is " + colorname[color]) ; System.out.println("Engine Number is " + getEngineNum()) ; System.out.println("Mileage is " + mileage) ;

import static java.lang.System.* ; public class ClassTest { public static void main(String[] args) { System.out.println(Car.getNation()) ; // 取得靜態類別方法 // 宣告類別物件並傳入資料 Car car = new Car(82250080, 3, "Wish", 75008, "Toyota") ; car.printVehicle() ; // 取得二手車資訊 // 設定新的資訊 car.setBrand("Honda") ; car.setModel("Accord") ; car.setMileage(59225) ; car.setEngineNum(72320415) ; car.setColor(0) ; // 取得靜態類別資訊 – 不需宣告類別物件 System.out.println(Car.getNation()) ; car.printVehicle() ; // 取得新的二手資訊 // 定義新的類別物件 Car suv = new Car() ; suv.setBrand("Nissan") ; suv.setModel("X-Trail") ; out.println(suv.getNation()) ; // 以類別物件取得靜態類別方法資訊 suv.printVehicle() ; }

方法程序的重載(Overload) 在同一類別內有兩個(含)以上之方法程序、具有相同名稱 其宣告之類型或參數個數卻不相同 不可以出現有相同名稱與引數卻有不同類型宣告的方法程序(如此邏輯將使電腦無法判別該使用哪一個方法)。 類別中各類型變數生命週期範圍如下 Class class_name { Member Variable Scope ; … public void method_name( … ) { Local Variable Scope ; } 成員變數範圍 方法參數範圍 區域變數範圍

// 類別部份 class MeanValue { public MeanValue() { } public double mean(double a, double b) { double c = Math.sqrt(a*a + b*b) ; return c ; public double mean(double[] a) { double c = 0.0 ; for(int i=0; i<a.length; i++) { c = c + a[i]*a[i] ; return Math.sqrt(c) ; public int mean(double[] a, double[] b) { c = c + a[i]*b[i] ; return (int)Math.sqrt(c) ; // 測試主程式部份 public class OverloadTest { public static void main(String[] args) { MeanValue mv = new MeanValue() ; double a = 1.5, b = 2.3 ; double[] c = {1.1, 2.2, 3.3, 4.4, 5.5} ; double[] d = {6.6, 7.7, 8.8, 9.9, 11.11} ; System.out.println(mv.mean(a, b)) ; System.out.println(mv.mean(c)) ; System.out.println(mv.mean(c, d)) ; } 類別中計算均值的三個Method 具有相同之名稱mean, 其宣告之資料型態不盡相同, 有int,也有double; 且輸入的引數也都不一樣, 有純量,也有陣列。 三個Method分別做不一樣的運算, 且傳回不一樣的值。

繼承(Inherit) 讓類別得以包含現存類別的部分 或全部成員資料和成原方法 可新增成員或方法,甚至覆載或 隱藏繼承類別的方法或變數 例如右述之車輛類別系統 卡車、一般車輛、機車均具備 車輛基本功能, 而轎車則又繼承一般車輛的性能, 但不具備卡車或機車的特定功能 Vehicle為父類別,Truck, Car, Motor 為Vehicle的子類別,又彼此互為兄弟類別 繼承的語句敘述如下 class 子類別名稱 extends 父類別名稱 { …… // 額外的成員資料和方法 } Vehicle Truck Car Motor Sedan

super - 利用super呼叫父類別的建構子-子類別不可以繼承父類別的建構子,需要使用時,用super指令來呼叫;例如 public Sedan(int engineNum, int color, String model, int miles, String brand) { super(engineNum, color, model, miles, brand) ; } 子類別Sedan所繼承的父類別之建構子中可加入四個引數,因此欲在子類別之建構子中傳入這些隱數值時,以super來呼叫父類別之建構子 同理,子類別內覆寫和隱藏的成員變數也可以使用super來呼叫。例如 System.out.println("The Model is " + super.getModel()) ; 假設父類別中提供一個getModel()方法,則子類別中可利用super去取得該方法來使用。

class Sedan extends Car {// 繼承前述範例中之Car類別 private int door ; private double price ; public Sedan() { } public Sedan(int engineNum, int color, String model, int miles, String brand) { super(engineNum, color, model, miles, brand) ; // 呼叫父類別之建構子 } public void setDoor(int door) {// Number of doors this.door = door ; public void setPrice(double price) {{// Price of the sedan this.price = price ; public void printSedan() {// 印出父類別提供方法之資料及子類別之變數 System.out.println("The Manufactor is " + super.getBrand()) ; System.out.println("The Model is " + super.getModel()) ; System.out.println("Color Number is " + super.getColor()) ; System.out.println("Color Name is " + super.getColorName()) ; System.out.println("Engine Number is " + super.getEngineNum()) ; System.out.println("Mileage is " + super.getMileage()) ; System.out.println("The number of doors: " + door) ; System.out.println("The price is " + price) ;

public class InheritTest { public InheritTest() { } public static void main(String[] args) { // TODO code application logic here // 取得父類別之靜態類別方法 System.out.println(Car.getNation()) ; // 宣告類別物件並傳入資料 Sedan car = new Sedan(82250080, 3, "Wish", 75008, "Toyota") ; car.printVehicle() ; // 利用子類別繼承父類別二手車資訊並印出 // 定義新的子類別物件 Sedan suv = new Sedan() ; suv.setBrand(“Nissan”) ; // 輸入子類別所繼承之父類別變數資料 suv.setModel("X-Trail") ; suv.setMileage(59225) ; suv.setEngineNum(72320415) ; suv.setColor(0) ; System.out.println(suv.getNation()) ; // 取得父類別之靜態類別方法資訊 suv.setDoor(4) ; // 輸入子類別變數資料 suv.setPrice(75000) ; suv.printSedan() ; }

複寫(Override)和隱藏(Hide) 當父類別所定義的方法不適用於子類別時,在子類別宣告同名、同參數及同傳回值但方法流程不同的方法來取代; 隱藏(Hide)- 物件的實例方法(Instance Method)不能取代宣告成static的類別方法(Class Method),因此如欲取代父類別的類別方法時,子類別需要宣告同樣的類別方法來取代,即隱藏(Hide)。 class Car { …… public static String getNation() {…運算A…} public void printVehicle() {…運算AA…} private int color ; public int getColor() { … } …… } class Sedan extends Car public static String getNation() {…運算B…} public void printVehicle() {…運算BB…} public String color ; public String getColor() { … }錯誤! (必須有相同資料型態的傳回值)

以繼承Car父類別的Sedan子類別中複寫Car類別的setColor方法為例,取得color代碼定義新的color字串 public void setColor(int color) { this.color = color ; } public int getColor() { return color; case 3: this.color = "green" ; break ; case 4: this.color = "blue" ; case 5: this.color = "silver" ; case 6: this.color = "golden" ; default: this.color = "white" ; } public String getColorname() { return this.color ; // Sedan類別中的setColor方法 public void setColor(int color) {// Override super.setColor(color) ; switch(super.getColor()) { case 1: this.color = "red" ; break ; case 2: this.color = "black" ;

抽象(Abstract)類別與 多形(Polymorphism) final(常數)- 在程式中宣告為final的變數視為不可被改變的固定值常數,只能取出來使用,但不能變更其值。 抽象類別(abstract)- 宣告為abstract的類別沒有建構子,因此不能用來建立物件,只能用來讓子類別繼承,就像是有身體卻沒有頭部的抽象形體,當類別擁有抽象方法,表示這一定是抽象類別。 抽象類別雖然不能建立物件,但是可以宣告成參考子類別實例的物件變數,如 Shape c = new Circle(10.0, 10.0, 7.0) ; <<abstract>> Shape +x:double +y:double area( ) Circle +r:double

多形(Polymorphism)- 目的在讓應用程式更容易擴充,不需要針對不同的資料型態分別建立類別,而是繼承一個基礎類別來建立同名方法,以處理不同的資料型態,如果有新的資料型態,則只須新增繼承的子類別。 abstract class Shape { // Shape抽象類別宣告 public double x; // x座標 public double y; // y座標 abstract void area(); // 抽象方法: 計算面積 } class Circle extends Shape {// Circle類別宣告 …… // 成員方法: 實作抽象方法area()計算圓面積 public void area() { …… }; class Triangle extends Shape {// Triangle類別宣告 …… // 成員方法: 實作抽象方法area()計算三角形面積 class Rectangle extends Shape {// Rectangle類別宣告 …… // // 成員方法: 實作抽象方法area()計算矩形面積 Shapes Triangle Rectangle Circle Shape.area() ;

public class PolymorphismTest { public PolymorphismTest() { } public static void main(String[] args) { Shape s; // 抽象類別的物件變數 // 宣告類別型態的變數, 並且建立物件 Circle s1 = new Circle(5.0, 10.0, 4.0); Rectangle s2 = new Rectangle(10.0, 10.0, 20.0, 20.0); Triangle s3 = new Triangle(10.0, 10.0, 5.0, 25.0, 5.0); // 呼叫抽象類型物件的抽象方法area() s = s1; // 圓形 System.out.println("圓面積" + s.area()); // 相當於執行 Circle.area() ; s = s2; // 長方形 System.out.println("長方形面積" + s.area());// 相當於執行 Rectangle.area() s= s3; // 三角形 System.out.println("三角形面積" + s.area());// 相當於執行 Triangle.area()

// Shape抽象類別宣告 abstract class Shape { public double x; // 成員資料:X座標 public double y; // 成員資料:y座標 // 抽象方法: 計算面積 abstract double area(); } // Circle類別宣告 class Circle extends Shape { private double r; //成員資料:半徑 //建構子 public Circle(double x, double y, double r){ this.x = x; this.y = y; this.r = r; // 成員方法: 實作抽象方法area() public double area() { return 3.1416*r*r ;

class Rectangle extends Shape {// Rectangle類別宣告 private double x1; //成員資料:X座標 private double y1; //成員資料:Y座標 public Rectangle(double x, double y, double x1,double y1) { // 建構子 this.x = x; this.y = y; this.x1 = x1; this.y1 = y1; } public double area() { // 成員方法: 實作抽象方法area() return (y1-y)*(x1-x) ;

class Triangle extends Shape {// Triangle類別宣告 private double x1; // X座標 private double y1; // Y座標 private double l; // 三角形底長 public Triangle(double x, double y, double x1, double y1, double l) { // 建構子 this.x = x; this.y = y; this.x1 = x1; this.y1 = y1; this.l = l; } public double area() { // 成員方法: 實作抽象方法area() return (y1-y)*l/2.0 ;

介面(Interface) 宣告介面-介面是在類別繼承架構中定義類別行為,內含常數和方法宣告,但無實作的程式碼 介面內的數值只能定義常數,不能定義沒有值的變數。 抽象類別的方法可能只有宣告,但是仍然可以擁有一般方法,介面的方法都只有宣告,而且一定沒有實作的程式碼。 與類別類似,同一支程式裡面可以有好幾個介面,但這些介面不能宣告成為public,宣告成public的介面也必須以程式名稱命名。 介面不屬於類別的繼承架構,一個介面可以繼承多個介面,而毫無關係的類別也一樣可以實作同一個介面。 類別只能繼承一個抽象類別,但是可以同時實作多個介面,而實作介面中所宣告的每一個方法都必須予以處理。

<<abstract>> <<interface>> 實作介面 class 類別名稱 implements 介面名稱1, 介面名稱2, … { … // 實作介面的方法 } 繼承介面 interface 介面名稱 extends 繼承的介面1, 繼承的介面2 … // 額外的常數和方法 右圖例中, Circle類別繼承Shape抽象類別 並實作ShapeInterface介面 ShapeInterface介面 繼承AreaInterface介面 <<abstract>> Shape +x:double +y:double <<interface>> AreaInterface PI:doube = 3.14159 area() Circle -r:double +area() +perimeter() ShapeInterface perimeter()

public class AbstractInterfaceTest { public AbstractInterfaceTest() { } public static void main(String[] args) { // 宣告Circle類別型態的變數, 並且建立物件 Circle c = new Circle(10.0, 7.0, 5.5); // 顯示介面的常數值 System.out.println("利用類別方法顯示相關參數") ; c.show() ; System.out.println("利用介面取得PI常數: " + ShapeInterface.PI); System.out.println("利用物件變數取得圓周率: " + c.PI) ; System.out.println("圓半徑: " + c.getR()) ; System.out.println("圓心: (" + c.x + " , " + c.y + ")") ; // 呼叫物件的介面方法area() System.out.println("圓面積: " + c.area()) ; // 呼叫物件的介面方法perimeter() System.out.println("圓周長: " + c.perimeter()) ;

// Shape抽象類別宣告 abstract class Shape { public double x; // X座標 public double y; // Y座標 } interface AreaInterface { // AreaInterface介面宣告 double area(); // 介面方法: 計算面積 interface CircumInterface { // CircumInterface介面宣告 double perimeter(); // 介面方法: 計算周長 // ShapeInterface介面宣告, 繼承AreaInterface與CircumInterface interface ShapeInterface extends AreaInterface, CircumInterface { final double PI = 3.1415926; // 常數的宣告 void show(); // 介面方法: 印出相關參數

// Circle類別宣告 class Circle extends Shape implements ShapeInterface { private double r; // 成員資料:半徑 // 建構子 public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; } // 實作ShapeInterface所繼承之 // AreaInterface介面的方法area() public double area() { return this.PI * this.r * this.r ; // CircumInterface介面的方法perimeter() public double perimeter() { return 2.0 * this.PI * this.r ; // 實作ShapeInterface中的show方法 public void show() { System.out.println("PI=" + this.PI) ; System.out.println("r=" + this.r) ; System.out.println("x=" + this.x) ; System.out.println("y=" + this.y) ; } // 利用getR()方法傳回私有變數r的值 public double getR() { return r ;

例外處理 對例外錯誤(exception)提供檢測與預防 try { } catch (Exception e) { } finally { } Ex: 以下程式執行時需輸入參數, 如 java 程式類別名稱 參數值 public static void main(String[] args) { //測試{}內的程式, 如果會當掉的話, 執行catch{}的指令 try { System.out.println(args[0] + “,您好”);//沒輸入參數值會當掉 } catch (Exception e) { // e.printStackTrace();//此指令輸出預設錯誤訊息 System.out.println("您未在執行程式時輸入參數(姓名)"); } finally {//無論try有沒有錯, 都會執行此區塊 System.out.println("此程式的執行結果會是: (輸入姓名,您好)"); }

執行緒 Threads – Lightweight process (輕量行程) 建立執行緒方式 不能單獨存在或獨立執行,必須隸屬一個程式 程式啟動執行緒後,可作為幕後處理(daemon) 將程式分割成多個同步執行緒一起執行,稱之為平行程式設計(parallel programming) 單一應用程式擁有多個執行流程,稱之為多執行緒(multithreads),即多工處理 建立執行緒方式 實作Runnable介面 繼承Thread類別

Runnable介面 以下程式利用兩個執行緒累計執行停滯時間 package ThreadsDemo; public class RunnableTest { //主程式: 呼叫SumClass啟動執行緒 public static void main(String[] args) { System.out.print("執行緒: "); //輸出目前執行緒物件 System.out.println(Thread.currentThread()); //建立執行緒物件 //定義執行緒1 SumRunner st1 = new SumRunner(15, 1); Thread t1 = new Thread(st1, "執行緒A"); SumRunner st2 = new SumRunner(20, 2); //定義執行緒2 Thread t2 = new Thread(st2, "執行緒B"); //啟動執行緒 t1.start(); t2.start(); } class SumClass { private long length = 100;//進行加總延遲時間的迴圈數(預設為100) //建構子: 宣告時輸入要執行加總的迴圈數 public SumClass(long length) { this.length = length; } public long sum(int threadID) { long temp = 0;//停滯時間總和 for(int i=1; i<=length; i++) { int sleepduration = (int)(Math.random()*10);//隨機產生停滯時間 try {//Stop running for a short moment Thread.sleep(sleepduration);//時間暫停 } catch (Exception e) {} temp += sleepduration; System.out.println(threadID + ":" + i);//印出迴圈數(因啟動執行緒平行運算, 執行緒代號會交互被輸出) return temp;

// 繼承計算方法類別SumClass並實作Runnable介面的run()方法 class SumRunner extends SumClass implements Runnable { private int threadID; //建構子: 繼承SumClass中的成員變數(length) public SumRunner(long length, int threadID) { super(length); this.threadID = threadID; } //實作執行緒方法 public void run() { System.out.println(Thread.currentThread() + "延遲時間總和 = " + sum(this.threadID) + "毫秒"); /******************執行結果****************/ 執行緒: Thread[main,5,main] 2:1 1:1 1:2 2:2 : 1:14 2:17 1:15 Thread[執行緒A,5,main]延遲時間總和 = 77毫秒 2:18 2:19 2:20 Thread[執行緒B,5,main]延遲時間總和 = 84毫秒

Thread類別 以下程式功能與前例相同 package ThreadsDemo; public class ThreadTest { public static void main(String[] args) { System.out.print("執行緒: "); //輸出目前執行緒物件 System.out.println(Thread.currentThread()); //建立執行緒物件 //定義執行緒1 SumThread st1 = new SumThread(15, 1, "執行緒A"); //定義執行緒2 SumThread st2 = new SumThread(20, 2, "執行緒B"); //啟動執行緒 st1.start(); st2.start(); } class SumThread extends Thread {//繼承執行緒類別Thread //進行加總延遲時間的迴圈數(預設為100) private long length = 100; private int threadID = 0; //執行緒編號, 預設為0 //建構子: 繼承SumClass中的成員變數(length) public SumThread(long length, int threadID, String name) { super(name); this.threadID = threadID; this.length = length; } @Override public void run() { long temp = 0;//停滯時間總和 for (int i = 1; i <= length; i++) { //隨機產生停滯時間 int sleepduration = (int) (Math.random() * 10); try {//Stop running for a short moment Thread.sleep(sleepduration);//時間暫停 } catch (Exception e) { } temp += sleepduration; //印出迴圈數(因啟動執行緒平行運算, 會交互輸出執行緒代號) System.out.println(threadID + ":" + i); 後續左側之程式碼 System.out.println(Thread.currentThread() + "延遲時間總和 = " + temp + "毫秒"); }

Daemon Process 幕後執行:自動啟動命令提示模式下執行的程式 建立幕後程式,執行 指令如: java DaemonFiling 0 test.txt 繼承Thread類別並在run()方法中利用Runtime產生執行緒 使用Process類別(exec()方法)代入幕後執行指令(cmd) RunTime.getRunTime().exec(cmd); import java.io.*; import java.util.Date; public class DaemonFiling {//幕後執行程式: 檔案存取 public static void main(String[] args) { try { String opt = args[0];//新建或刪除選項(0 or 1) String filename = args[1];//新建或刪除檔名 File f = new File(filename); if (opt.equals(“0”)) {//新建檔案 FileWriter fw; if (f.exists()) {//檔案已存在則附加資料 fw = new FileWriter(f, true); } else {//檔案不存在則新建檔案 fw = new FileWriter(f); } Date date = new Date();//產生修改時間 fw.write(date.toString() + “\n”);//寫入資料 fw.close();//封存檔案 System.out.println("File is created or updated"); } else {//刪除檔案 if(f.exists()) {//檔案存在則刪除 f.delete(); } System.out.println("File is deleted or absent"); } catch (Exception e) {//例外訊息 System.out.println("0: Input filename to create or " + "1: output filename to delete is required");

package ThreadsDemo; import java.io.*; import java.util.*; public class DaemonTest extends Thread { private String cmd; public DaemonTest(String cmd) { this.cmd = cmd;//取得幕後執行指令 System.out.println("Command: " + cmd); } @Override public void run() { try {//代入幕後執行指令 Process proc = Runtime.getRuntime().exec(cmd); } catch (IOException ex) { System.out.println("Runtime process exception"); public static void main(String[] args) { DaemonTest run = new DaemonTest("java DaemonFiling 0 test.txt"); try { run.start();//啟動執行緒 run.setDaemon(true);//建立幕後執行 } catch (Exception e) { System.out.println("Cannot find process"); } finally { Scanner sc = new Scanner(System.in); if (run.isAlive()) {//判斷執行緒是否存在 System.out.println("Running is alive"); } if (run.isDaemon()) {//判斷有幕後執行 System.out.println("Running is in daemon"); if (run.isInterrupted()) {//判斷執行緒是否中斷 System.out.println("Running is interrupted"); System.out.println("Stop the thread process(y/n)?"); if(sc.next().toLowerCase().charAt(0) == 'y') { run.stop();//強迫停止執行緒 System.out.println("Stop the thread process"); /*****執行結果(不會看到幕後執行過程)*****/ J:\>java ThreadsDemo.DaemonTest Command: java DaemonFiling 0 test.txt Running is terminated Stop the thread process(y/n)? y Stop the thread process J:\>type test.txt Fri Mar 13 13:36:54 CST 2015 Fri Mar 13 13:40:44 CST 2015 Fri Mar 13 13:40:55 CST 2015

套件(Package) 套件- 類別與介面的管理- 建立套件- 將相關的類別和介面集合起來,可編譯成套件,如一般程式所使用的函式庫,利用import指令可把套件匯入程式中,便可使用套件中所有提供的物件。 Java標準的API即是一個名為java的大套件,並擁有數個子套件如lang(所有語言基礎)、awt(執行GUI元件)、io(支援輸出與輸入)等。 類別與介面的管理- 將原本獨立的Java程式宣告成public的類別或介面,並將主程式分離出來 利用javac編譯後,便可形成獨立的物件檔,此時只要單獨編譯主程式檔,仍可以達成相同的功能 建立套件- 利用package指令敘述,在每個獨立出來的Java類別程式前面加上套件名稱,即可將這些類別包含到該套件裡面。

匯入套件- 修飾子間的關係- 利用import指令敘述,將所需用到套件中的類別匯入執行的程式中。 一般在netbeans等開發工具均提供套件之建立功能,開發者可輕鬆地將各類別包入套件中,並配合開發工具之提示指令匯入相關套件 修飾子間的關係- protected - 宣告的成員方法或變數可以在同一類別、其子類別或同一套件存取,其存取權限介於public與private之間。 public-擁有全域變數,任何類別都可以存取,包含子類別。 private-只可以在同一類別中存取,不可以在子類別中存取。 不使用修飾子:預設範圍是同一個類別和套件中存取,但不包含不同套件的子類別,其存取範圍比protected小,因為protected可包含不同套件的子類別。

泛型(Generic Types) 泛型的概念 泛型類別使用時機:定義類別時,發現到好幾個類別的邏輯其實都相同,就只是當中所涉及的型態不一樣時,會增加不必要的檔案管理困擾。 可任意使用型態代號,如<E>,用來宣告一個型態持有者(Holder) E,之後可用 E 作為型態代表來宣告變數。 語法範例 public class GenericFoo<E> { private E foo; public void setFoo(E foo) { this.foo = foo; } public E getFoo() { return foo; //呼叫範例如下 GenericFoo<Boolean> foo1 = new GenericFoo<Boolean>(); GenericFoo<Integer> foo2 = new GenericFoo<Integer>(); foo1.setFoo(new Boolean(true)); Boolean b = foo1.getFoo(); foo2.setFoo(new Integer(10)); Integer i = foo2.getFoo();

泛型的應用 置入不同資料型態於同一類別中進行計算 建立以下泛型類別 class GenericFoo<E> { private E foo; public void setFoo(E foo) { this.foo = foo; } public E getFoo() { return foo; public void setIntegerFoo(E foo) {//以泛型計算整數資料 this.foo = (E) (Object) (Integer.parseInt(foo.toString()) * 10); public void setDoubleFoo(E foo) {//以泛型計算實數資料 this.foo = (E) (Object) (Double.parseDouble(foo.toString()) * Math.PI); public int getIntegerFoo(E foo) {//輸入泛型資料計算後傳回整數值 return Integer.parseInt(foo.toString()) * 100; public double getDoubleFoo(E foo) {//輸入泛型資料計算後傳回實數值 return Double.parseDouble(foo.toString()) * Math.PI;

使用一般資料型態呼叫泛型類別 public class GenericBasicTest { public GenericBasicTest() { } public static void main(String[] args) { //建立泛型物件, 只允許輸入整數 GenericFoo<Integer> foo_i = new GenericFoo<Integer>(); //建立泛型物件, 只允許輸入實數 GenericFoo<Double> foo_d = new GenericFoo<Double>(); foo_i.setFoo(100); foo_d.setFoo(100.0); Integer foo_i1 = foo_i.getFoo(); Double foo_d1 = foo_d.getFoo(); System.out.println(foo_i1 + " <-> " + foo_d1); foo_i.setIntegerFoo(100); int foo_i2 = foo_i.getFoo().intValue();//取得泛型物件計算後整數值 System.out.println(foo_i2); foo_d.setDoubleFoo(100.0); double foo_i3 = foo_d.getFoo().doubleValue();//取得泛型物件計算後實數值 System.out.println(foo_i3); int foo_i4 = foo_i.getIntegerFoo(100); System.out.println(foo_i4); double foo_i5 = foo_d.getDoubleFoo(100.0); System.out.println(foo_i5); }

應用於List抽象類別 建立泛型串列類別,建構子及類別方法 public class GenericListTest { //物件建構子 public GenericListTest() { } //物件方法:輸入任意型態的List建立串列 public void setList(List<?> list) {//<?> 符號代表所有資料型態均可接受(可省略) Iterator it = list.iterator(); while (it.hasNext()) { System.out.println("Set: " + it.next()); //物件方法:輸入整數陣列傳回整數型態串列 public List<Integer> getList(int[] x) { List<Integer> list = new ArrayList<Integer>();//宣告只允許存放整數之串列 for (int xi : x) {//利用foreach迴圈將整數置入串列中 list.add(xi * 10); return list; :  建立類別之主程式於後

建立主程式如下 //物件主程式 public static void main(String[] args) { //宣告List抽象類別,只允許輸入字串String資料 //抽象類別必須透過實體類別實體化,在此例如ArrayList, LinkedList, Vector等等 List<String> alist = new ArrayList<String>(); alist.add("Snow"); alist.add(0, "Ball");//將下一個字串放在前一個字串之前,字串依序後推一位 Iterator it = alist.iterator();//宣告走訪串列物件 while (it.hasNext()) {//走訪串列 System.out.println(it.next());//輸出走訪資料 } GenericListTest glt = new GenericListTest();//宣告泛型串列物件 glt.setList(alist); int[] xx = {1, 2, 3, 4, 5}; List blist = glt.getList(xx); it = blist.iterator(); while (it.hasNext()) { System.out.println(it.next());

擴充泛型類別 繼承一泛型類別,保留其型態持有者並新增型態持有者 //建立父類別MainGenericFoo public class MainGenericFoo<T1, T2> { private T1 foo1; private T2 foo2; public void setFoo1(T1 foo1) { this.foo1 = foo1; } public T1 getFoo1() { return foo1; public void setFoo2(T2 foo2) { this.foo2 = foo2; public T2 getFoo2() { return foo2; //建立子類別SubGenericFoo.java擴充以上之父類別 public class SubGenericFoo<T1, T2, T3> extends GenericFoo<T1, T2> { private T3 foo3; public void setFoo3(T3 foo3) { this.foo3 = foo3; } public T3 getFoo3() { return foo3; //測試以上物件類別 public class GenericInheritTest { public static void main(String[] args) { //宣告泛型類別, 指定三種資料型態 SubGenericFoo<String, Integer, Double> sgf = new SubGenericFoo<String, Integer, Double>(); sgf.setFoo1("Hello Kitty"); sgf.setFoo2(12); sgf.setFoo3(34.5); System.out.println(sgf.getFoo1() + “ earns ” + sgf.getFoo3() + “ as ” + sgf.getFoo2() + " years old"); }

實作泛型介面 實作一泛型介面,保留其型態持有者並新增型態持有者 //建立類別GenericClassFoo實作GenericInterfaceFoo介面 class GenericClassFoo<T1, T2> implements GenericInterfaceFoo<T1, T2> { private T1 foo1; private T2 foo2; public void setFoo1(T1 foo1) { this.foo1 = foo1; } public T1 getFoo1() { return foo1; public void setFoo2(T2 foo2) { this.foo2 = foo2; public T2 getFoo2() { return foo2; //建立介面GenericInterfaceFoo interface GenericInterfaceFoo<T1, T2> { public void setFoo1(T1 foo1); public void setFoo2(T2 foo2); public T1 getFoo1(); public T2 getFoo2(); } //測試以上物件類別與介面 public class GenericInterfaceTest { public static void main(String[] args) { GenericClassFoo<String, Boolean> gif = new GenericClassFoo<String, Boolean>(); gif.setFoo1("Steve Jobs"); gif.setFoo2(false); System.out.println(gif.getFoo1() + " is alive? " + gif.getFoo2()); }