Bai giang JAVA

146
1 MỤC LỤC MỤC LỤC .................................................................................................................................. 1 Đề tài 0. Giới thiệu về Java ......................................................................................................... 6 I. Lịch sử hình thành và phát triển ngôn ngữ lập trình Java ...................................................... 6 I.1. Giới thiệu về Java.......................................................................................................... 6 I.2 Tóm tắt lịch sử hình thành của Java ................................................................................ 6 II. Các đặc trưng của Java ....................................................................................................... 7 II.1. Tính đơn giản............................................................................................................... 7 II.2. Tính hướng đối tượng .................................................................................................. 7 II.3. Tính phân tán ............................................................................................................... 7 II.4. Tính mạnh mẽ .............................................................................................................. 7 II.5. Tính an toàn ................................................................................................................. 7 II.6. Tính trung lập .............................................................................................................. 7 II.7. Tính di động ................................................................................................................ 8 II.8. Tính thông dịch ............................................................................................................ 9 II.9. Tính thực thi cao .......................................................................................................... 9 II.10. Tính đa luồng ............................................................................................................. 9 II.11. Tính động .................................................................................................................. 9 III. Các loại ứng dụng của Java ............................................................................................... 9 IV. Công cụ và môi trường lập trình Java ................................................................................ 9 V. Cài đặt Java ........................................................................................................................ 9 Đề tài 1. Ngôn ngữ mô hình hóa UML ...................................................................................... 12 I. Xây dựng hệ thống phần mềm theo hướng đối tượng ......................................................... 12 I.1 Các khái niệm căn bản của công nghệ hướng đối tượng ................................................ 12 I.2 Quy trình chung phát triển hệ thống phần mềm ............................................................ 13 I.3 Những thách thức của ngành công nghiệp phần mềm hiện nay ..................................... 13 II. Lịch sử phát triển ngôn ngữ mô hình hóa UML................................................................. 13 II.1. Tóm tắt lịch sử UML ................................................................................................. 13 II.2. Khái niệm về UML .................................................................................................... 14 II.3 Đặc trưng của UML .................................................................................................... 14 III. Ngôn ngữ UML ............................................................................................................... 15 III.1. Các thành phần của UML ......................................................................................... 15 III.2. Các hướng nhìn ( view) ............................................................................................. 15 III.3 Ứng dụng UML trong quy trình làm phần mềm ......................................................... 22 IV. Quy trình Rational Unified Process (RUP) phát triển phần mềm dựa trên UML .............. 23 IV.1. Giới thiệu về RUP .................................................................................................... 23 IV.2. Các nguyên tắc chính của RUP: ................................................................................ 23 IV.3. Vòng đời của phần mềm theo quy trình RUP ............................................................ 24 IV.4. Các công cụ của RUP ............................................................................................... 25 Bài tập .................................................................................................................................. 26 Đề tài 2. Nhập môn Java ........................................................................................................... 27 I. Viết và thực hiện một chương trình Java ............................................................................ 27 I.1 Tìm hiểu mã nguồn một chương trình đơn giản ............................................................ 27 I.2. Thực hiện chương trình Java. ...................................................................................... 27 I.3. Một số chú ý khi lập trình Java .................................................................................... 28

description

Bai giảng JAVA

Transcript of Bai giang JAVA

Page 1: Bai giang JAVA

1

MỤC LỤC

MỤC LỤC .................................................................................................................................. 1

Đề tài 0. Giới thiệu về Java ......................................................................................................... 6

I. Lịch sử hình thành và phát triển ngôn ngữ lập trình Java ...................................................... 6

I.1. Giới thiệu về Java.......................................................................................................... 6

I.2 Tóm tắt lịch sử hình thành của Java ................................................................................ 6

II. Các đặc trưng của Java ....................................................................................................... 7

II.1. Tính đơn giản............................................................................................................... 7

II.2. Tính hướng đối tượng .................................................................................................. 7

II.3. Tính phân tán ............................................................................................................... 7

II.4. Tính mạnh mẽ .............................................................................................................. 7

II.5. Tính an toàn ................................................................................................................. 7

II.6. Tính trung lập .............................................................................................................. 7

II.7. Tính di động ................................................................................................................ 8

II.8. Tính thông dịch ............................................................................................................ 9

II.9. Tính thực thi cao .......................................................................................................... 9

II.10. Tính đa luồng ............................................................................................................. 9

II.11. Tính động .................................................................................................................. 9

III. Các loại ứng dụng của Java ............................................................................................... 9

IV. Công cụ và môi trường lập trình Java ................................................................................ 9

V. Cài đặt Java ........................................................................................................................ 9

Đề tài 1. Ngôn ngữ mô hình hóa UML ...................................................................................... 12

I. Xây dựng hệ thống phần mềm theo hướng đối tượng ......................................................... 12

I.1 Các khái niệm căn bản của công nghệ hướng đối tượng................................................ 12

I.2 Quy trình chung phát triển hệ thống phần mềm ............................................................ 13

I.3 Những thách thức của ngành công nghiệp phần mềm hiện nay ..................................... 13

II. Lịch sử phát triển ngôn ngữ mô hình hóa UML................................................................. 13

II.1. Tóm tắt lịch sử UML ................................................................................................. 13

II.2. Khái niệm về UML .................................................................................................... 14

II.3 Đặc trưng của UML .................................................................................................... 14

III. Ngôn ngữ UML ............................................................................................................... 15

III.1. Các thành phần của UML ......................................................................................... 15

III.2. Các hướng nhìn (view) ............................................................................................. 15

III.3 Ứng dụng UML trong quy trình làm phần mềm ......................................................... 22

IV. Quy trình Rational Unified Process (RUP) phát triển phần mềm dựa trên UML .............. 23

IV.1. Giới thiệu về RUP .................................................................................................... 23

IV.2. Các nguyên tắc chính của RUP: ................................................................................ 23

IV.3. Vòng đời của phần mềm theo quy trình RUP ............................................................ 24

IV.4. Các công cụ của RUP ............................................................................................... 25

Bài tập .................................................................................................................................. 26

Đề tài 2. Nhập môn Java ........................................................................................................... 27

I. Viết và thực hiện một chương trình Java ............................................................................ 27

I.1 Tìm hiểu mã nguồn một chương trình đơn giản ............................................................ 27

I.2. Thực hiện chương trình Java. ...................................................................................... 27

I.3. Một số chú ý khi lập trình Java .................................................................................... 28

Page 2: Bai giang JAVA

2

I.4. Cấu trúc một chương trình Java ................................................................................... 28

II. Các kiểu dữ liệu trong Java ............................................................................................... 29

II.1 Các kiểu dữ liệu số nguyên ......................................................................................... 29

II.2 Các kiểu số thực.......................................................................................................... 30

II.3 Kiểu ký tự (character) ................................................................................................. 30

II.4 Kiểu logic (boolean) ................................................................................................... 30

II.5 Kiểu chuỗi .................................................................................................................. 30

II.6 Chuyển đổi giữa các kiểu số ........................................................................................ 30

III. Khai báo biến và hằng trong Java .................................................................................... 31

III.1 Quy tắc đặt tên biến ................................................................................................... 31

III.2 Khai báo biến ............................................................................................................ 31

III.3 Biến kiểu mảng .......................................................................................................... 32

III.4 Hằng số (literal) ......................................................................................................... 33

III.5 Phạm vi hoạt động của hằng và biến: ......................................................................... 34

IV. Các toán tử và biểu thức .................................................................................................. 34

IV.1 Các toán tử và thứ tự ưu tiên ...................................................................................... 34

IV.2 Biểu thức ................................................................................................................... 35

V. Các lệnh điều khiển rẽ nhánh ............................................................................................ 35

V.1 Lệnh if ........................................................................................................................ 35

V.2. Lệnh switch …case .................................................................................................... 36

VI. Các lệnh lặp .................................................................................................................... 37

VI.1. Vòng lặp for ............................................................................................................. 37

VI.2. Vòng lặp while ......................................................................................................... 38

VI.3. Vòng lặp do... while ................................................................................................. 38

VI.4. Phép nhảy ................................................................................................................. 39

VII. Vào dữ liệu từ bàn phím và xuất dữ liệu ra màn hình ..................................................... 40

VII.1. Lấy giá trị nhập vào từ bàn phím ............................................................................. 40

VII.2 Kết xuất dữ liệu ra màn hình .................................................................................... 41

Bài tập .................................................................................................................................. 42

Đề tài 3. Lập trình hướng đối tượng trong Java ......................................................................... 44

I. Khái niệm lập trình hướng đối tượng (Object-Oriented Programming - OOP) .................... 44

I.1. Khái niệm OOP ........................................................................................................... 44

I.2 Cơ sở lý luận của OOP ................................................................................................. 44

I.3 Trừu tượng hóa ............................................................................................................ 44

II. Tính đóng gói trong Java .................................................................................................. 46

II.1 Khái niệm tính đóng gói .............................................................................................. 46

II.2 Mối quan hệ giữa các class.......................................................................................... 46

II.3 Một số gợi ý khi thiết kế class ..................................................................................... 46

IV. Sử dụng các Class xây dựng sẵn trong thư viện ............................................................... 47

V. Xây dựng Class trong Java ............................................................................................... 48

V.1 Cấu trúc của class ....................................................................................................... 48

V.2 Các thuộc tính thành phần:.......................................................................................... 49

V.3 Các phương thức thành phần....................................................................................... 50

V.4 Gọi và truyền tham số cho phương thức ...................................................................... 51

V.6 Các hàm và phương thức đặc biệt ............................................................................... 51

V.7 Khai báo chồng các phương thức ................................................................................ 52

V.8 Lớp lồng nhau – lớp nội .............................................................................................. 53

Page 3: Bai giang JAVA

3

VI. Tính kế thừa trong Java ................................................................................................... 54

VI.1 Sự kế thừa các thuộc tính và phương thức.................................................................. 54

VI.2 Sự kế thừa đối với các constructor ............................................................................. 57

VII. Tính đa hình trong Java .................................................................................................. 58

VII.1 Sự ép kiểu và gán tham chiếu đối tượng ................................................................... 58

VII.2 Sự ràng buộc động –Dynamic Binding ..................................................................... 58

VIII. Lớp Object ................................................................................................................... 59

IX. Giao diện ........................................................................................................................ 60

IX.1 Cấu trúc của giao diện ............................................................................................... 60

IX.2 Các tính chất của giao diện ........................................................................................ 62

X. Package ............................................................................................................................ 62

X.1 Sử dụng các package trong thư viện Java .................................................................... 62

X.2 Đặt lớp vào package ................................................................................................... 63

Bài tập .................................................................................................................................. 63

Đề tài 4. Lớp và phương thức trừu tượng .................................................................................. 64

I. Khái niệm lớp trừu tượng ................................................................................................... 64

II. Cài đặt lớp và phương thức trừu tượng trong Java ............................................................. 64

Bài tập .................................................................................................................................. 65

Đề tài 5. Lưu trữ và xử lý đối tượng .......................................................................................... 66

I. Lớp Vector và giao diện Enumeration ................................................................................ 66

I.1 Lớp Vector ................................................................................................................... 66

I.2 Giao diện Enumeration ................................................................................................. 67

II. Mảng trong Java và lớp ArrayList ..................................................................................... 69

II.1 Mảng trong Java ......................................................................................................... 69

II.2. Các thuật toán cơ bản trên mảng ................................................................................ 70

II.3 Class Arrays ............................................................................................................... 71

III Danh sách trong java và giao diện Lists ............................................................................ 73

Bài tập .................................................................................................................................. 74

Đề tài 6. Các luồng vào ra dữ liệu với file ................................................................................. 75

I. Khái niệm luồng vào ra (I/O stream) .................................................................................. 75

II. Lớp InputStream: .............................................................................................................. 76

III. Lớp OutputStream ........................................................................................................... 77

IV. Lớp FileInputStream ....................................................................................................... 77

V. Lớp FileOutputStream ...................................................................................................... 77

VI. Lớp File .......................................................................................................................... 77

VII. Nhập xuất lọc ................................................................................................................. 78

VII.1 Lớp FilterInputStream: ............................................................................................. 79

VII.2 Lớp FilterOutputStream ........................................................................................... 79

VIII. Vào/ra có sử dụng bộ đệm ............................................................................................ 79

VIII.1 Lớp BufferedInputStream: ...................................................................................... 79

VIII.2 Lớp BufferedOutputStream ..................................................................................... 79

IX. Lớp RandomAccessFile .................................................................................................. 81

X. Đối tượng System.in ......................................................................................................... 82

XI. Truy cập file ở chế độ tuần tự .......................................................................................... 82

XII. Truy cập file nhị phân .................................................................................................... 86

Bài tập .................................................................................................................................. 86

Đề tài 7. Xử lý ngoại lệ ............................................................................................................. 88

Page 4: Bai giang JAVA

4

I. Các tình huống sử dụng ngoại lệ ........................................................................................ 88

II. Cơ sở quản lý ngoại lệ trong Java ..................................................................................... 88

III. Cấu trúc cây kế thừa các xử lý ngoại lệ ............................................................................ 89

IV. Sử dụng ngoại lệ được kiểm soát ..................................................................................... 90

V. Xây dựng một ngoại lệ ..................................................................................................... 91

VI. Bài tập ............................................................................................................................ 92

Đề tài 8. Xử lý các sự kiện trong Java ....................................................................................... 93

I. Khái niệm và cơ sở xử lý sự kiện ....................................................................................... 93

II. Truy cập thông tin sự kiện ................................................................................................ 98

III. Xử lý các sự kiện trên window ........................................................................................ 99

IV. Các lớp thích nghi ..........................................................................................................100

V. Xử lý các sự kiện chuột ...............................................................................................102

Bài tập .................................................................................................................................103

Đề tài 9. Applet ........................................................................................................................104

I. Xây dựng một Applet đơn giản .........................................................................................104

II. Cấu trúc cơ bản và vòng đời của một Applet ....................................................................104

III. An ninh và khả năng của Applet .....................................................................................106

IV. Ứng dụng Applet với của sổ Popup ................................................................................106

V. Các thẻ HTML của Applet...............................................................................................107

VI. Các phương thức, lập trình đồ họa và bắt sự kiện của applet ...........................................108

Đề tài 10. Lập trình giao diện đồ họa GUI ................................................................................110

I. Giới thiệu AWT ................................................................................................................110

II. Vật chứa (Container) .......................................................................................................111

II.1 JFrame .......................................................................................................................111

II.2 JPanel ........................................................................................................................111

II.3 JDialog ......................................................................................................................112

II.4 JScrollPane ................................................................................................................113

III. Giới thiệu về các thành phần GUI cơ bản .......................................................................113

III.1 Nút nhấn ...................................................................................................................113

III.2 Nhãn (Label) ............................................................................................................114

III.3 Nút đánh dấu (checkbox) ..........................................................................................115

III.4 Nút chọn (radio button).............................................................................................117

III.5 Hộp thoại Combo .....................................................................................................118

III.6 Danh sách (Lists) ......................................................................................................119

III.7 Ô văn bản (text field) và vùng văn bản (text areas) ...................................................121

III.8 Thanh trượt (Scrollbar) .............................................................................................123

IV. Thành phần Menu ..........................................................................................................124

V. Bộ quản lý cách trình bày (Layout Manager) ...................................................................127

V.1 Cách trình bày FlowLayout:.......................................................................................128

V.2 Cách trình bày GridLayout: .......................................................................................128

V.3 Cách trình bày BorderLayout .....................................................................................128

VI. Các hộp thoại .................................................................................................................128

VI.1 Hộp thoại thông báo .................................................................................................128

VI.2 Hộp thoại chọn File ..................................................................................................129

VI.3 Hộp thoại chọn màu .................................................................................................130

Bài tập .................................................................................................................................130

Đề tài 11. Threading ................................................................................................................132

Page 5: Bai giang JAVA

5

I. Khái niệm thread...............................................................................................................132

I.1 Khái niệm: ..................................................................................................................132

I.2. Lớp Thread ................................................................................................................132

I.3 Các bước để tạo một thread .........................................................................................132

II. Các trạng thái của thread. .................................................................................................133

III. Các thuộc tính của thread ...............................................................................................134

III.1 Độ ưu tiên của thread ................................................................................................134

III.2 Nhóm thread .............................................................................................................135

III.3 Quản lý các ngoại lệ của thread ................................................................................135

IV. Điều khiển các thread .....................................................................................................136

IV.1 Interrupt một thread ..................................................................................................136

IV.2 Dừng một thread ......................................................................................................137

IV.3 Tạm dừng và phục hồi một thread ............................................................................138

IV.4 Giải phóng thời gian cho CPU ..................................................................................138

IV.5 Đợi một thread kết thúc công việc ............................................................................138

V. Đồng bộ thread ................................................................................................................139

V.1 Tình trạng “đua tranh” ...............................................................................................139

V.2 Khóa đối tượng ..........................................................................................................140

V.3 Đối tượng điều kiện ...................................................................................................141

Bài tập .................................................................................................................................143

Phụ lục A. Các từ khóa của Java ..............................................................................................144

Phụ lục B Một số hàm hay sử dụng ..........................................................................................145

Tài liệu tham khảo ...................................................................................................................146

Page 6: Bai giang JAVA

6

Đề tài 0. Giới thiệu về Java

I. Lịch sử hình thành và phát triển ngôn ngữ lập trình Java

I.1. Giới thiệu về Java

Java là một ngôn ngữ lập trình mạnh đang được sử dụng rất rộng rãi hiện nay trên toàn thế

giới. Trên thực tế, Java được biết đến không chỉ là một ngôn ngữ lập trình mà là một platform –

một môi trường và công nghệ phát triển – riêng biệt. Khi làm việc với Java, người lập trình được

sở hữu một thư viện lớn, có tính mở với một lượng mã nguồn tái sử dụng khổng lồ luôn có trên

internet. Ngoài ra, các chương trình viết bằng Java có môi trường thực thi riêng với các tính năng

bảo mật, khả năng triển khai trên nhiều hệ điều hành khác nhau và nhiều tính năng ưu việt khác

chúng ta sẽ xem xét trong phần sau.

I.2 Tóm tắt lịch sử hình thành của Java

Năm 1991, một nhóm kỹ sư của hãng SUN bao gồm Patrick Naughton, Sun Fellow và

James Gosling có ý tưởng phát minh ra một ngôn ngữ lập trình nhỏ gọn có thể thực thi được trên

các thiết bị dạng như bộ chuyển kênh của truyền hình cáp vì các thiết bị kiểu này có bộ nhớ nhỏ.

Bên cạnh đó, do các hãng khác nhau sử dụng các chíp xử lý (CPUs) khác nhau nên một đặc tính

quan trọng mà ngôn ngữ này phải có là độc lập với các dòng CPUs khác nhau – gọi là đặc tính di

động. Nhóm đã mở một dự án có tên là Green để hiện thực hóa ý tưởng này.

Để giải quyết vấn đề di động, nhóm đã sử dụng ý tưởng của kỹ sư Niklaus Wirth – người

sáng lập ngôn ngữ Pascal – về việc sử dụng cơ chế thông dịch và máy ảo (virtual machine).

Về nền tảng ngôn ngữ, do hãng SUN phát triển trên nền UNIX nên họ sử dụng ngôn ngữ

lập trình C++ là chủ yếu. Do đó, ngôn ngữ mới thiên về hướng đối tượng (Object Oriented) của

C++ hơn là hướng thủ tục như Pascal.

Ban đầu nhóm đặt tên cho ngôn ngữ mới là “Oak” nhưng sau đó được chuyển thành Java

do Oak cũng đã là tên một ngôn ngữ lập trình khác.

Năm 1992, dự án Green cho ra đời sản phẩm đầu tiên có tên là “*7” nhưng đã không được

chào đón như mong đợi. Sau đó nhóm đã phải mất cả năm 1993 và nửa đầu 1994 để đi tiếp thị

công nghệ của mình. Từ năm 1994, sự phát triển của Internet đã tạo cơ hội để Java phát triển

nhanh chóng. Nhóm đã phát triển một trình duyệt có tên là HotJava cho phép các chương trình

Java nhúng được trong đó (applet). Đây chính là minh chứng rõ ràng về sức mạnh của Java đã

nhanh chóng được cộng đồng người sử dụng internet biết đến và là tiền đề để Java phát triển rực

rỡ như ngày hôm nay.

Phiên bản đầu tiên 1.0 của Java ra đời vào năm 1996, sau đó là phiên bản 1.1 mặc dù khá

mạnh nhưng cũng còn nhiều hạn chế.

Năm 1998 đánh đấu bước chuyển mình mạnh mẽ của Java với sự ra đời của phiên bản 1.2

làm cho Java tiến gần tới mục tiêu “viết một lần, chạy khắp nơi” (Write once, Run Anywhere).

Các nhân viên tiếp thị của Java gọi đây là phiên bản “Java 2 Standard Edition Software

Development Kit Version 1.2” ý nói tới sự có mặt đồng thời của 2 phiên bản “Standard Edition”

là Micro Edition và Enterprise Edition trong Java.

Các phiên bản 1.3, 1.4 là sự phát triển mở rộng tiếp theo của phiên bản 1.2. Phiên bản 1.5

(chuyển sang gọi là phiên bản 5.0) đánh dấu sự tích hợp đầy đủ nhất các công nghệ Java.

Bảng sau cho thấy sự phát triển thư viện Java qua các phiên bản:

Phiên bản Số các Class và Interface

Page 7: Bai giang JAVA

7

1.0 211

1.1 477

1.2 1524

1.3 1840

1.4 2723

5.0 3270

Hiện tại, Java đã phát triển tới phiên bản 1.6.

II. Các đặc trưng của Java

Java được biết đến với các đặc trưng sau:

II.1. Tính đơn giản

Java được phát triển dựa trên C++ nhưng lược bớt đi hoặc thay thế các khái niệm khó

hiểu như header file, con trỏ, structures, union, operator overloading, virtual base class. Trong

Java chỉ có thừa kế đơn mà không có tính đa thừa kế như của C++. Tuy nhiên tính đa thừa kế

được biểu hiện thông qua việc sử dụng các Interface.

II.2. Tính hướng đối tượng

Như đã trình bày ở trên, Java được phát triển từ C++ nên nó là ngôn ngữ lập trình hướng

đối tượng.

II.3. Tính phân tán

Java cho phép lập trình truy cập các đối tượng từ xa thông qua các giao thức HTTP, FTP

bằng các phương thức như RMI hay Socket.

Java hoàn toàn thích hợp cho các ứng dụng Internet. Các công nghệ JSP, Servlet cho phép

xây dựng các website tương tác với các tính năng thực thi tối ưu

II.4. Tính mạnh mẽ

Việc loại bỏ con trỏ làm tăng độ tin cậy của chương trình. Lập trình viên không cần quan

tâm đến thao tác cấp phát và giải phóng bộ nhớ. Với Java, bộ nhớ được giải phóng tự động.

II.5. Tính an toàn

Ngôn ngữ Java được thiết kế để tránh các sự cố:

Nạp chồng stack lúc runtime.

Ảnh hưởng tới bộ nhớ nằm ngoài phạm vi được cấp phát.

Đọc và ghi file tự do

II.6. Tính trung lập

Các chương trình viết bằng Java không bị phụ thuộc vào hệ điều hành. Điều này có được

là do mã nguồn chương trình không được biên dịch thành mã máy ngay mà thành mã Bytecode.

Page 8: Bai giang JAVA

8

Khi đem mã Bytecode này chạy trên hệ máy tính nào thì một trình thông dịch virtual machine

(Java Vitual Machine-JVM) sẽ thông dịch chúng sang mã máy tương ứng để thực thi.

Mã nguồn -> ByteCodes -> machine code.

Từ mã nguồn -> Bytecodes: Trình biên dịch Java.

Từ Bytecodes -> machine code: Trình thông dịch Virtual machine.

Java Virtual Machine – JVM

Máy ảo là một phần mềm dựa trên cơ sở máy tính ảo. Nó có tập hợp các lệnh logic để xác

định các hoạt động của máy tính. Người ta có thể xem nó như một hệ điều hành thu nhỏ. JVM

thiết lập các lớp trừu tượng cho phần cứng bên dưới, hệ điều hành, mã đã biên dịch.

Trình biên dịch chuyển mã nguồn thành tập các lệnh của máy ảo mà không phụ thuộc vào

phần cứng cụ thể. Trình thông dịch trên mỗi máy sẽ chuyển tập lệnh này thành chương trình thực

thi. Máy ảo tạo ra một môi trường bên trong để thực thi các lệnh bằng cách:

Nạp các file .class

Quản lý bộ nhớ

Dọn “rác”, thu hồi bộ nhớ cấp cho các biến không còn được sử dụng.

Việc không nhất quán của phần cứng làm cho máy ảo phải sử dụng ngăn xếp để lưu trữ

các thông tin sau:

Các “Frame” chứa các trạng thái của các phương thức.

Các toán hạng của mã bytecode.

Các tham số truyền cho phương thức.

Các biến cục bộ.

II.7. Tính di động

Không giống C++ và C, các kiểu dữ liệu nguyên thủy của Java được cấp phát một lượng

bộ nhớ cố định. Chẳng hạn kiểu dữ liệu int của Java luôn là 4 byte (32 bit) trong khi kiểu int của

C++ có thể hiểu là 2 byte hoặc 4 byte. Thiết kế này giúp cho trình biên dịch luôn có số bytecode

như nhau trên mọi hệ máy và sau đó phát sinh mã máy theo khuôn dạng cố định.

Trong các phiên bản đầu của Java, vấn đề giao diện đồ họa cho người sử dụng (GUI) chưa

được xử lý triệt để và phụ thuộc vào hệ máy. Ngày nay, thư viện GUI của Java đã được viết lại

hoàn toàn và có tính độc lập cao giúp cho chương trình Java có giao diện giống nhau trên mọi hệ

máy.

Macintosh

Trình

biên dịch

Bytecode

Trình

thông

dịch

Java

(Java

Interpreter)

IBM

Sparc

Page 9: Bai giang JAVA

9

II.8. Tính thông dịch

Trình thông dịch Java sẽ thông dịch mã bytecode sang mã máy nơi mà nó được cài đặt.

Quá trình này cũng làm các chương trình Java chạy chậm hơn. Tuy nhiên đây lại là giải pháp cho

tính di động.

II.9. Tính thực thi cao

Java sử dụng công nghệ Just-In-Time (JIT) giúp quá trình thông dịch thực hiện nhanh

hơn. Với công nghệ này, những mã bytecode giống nhau sẽ chỉ cần thông dịch một lần. Ngày

nay, công nghệ này liên tục được cải tiến và cho kết quả vượt trội so với các trình thông dịch

truyền thống. Ví dụ như JIT có thể quản lý các đoạn mã được sử dụng thường xuyên trong

chương trình, tối ưu chúng để nâng cao tốc độc thực hiện.

II.10. Tính đa luồng

Với chương trình Java, lập trình viên có thể cùng lúc quản lý nhiều tiến trình khác nhau.

Điều này giúp cho việc cài đặt các thuật toán song song bằng Java trên các máy tính nhiều CPU

được dễ dàng hơn, đặc biệt trong các ứng dụng thời gian thực.

II.11. Tính động

Các chương trình Java có thể được nâng cấp mà không ảnh hưởng tới người sử dụng. Các

phương thức mới có thể được cài đặt thêm vào các lớp đối tượng hay các giao diện trong thư viện

của chương trình đang chạy.

III. Các loại ứng dụng của Java

Ứng dụng console: Không có giao diện GUI.

Ứng dụng đồ hoạ: Có giao diện GUI.

Applet: Nhúng trong các trang Web.

Servlet: Các class thực thi phía web server.

JSP: Các file nhúng mã Java và HTML.

Ứng dụng EJB, RMI, JMS: Xây dựng ứng dụng bởi nhiều thành phần ghép lại,

giao tiếp từ xa.

IV. Công cụ và môi trường lập trình Java

Hiện nay có rất nhiều môi trường phát triển Java (Integrated Development Environment -

IDE). Mỗi môi trường cung cấp cho lập trình viên những tiện ích lập trình ở mức độ khác nhau.

Một số IDE thông dụng là:

Netbeans (miễn phí tại http://www.netbeans.org).

Jcreator (thương mại).

Jbuilder (thương mại).

Eclipse (miễn phí http://www.eclipse.org/).

V. Cài đặt Java

Java phiên bản Java mới nhất có thể download tại địa chỉ http://java.sun.com/j2se. Sau đó

cài đặt như ứng dụng bình thường.

Thư mục cài đặt mặc định của Java trên Windows là C:\Program Files\Java\jdk1.6.0_02

(nếu phiên bản cài là jdk1.6.0_02). Trong đó có chứa các thư mục với ý nghĩa sau:

Page 10: Bai giang JAVA

10

bin Chứa các công cụ và trình biên dịch Java

demo Chứa các chương trình Java Demo

docs Chứa các tài liệu mô tả thư viện của Java

includes Chứa các file dùng để biên dịch các đoạn mã nguồn viết bằng ngôn ngữ khác (native).

jre Chứa các file lưu thông tin môi trường lúc thực thi

lib Chứa các file thư viện

src Chứa mã nguồn java

Trong thư mục \bin có chữa các công cụ chính của Java:

Trình biên dịch, 'javac'

Cú pháp:javac [options] sourcecodename.java

Trình thông dịch, 'java'

Cú pháp:java [options] classname

Trình dịch ngược, 'javap'

javap dịch ngược bytecode và in ra thông tin về các thuộc tính (các trường), các phương

thức của một lớp.

Cú pháp:javap [options] classname

Công cụ sinh tài liệu, 'javadoc'

Tiện ích này cho phép ta tạo ra tệp HTML dựa trên các lời giải thích trong mã chương

trình (phần nằm trong cặp dấu /*.... */).

Cú pháp:javadoc [options] sourcecodename.java

Chương trình tìm lỗi - Debug, 'jdb„

Cú pháp:jdb [options] sourcecodename.java

hay

jdb -host -password [options] sourcecodename.java

Cài đặt đường dẫn mặc định.

1. Mở Control Panel

2. Chọn System

Page 11: Bai giang JAVA

11

3. Chọn Tab Advanced

4. Chọn Environment Variables

5. Thêm đường dẫn C:\Program Files\Java\jdk1.6.0_02\bin vào biến môi trường Path

- Chọn Variable Path

- Chọn Edit

Page 12: Bai giang JAVA

12

Đề tài 1. Ngôn ngữ mô hình hóa UML

I. Xây dựng hệ thống phần mềm theo hướng đối tượng

I.1 Các khái niệm căn bản của công nghệ hướng đối tượng

Hướng đối tượng là một công nghệ để sản sinh ra các mô hình phản ánh một cách tự

nhiên các nghiệp vụ thực tế. Xét cho cùng thì mọi quy trình nghiệp vụ trong thực tế đều là sự

tương tác của các đối tượng theo một trình tự nhằm đạt được một mục đích cụ thể. Nói cách khác,

các đối tượng và mối quan hệ giữa chúng phản ánh quy trình nghiệp vụ. Ví dụ như nghiệp vụ

tuyển nhân sự cho một công ty có thể được tóm tắt qua một chuỗi các tương tác như sau:

1. Công ty đưa ra thông báo tuyển nhân sự tới các ứng viên có nhu cầu

2. Ứng viên gửi hồ sơ dự tuyển tới công ty

3. Công ty duyệt hồ sơ và gửi giấy hẹn phỏng vấn tới ứng viên

4. Công ty phỏng vấn ứng viên

5. Công ty ký hợp đồng với ứng viên hoặc từ chối

Trong ví dụ trên có sự tham gia của hai đối tượng “công ty” và “ứng viên”. Sự trao đổi

thông tin giữa hai đối tượng này cho thấy mối quan hệ phụ thuộc giữa chúng (dependence).

Một ví dụ khác là trong hệ thống quản lý nhân sự chúng ta có các đối tượng như: nhân

viên, quản lý,…cho thấy mối quan hệ dạng khác: các nhân viên làm công việc quản lý tất nhiên

cũng là nhân viên của công ty nhưng có thêm các thuộc tính riêng biệt – một quan hệ kế thừa

(inheritance).

Trong một hệ thống bán hàng, mỗi đơn hàng bao gồm trong nó các thông tin về khách

hàng, ngày giờ, …và một danh mục các mặt hàng. Khi này ta nói rằng giữa đơn hàng và mặt

hàng tồn tại một quan hệ bao gồm (aggregation)

Mục tiêu của công nghệ hướng đối tượng chính là thể hiện được các đối tượng và mối

quan hệ giữa chúng vào trong các hệ thống phần mềm. Vì vậy, các hệ thống phần mềm theo công

nghệ hướng đối tượng phản ánh một cách tự nhiên và trung thực nghiệp vụ thực tế và có khả

năng đáp ứng các thay đổi dễ dàng.

Phát triển một hệ thống phần mềm theo hướng đối tượng dựa trên 5 khái niệm cơ bản:

Lớp (class), đối tượng (object), thông điệp (mesage), thừa kế (inheritance) và đa hình

(polymorphism).

Lớp là sự trừu tượng hóa các đối tượng thực tế theo phạm vi nghiệp vụ. Lấy ví dụ về hệ

thống quản lý sinh viên của trường ĐHBK Hà Nội cần quản lý rất nhiều đối tượng sinh viên khác

nhau nhưng có thể chỉ được trừu tượng hóa thành một lớp đối tượng có tên SinhVien chẳng hạn.

Sự trừu tượng hóa một lớp đối tượng cho ta kết quả một tập các thuộc tính (attributes) và các

hành vi (operations) đặc trưng cho bất kỳ đối tượng nào thuộc lớp đó. Đối tượng thực tế thì có vô

số thuộc tính và hành vi nhưng chỉ thuộc tính và hành vi trong phạm vi nghiệp vụ là được xét

đến. Sự chi tiết phụ thuộc vào phạm vi nghiệp vụ.

Sự trừu tượng hóa diễn ra ở nhiều cấp độ. Lấy ví dụ: lớp động vật có vú bao gồm lớp

động vật 4 chân, lớp 4 chân lại bao gồm các lớp như lớp mèo, lớp trâu,…

Mỗi đối tượng là một biểu hiện thực tế của một lớp.

object = name + attributes + operations

Hệ thống hướng đối tượng nếu được mô hình đúng sẽ rất linh hoạt, dễ hiệu chỉnh, được

cài đặt dễ dàng bằng các ngôn ngữ hướng đối tượng. Các hệ thống phần mềm hướng đối tượng

cũng được cài đặt bởi các ngôn ngữ lập trình hướng đối tượng.

Page 13: Bai giang JAVA

13

Hướng đối tượng không chỉ là một lý thuyết mà đã được chứng minh bằng những ứng

dụng rất thành công trong thực tế ở nhiều lĩnh vực khác nhau. Tuy nhiên, lĩnh vực này vẫn cần

được chuẩn hóa hơn nữa.

I.2 Quy trình chung phát triển hệ thống phần mềm

Xây dựng một hệ thống phần mềm hướng đối tượng cũng tuân theo quy trình chung như

mọi công nghệ khác:

1. Requirements : Thu thập yêu cầu

2. Analysis : Phân tích

3. Design: Thiết kế

4. Implementation: Cài đặt

5. Test: Kiểm thử

6. Deployment: Triển khai

Theo nguyên tắc chung này, mỗi công ty lại ứng dụng những công nghệ khác nhau để

phát triển ứng dụng như các mô hình water fall, mô hình hướng chức năng,…

I.3 Những thách thức của ngành công nghiệp phần mềm hiện nay

Mặc dù đã ứng dụng các công nghệ tiến tiến và quy trình phát triển chuẩn hóa nhưng

ngành công nghiệp phần mềm vẫn phải đối mặt với những thách thức:

1. Sự gia tăng về quy mô từ nhỏ đến lớn của ứng dụng

2. Sức ép về thời gian hoàn thành

3. Sự phân tán về không gian làm việc

4. Đa dạng về nội dung

5. Sự thay đổi các yêu cầu của người sử dụng

Những thách thức này có thể nói là gắn liền với mọi công ty phần mềm đặc biệt là ở Việt

Nam, nơi mà vai trò của quá trình khảo sát, phân tích còn bị xem nhẹ cũng như các công ty còn

đang bỡ ngỡ với sự mở rộng về quy mô và thiếu nhân lực chuyên môn về phân tích thiết kế.

II. Lịch sử phát triển ngôn ngữ mô hình hóa UML

II.1. Tóm tắt lịch sử UML

Những năm 1980 là thời kỳ bùng nổ số lượng các công ty phần mềm sử dụng ngôn ngữ

lập trình hướng đối tượng(Object Oriented Programming - OOP) để xây dựng các ứng dụng.

Điều này dẫn tới một đòi hỏi phải có một quy trình làm phần mềm tiếp cận theo hướng phân tích

và thiết kế hướng đối tượng (Object Oriented Analyze and Design - OOAD). Nhiều nhà nghiên

cứu phương pháp trong đó có Booch, Rumbaugh và Jacobson đã làm việc độc lập và đã đề xuất

các quy trình thỏa mãn yêu cầu này. Mỗi một quy trình có một tập ký hiệu mô hình riêng để

truyền đạt và diễn tả các kết quả phân tích và thiết kế.

Vào đầu những năm 1990, các công ty khác nhau, thậm chí là các bộ phận khác nhau của

cùng một công ty đã sử dụng các quy trình khác nhau. Thêm vào đó, các công ty này lại muốn sử

dụng các công cụ phần mềm hỗ trợ các quy trình của họ. Với quá nhiều quy trình khác nhau, các

công ty phần mềm đã rất khó khăn trong việc cung cấp các công cụ này. Điều này cho thấy việc

cần thiết phải có một quy trình với tập ký hiệu thống nhất.

Năm 1994, James Rumbaugh đã hợp tác cùng Grady Booch tại công ty phần mềm

Rational Software Corporation để cùng xây dựng một quy trình thống nhất dựa trên kết quả của

từng người. Sau đó Ivar Jacobson cũng sớm gia nhập nhóm này. Năm 1996, nhóm đã cho xuất

Page 14: Bai giang JAVA

14

bản phiên bản đầu tiên của UML tới cộng đồng phát triển phần mềm và yêu cầu phản hồi. Cũng

cùng thời gian đó, một tổ chức có tên Object Management Group (OMG) đã mời nhóm đệ trình

một ngôn ngữ mô hình. OMG là một tổ chức phi lợi nhuận chuyên xúc tiến việc sử dụng công

nghệ hướng đối tượng trong ngành công nghiệp phần mềm thông qua việc đưa ra các hướng dẫn

và đặc tả OOP. Các thành viên của OMG ban đầu là 3Com Corporation; American Airlines;

Canon, Inc.; Data General; Hewlett-Packard; Philips Telecommunications N.V.; Sun

Microsystems; và Unisys Corporation. Các tập đoàn lớn như HP, IBM, Microsoft, Oracle và

Rational Software đã nhận thấy lợi ích của UML và đã nhận lời tài trợ cho các dự án về UML của

OMG. Năm 1997, OMG tiếp tục xem xét lại UML và đến năm 2001 thì phiên bản UML 1.4 ra

đời. Hiện nay OMG đã phát hành tới phiên bản UML 2.0 và đang nghiên cứu phiên bản 2.1.

II.2. Khái niệm về UML

UML – Unified Modeling Language là một ngôn ngữ dùng các sơ đồ và mô hình thống

nhất để mô hình các hệ thống phần mềm.

Mục đích của UML là:

Trở thành ngôn ngữ mô hình mà tất cả mọi người làm mô hình có thể sử dụng

Tập trung hướng tới giải quyết các vấn đề tồn tại trong phát triển phần mềm hiện

nay.

Đơn giản nhất có thể trong khi vẫn mô hình được phần lớn các ứng dụng.

Nâng cao tính tái sử dụng các thành phần của một hệ thống phần mềm

UML là một ngôn ngữ diễn tả, UML không phải là một quy trình.

Thuật ngữ “Unified” ở đây có một ý nghĩa quan trọng, nó nói lên các nguyên tắc của

UML:

Thống nhất phương thức, ký hiệu, thuật ngữ

Gắn kết giữa các chu trình phát triển

Không phụ thuộc vào lĩnh vực ứng dụng

Không phụ thuộc vào ngôn ngữ lập trình và môi trường thực hiện

Không phụ thuộc vào quy trình phát triển

Gắn kết chặt chẽ các khái niệm nội tại của hệ thống.

II.3 Đặc trưng của UML

Hiện nay, UML là một ngôn ngữ đã được OMG chuẩn hóa và được đặc tả rõ ràng. Tất cả

các mô hình, sơ đồ của UML đều theo hướng đối tượng.

Các đặc tính của UML bao gồm:

Mô hình class (class diagrams) mô tả cấu trúc tĩnh của hệ thống và mối quan hệ

giữa các đối tượng

Mô hình tương tác (interaction diagrams), mô hình trạng thái (state diagrams), mô

hình hoạt động (activity diagrams) mô tả các hành vi động của các đối tượng trong

hệ thống cũng như các thông điệp giữa chúng.

Mô hình Use-case và mô hình hoạt động mô tả các yêu cầu và các luồng công việc

trong hệ thống.

Các mô hình cấu trúc hỗn hợp (composite structure diagrams) mô tả sự hợp tác

cũng như các đặc điểm về cài đặt.

Mô hình triển khai (deployment diagrams) mô tả việc triển khai phần mềm trên

một môi trường xác định.

Page 15: Bai giang JAVA

15

III. Ngôn ngữ UML

III.1. Các thành phần của UML

Xét trên khía cạnh ngôn ngữ diễn tả, UML có đầy đủ các mô hình và sơ đồ để thể hiện

hầu hêt các khía cạnh của hệ thống phần mềm. Các thành phần của ngôn ngữ UML bao gồm:

Các Views (các hướng nhìn): Các view thể hiện các cách nhìn khác nhau tới hệ

thống. Một hệ thống không thể chỉ được mô tả bởi một sơ đồ. Nhiều hướng nhìn

khác nhau cho ta nhiều sơ đồ mô tả đầy đủ về hệ thống. Các hướng nhìn cũng liên

kết ngôn ngữ mô hình với các quy trình được chọn cho việc phát triển hệ thống.

Các Diagrams (các sơ đồ): Các sơ đồ bao gồm các phần tử hình vẽ dùng để mô tả

nôi dung của các View. UML 2.0 bao gồm 13 loại sơ đồ khác nhau.

Các Model Elements (các phần tử mô hình): Các khái niệm được sử dụng trong

các sơ đồ và các phần tử của sơ đồ diễn tả các khái niệm phổ biến của công nghệ

hướng đối tượng như class, object, message (thông điệp) và mối quan hệ giữa

chúng bao gồm quan hệ dependence, inheritance và aggregation. Một phần tử mô

hình có thể được sử dụng trong nhiều sơ đồ nhưng chúng luôn có cùng ý nghĩa và

ký hiệu giống nhau.

Các General Mechanisms (các đặc tả chung mở rộng): Mô tả các thông tin chú

thích, ngữ nghĩa của các phần tử mô hình, thuật ngữ.

III.2. Các hướng nhìn (view)

Use-case view: Đây là hướng nhìn về mặt chức năng của hệ thống được thực hiện bởi các

tác nhân bên ngoài.

Page 16: Bai giang JAVA

16

Các nguyên tắc cho việc xây dựng use-case view là:

Các use-case được hình thành trên cơ sở nhìn từ bên ngoài vào trong hệ thống

(out-> in).

Các use-case phải đầy đủ, chúng được tổng hợp theo phương pháp đi từ tối đa đến

tối thiểu (ban đầu mở rộng tối đa các use-case có thể sau đó thu hẹp lại theo nhu

cầu khách hàng).

Các use-case cần có tính độc lập tương đối để dễ tổ chức nhóm làm việc và có tính

tái sử dụng cao.

Bên cạnh sơ đồ, người làm mô hình có thể sử dụng mô tả bằng văn bản chi tiết cho mỗi

use-case (text detail). Mỗi mô tả cần đảm bảo các thông tin sau:

1. Tên use-case

2. Mục tiêu của use-case

3. Phạm vi của use-case

4. Các tác nhân chính

5. Tiền điều kiện

6. Dòng chính

7. Dòng phụ

ud Primary Use Cases• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

HÖ thèng b¸n hµng qua m¹ng Interrnet

Chän hµng

Kh¸ch hµng

§¨ng ký kh¸ch hµng

Qu¶n trÞ hÖ thèng

Nh©n viªn kinh doanh

LËp ®¬n mua hµng

Göi th«ng tin ph¶n håi

Xem chi tiÕt s¶n phÈm

CËp nhËt giá hµng

CËp nhËt th«ng tin mÆt hµng

Qu¶n lý danh môc hµng hãa

Tr¶ lêi kh¸ch hµng

Theo dâi ®¬n hµng

Page 17: Bai giang JAVA

17

8. Ngoại lệ

9. Hậu điều kiện

Sau đây là một ví dụ về use-case text detail:

Use-case: Đòi tiền bồi thường

Phạm vi: Công ty Bảo hiểm PCM

Actor chính: Người đòi bồi thường

Dòng chính

1. Người đòi bồi thường gửi đơn yêu cầu với các dữ liệu bằng chứng về tai nạn

2. Công ty bảo hiểm xác nhận người viết đơn có quyền lợi bảo hiểm hợp lệ

3. Công ty bảo hiểm phân công cho một đại lý xác minh trường hợp này

4. Đại lý đối chiếu tất cả các chi tiết trong đơn theo chính sách bảo hiểm của công ty

5. Công ty bảo hiểm trả tiền bảo hiểm

Dòng phụ

1a. Bằng chứng tai nạn không đầy đủ

1a1. Công ty bảo hiểm yêu cầu dữ liệu thiếu

1a2. Người đòi bồi thường gửi lại các dữ liệu thiếu

2a. Người đòi bồi thường không có chính sách bảo hiểm hợp lệ

2a1. Công ty bảo hiểm từ chối yêu cầu, nhắc nhở, ghi lại và kết thúc xử lý vụ việc

3a. Không có đại lý nào rảnh rỗi

3a1. (Công ty bảo hiểm sẽ làm gì trong trường hợp này???)

4a. Vụ tai nạn vi phạm chính sách bảo hiểm cơ bản

4a1. Công ty bảo hiểm từ chối yêu cầu, nhắc nhở, ghi lại và kết thúc xử lý vụ việc

4b. Vụ tai nạn chỉ vi phạm chính sách bảo hiểm nhỏ

4b1. Công ty bảo hiểm điều đình với người đòi bảo hiểm và đồng ý trả bảo hiểm

Trong trường hợp các use-case quá phức tạp và chưa được mô tả rõ ràng, chúng có thể

được tác ra thành các use-case nhỏ hơn theo hai dạng:

Include: use-case mới được tách ra và được bao gồm trong use-case chính một

cách vô điều kiện

Extend: use-case mới xảy ra khi một điều kiện xảy ra trong use-case chính.

uc Use Case Model

Use Case Principal

Use Case Include

«include»

Page 18: Bai giang JAVA

18

Nói chung, use-case view giúp ta trả lời câu hỏi WHAT? về hệ thống.

Logical views

Đây là hướng nhìn cho biết các chức năng được thiết kế vào trong hệ thống như thế nào

(HOW?) thông qua việc mô tả các cấu trúc tĩnh và các hành vi động của hệ thống. Sau đây là một

số sơ đồ quan trọng thường được sử dụng.

Các cấu trúc tĩnh (static structure): Cấu trúc tĩnh được mô hình bằng UML chính là các

class diagrams. Đây là sự mô hình các khái niệm trong ứng dụng, các đặc điểm nội tại cũng như

mối quan hệ giữa chúng.

Ví dụ về mô hình class:

Các khái niệm Mô hình hóa

Classes

Attributes Operations

Object

uc Use Case Model

Use Case Principal

Use Case Extend

«extend»

Page 19: Bai giang JAVA

19

Các hành vi động:

State machine:

cd Jav a Model

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

Account

- billingAddress: String- closed: boolean- deliveryAddress: String- emailAddress: String- name: String

+ createNewAccount() : void+ loadAccountDetails() : void+ markAccountClosed() : void+ retrieveAccountDetails() : void+ submitNewAccountDetails() : void+ validateUser(String, String)

property get

+ getBasket() : ShoppingBasket+ getBillingAddress() : String+ getClosed() : boolean+ getDeliveryAddress() : String+ getEmailAddress() : String+ getName() : String+ getOrder() : Order

property set

+ setBasket(ShoppingBasket) : void+ setBillingAddress(String) : void+ setClosed(boolean) : void+ setDeliveryAddress(String) : void+ setEmailAddress(String) : void+ setName(String) : void+ setOrder(Order) : void

LineItem

- quantity: int

property get

+ getItem() : StockItem+ getQuantity() : int

property set

+ setItem(StockItem) : void+ setQuantity(int) : void

Order

- date: Date- deliveryInstructions: String- orderNumber: String

+ checkForOutstandingOrders() : void

property get

+ getDate() : Date+ getDeliveryInstructions() : String+ getLineItem() : LineItem+ getOrderNumber() : String+ getStatus() : OrderStatus

property set

+ setDate(Date) : void+ setDeliveryInstructions(String) : void+ setLineItem(LineItem) : void+ setOrderNumber(String) : void+ setStatus(OrderStatus) : void

«enumeration»OrderStatus

enum- closed: int- delivered: int- dispatched: int- new: int- packed: int

ShoppingBasket

- shoppingBasketNumber: String

+ addLineItem() : void+ createNewBasket() : void+ deleteItem() : void+ processOrder() : void

property get

+ getLineItem() : LineItem

property set

+ setLineItem(LineItem) : void

StockItem

- Author: string- catalogNumber: string- costPrice: number- listPrice: number- title: string

property get

+ getAuthor() : string+ getCatalogNumber() : string+ getCostPrice() : number+ getListPrice() : number+ getTitle() : string

property set

+ setAuthor(string) : void+ setCatalogNumber(string) : void+ setCostPrice(number) : void+ setListPrice(number) : void+ setTitle(string) : void

Transaction

- date: Date- orderNumber: String

+ loadAccountHistory() : void+ loadOpenOrders() : void

property get

+ getAccount() : Account+ getDate() : Date+ getLineItem() : LineItem+ getOrderNumber() : String

property set

+ setAccount(Account) : void+ setDate(Date) : void+ setLineItem(LineItem) : void+ setOrderNumber(String) : void

-history-account

-status

-item

-basket

-account

Page 20: Bai giang JAVA

20

Đây là mô hình mô tả việc chuyển đổi trạng thái của đối tượng trong quá trình tham gia

các hoạt động nghiệp vụ của hệ thống. Trạng thái của đối tượng bị thay đổi bởi một hành vi nào

đó.

Sơ đồ hành động (activity diagrams): Đây là sơ đồ mô tả luồng nghiệp vụ trong hệ thống.

Page 21: Bai giang JAVA

21

Sơ đồ tương tác (interaction diagram): Đây là sơ đồ mô tả sự tương tác giữa các đối tượng

theo trình tự thời gian (còn gọi là sequence diagram). Các sơ đồ sequence có thể được mô tả ở

mức hệ thống (Sequence System – chỉ có user tương tác với hệ thống) hoặc mức chi tiết

(Sequence Detail – Các đối tượng và thông điệp giữa chúng đã được định hình):

Các class trong hệ thống được chia thành ba loại tách biệt: M (Model) – V (View) – C

(Control). Các class V chịu trách nhiệm hiển thị giao diện tương tác với người sử dụng, các class

M lưu trữ dữ liệu được mô hình hóa từ thông tin đối tượng quản lý trong khi các class C là nơi

điều khiển việc dữ liệu từ M được đưa tới giao diện V như thế nào hoặc xử lý các yêu cầu từ V

sau đó cập nhật vào M.

Sơ đồ triển khai (Deployment Diagram):

sd Sequence• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

Khach muahang

DangKy Page

AccountUtilities AccountTable

Nhap thong tin dang ky

Click "Dang Ky"

XacNhanThongTinDangKy()

DangKyKhachHang()

sd MuaHang• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •

TrangChuKhach Hang SanPhamUtil itiesTrangDanhMucSanPham SanPhamTable

Chon xem san pham theo hang

Redirect

LayDanhSachSanPham

HienThi

M V C

M V C

Page 22: Bai giang JAVA

22

III.3 Ứng dụng UML trong quy trình làm phần mềm

Như đã trình bày ở trên, UML chỉ thuần túy là một ngôn ngữ mô hình. Các công ty phần

mềm khác nhau tuy đều ứng dụng UML nhưng có thể sử dụng các quy trình phát triển khác nhau.

Page 23: Bai giang JAVA

23

Sơ đồ trên cho thấy một trình tự sử dụng các mô hình UML để xây dựng một ứng dụng.

Xuất phát từ ý tưởng ban đầu thuần túy mang tính nghiệp vụ, các bước tiếp theo cần làm song

song là xây dựng mô hình use-case và vẽ phác thảo giao diện chương trình. Tiếp theo xây dựng

mô hình sequence system vì thông qua giao diện ta đã biết user tương tác với system như thế nào.

Sau đó xây dựng mô hình class ở mức phác thảo, sơ đồ trạng thái và sơ đồ hành động. Đến đây ta

đã biết user tương tác với cụ thể đối tượng nào của system và các thông điệp giữa các đối tượng

từ mô hình class. Đây là cơ sở để xây dựng sequence detail và hoàn chỉnh mô hình class với các

quan hệ đầy đủ.

Theo quan điểm về phân tích thiết kế bằng UML thì việc lập trình rõ ràng không chỉ bắt

đầu khi cài đặt các class và các sequence detail bằng một ngôn ngữ lập trình mà thực tế chúng ta

đã lập trình ngay từ khi xây dựng mô hình use-case và viết text detail cho nó. Như vậy việc lập

trình cài đặt chỉ được tiến hành sau khi cac mô hình đã hoàn tất. Trong quá trình xây dựng các

mô hình cần liên tục tiếp xúc với khách hàng để đảm bảo tính chính xác của mô hình. Một khi

các mô hình và tài liệu đặc tả đã hoàn chỉnh, việc coding thực sự chỉ chiếm khoảng 20% tổng số

thời gian.

Sau đây là một số công cụ giúp sử dụng UML trong phát triển hệ thống phần mềm:

IV. Quy trình Rational Unified Process (RUP) phát triển phần mềm dựa trên UML

IV.1. Giới thiệu về RUP

Trong số các quy trình hiện nay, RUP được phát triển bởi công ty Rational Software được

sử dụng khá phổ biến.

Lịch sử: RUP là sự phối hợp giữa cách tiếp cận công nghệ hướng đối tượng của Rational

trong những năm 1980s và 1990s với công nghệ xử lý đối tượng của Ival Jarcobson.

Phiên bản mới nhất của RUP là version 7.0 phát hành 2005.

Động cơ phát triển RUP là tìm ra nguyên nhân của các lỗi phần mềm và tìm cách khắc

phục chúng thông qua một quy trình.

IV.2. Các nguyên tắc chính của RUP:

1- Tuân thủ tiến trình (Adapt the process)

2- Cân bằng các ưu tiên của stakeholder (Balance stackeholder priorities). Stakeholder là

những người đưa ra những ý kiến có ảnh hưởng lớn tới tư tưởng thiết kế hệ thống.

3- Cộng tác giữa các nhóm (Collaborate across teams)

Page 24: Bai giang JAVA

24

4- Thể hiện kết quả theo quy trình lặp (Demonstrate value iteratively). Kết thúc mỗi quy

trình cần theo dõi kết quả và kiểm tra chặt chẽ.

5- Nâng cao mức độ trừu tượng (Elevate the level of abstraction)

6- Tập trung theo dõi chất lượng liên tục (Focus continuously on quality)

IV.3. Vòng đời của phần mềm theo quy trình RUP

Trong một vòng đời của phần mềm, có 4 pha: Inception, Elaboration, Construction và

Transition.

Biểu đồ trên cho biết trình tự các pha và lượng tài nguyên sử dụng cho mỗi pha.

Inception: Đây là giai đoạn chuẩn bị, tiếp xúc với khách hàng để nắm bắt ý tưởng

và thu thập yêu cầu, chuẩn bị nhân lực, vật tư kỹ thuật.

Elaboration: Sau khi đã thu thập được yêu cầu thì đây là pha thiết kế phác thảo sử

dụng các sơ đồ UML để mô hình hóa các yêu cầu, các quy trình nghiệp vụ của

ứng dụng,…

Construction: Pha xây dựng hệ thống yêu cầu sử dụng nhiều nhân lực, tài nguyên

của công ty. Các công việc như thiết kế chi tiết, cài đặt, kiểm thử,…đều được tiến

hành trong pha này.

Transition: Pha chuyển giao cho khách hàng.

Một biểu đồ khác chi tiết hơn cho ta thấy các các giai đoạn phát triển được tiến hành khi

nào và mức độ sử dụng tài nguyên của chúng trong các pha theo các nguyên tắc chung.

Page 25: Bai giang JAVA

25

Các giai đoạn công việc của RUP bao gồm:

Mô hình hóa nghiệp vụ (business modeling): mô tả cấu trúc và quy trình nghiệp

vụ.

Xác định yêu cầu (requirement): mô tả nghiệp vụ bằng phương pháp “tình huống

sử dụng” (use case base method)

Phân tích và thiết kế (analysis & design): mô tả kiến trúc hệ thống thông qua các

sơ đồ phân tích thiết kế.

Lập trình (Implement): thực hiện các việc xây dựng chương trình bằng ngôn ngữ

lập trình.

Thử nghiệm (Test): mô tả các tình huống và kịch bản thử nghiệm, tiến hành thử

nghiệm hệ thống phần mềm.

Triển khai (Deployment): đưa hệ thống phần mềm vào sử dụng.

Quản trị cấu hình và quản trị thay đổi (Configuration & Change Management):

kiểm soát các thay đổi và duy trì sự hợp nhất của các thành phần dự án.

Quản trị dự án: quản lý toàn bộ quá trình làm việc của dự án.

Đảm bảo môi trường: đảm bảo các hạ tầng cần thiết để có thể phát triển được hệ

thống.

IV.4. Các công cụ của RUP

Để áp dụng được quy trình phát triển hệ thống phần mềm của Rational thì yêu cầu không

thể thiếu là hệ thống các phần mềm công cụ hỗ trợ. Hãng Rational đã xây dựng một hệ thống

công cụ như vậy, mà tiêu biểu và thường dùng nhất là:

Phần mềm Rational Requisite Pro: cho phép phân tích các yêu cầu, xây dựng kế

hoạch thực hiện, xác định các tác nhân của hệ thống cùng những tình huống sử

dụng.

Page 26: Bai giang JAVA

26

Phần mềm Rational Rose: cho phép xây dựng các mô hình phân tích, thiết kế, triển

khai.

Phần mềm Rational XDE: cho phép vừa xây dựng các mô hình vừa kết sinh mà

nguồn chương trình song song với nhau.

Phần mềm Rational Clear Case: quản trị dự án phân tích thiết kế, cho phép làm

việc theo nhóm.

Bài tập

1. Xây dựng mô hình use-case cho hệ thống quản lý việc mượn và trả sách tại thư viện.

Hãy tiết text detail và xây dựng mô hình sequence system cho các use-case : “Mượn sách” và

“Trả sách”.

2. Hãy mô tả một quy trình ứng dụng UML trong phát triển hệ thống phần mềm.

Page 27: Bai giang JAVA

27

Đề tài 2. Nhập môn Java

I. Viết và thực hiện một chương trình Java

I.1 Tìm hiểu mã nguồn một chương trình đơn giản

1. /* Day la chuong trinh vi du*/

2. public class Vidu

3. {

4. public static void main(String[] args)

5. {

6. System.out.println("Hello, World!");

7. }

8. }

Dòng 1: Dòng chú thích trong một chương trình Java. Trong khi lập trình, ta cần chú ý

viết các dòng chú thích để mô tả về mã nguồn. Điều này rất quan trọng khi chương trình lớn và

gặp lỗi, các dòng chú thích giúp ta nhanh chóng nhận ra vai trò và ý nghĩa của từng đoạn code.

Các chú thích trong chương trình Java được đặt trong cặp /* và */ khi cần chú thích nhiều

dòng hoặc để sau cặp // khi chỉ chú thích một dòng. Tuy nhiên các cặp /* và */ hay được dùng

hơn vì các đoạn chú thích này sẽ được tự động đưa vào tài liệu khi ta dùng công cụ javadoc để

sinh tài liệu cho mã nguồn.

Dòng 2: Khai báo một lớp có tên Vidu.

Dòng 3. Cùng với dòng 8 tạo thành một cặp {} dùng để đánh dấu việc mở và đóng cho

một khối lệnh, trong trường hợp này, tất cả các lệnh nằm trong cặp này đều thuộc phạm vi của

lớp Vidu.

Dòng 4: Khai báo hàm main. Trong Java, mọi chương trình nếu cần thực thi đều bắt đầu

từ hàm main. Trình thông dịch sẽ tìm hàm main làm điểm khởi phát cho một ứng dụng Java.

Dòng 5 và 7 cũng là đánh dấu mở và đóng cho một khối lệnh thuộc hàm main.

Dòng 6: Câu lệnh in ra màn hình dòng chữ “Hello, World!”. Các lệnh trong Java luôn

được kết thúc bởi dấu ;.

I.2. Thực hiện chương trình Java.

Để thực hiện chương trình Java trong ví dụ trên, ta thực hiện theo các bước sau:

1. Dùng một trình soạn thảo bất kỳ hoặc một IDE Java thì càng tốt để soạn chương trình.

2. Ghi file vừa soạn với tên Vidu.java. Ở đây, tên file phải bắt buộc là Vidu giống như tên

lớp trong chương trình. Phần mở rộng cũng bắt buộc là .java để trình biên dịch Java biết đây là

file chứa mã nguồn Java. Giả sử ghi vào thư mục c:\JavaSample.

3. Gọi cửa sổ Command Line của Windows: Từ Menu Start, chọn Run và gõ vào lệnh

“cmd”.

4. Từ dấu nhắc gõ lệnh:

javac c:\JavaSample\Vidu.java

Sau lệnh này, nếu chương trình không có lỗi cú pháp, Java sẽ sinh ra một file mã bytecode

có tên Vidu.class mặc định cũng nằm trong thư mục c:\JavaSample.

5. Từ dấu nhắc gõ lệnh:

java c:\ JavaSample\Vidu.class

Page 28: Bai giang JAVA

28

Lệnh này sẽ thông dịch file mã bytecode Vidu.class và in ra màn hình dòng chữ “Hello,

World!”.

Ở đây, ta cần chú ý Windows không tự động hiểu các lệnh javac, java. Tuy nhiên, khi cài

đặt Java ta đã đặt đường dẫn mặc định đến thư mục chứa các lệnh này là

C:\Program Files\Java\jdk1.6.0_02\bin

Trường hợp chưa đặt đường dẫn mặc định, ta phải gọi các lệnh này với đường dẫn đầy đủ

của nó.

I.3. Một số chú ý khi lập trình Java

Java phân biệt chữ viết hoa và viết thường.

Hàm main phải nằm trong file gọi thực hiện

Tên khai báo phải trùng với tên tệp “Vidu.java”

Hàm main trong Java luôn luôn là static

Trong Java tất cả hàm và thủ tục đều phải được đặt trong một lớp cụ thể.

Không được khai báo phương thức, hàm hay thủ tục bên ngoài lớp.

Sử dụng phương thức (method) để thay thế cho hàm và thủ tục.

I.4. Cấu trúc một chương trình Java

/*Khai bao goi*/

package <tên gói>;

/*Khai bao thu vien*/

import <tên gói thư viện>;

/*Khai bao lop chua ham main*/

public class <tên lớp>

{

/*Các thuoc tinh cua lop */

…………………….

/*Cac phuong thuc*/

…………………….

/*Hàm main*/

public static void main(String[] args)

{

// Các lệnh trong hàm main

}

}

/*Cac lop lien quan khac*/

class A

{

………….

}

class B

{

………….

}

Các thành phần trong một chương trình Java gồm có:

1. Khai báo gói:

Page 29: Bai giang JAVA

29

Cú pháp: package <tên gói>.

Khai báo này là không bắt buộc với một chương trình Java. Trong trường hợp ứng dụng

gồm nhiều class và cần tổ chức các class vào các gói riêng thì ta cần khai báo gói. Trong chương

trình trên, class Vidu sau khi biên dịch sẽ được đặt trong gói my.java. Tên của gói có chứa các

dấu “.” chỉ sự bao gồm, ở đây gói “java” nằm trong gói “my” và class Vidu nằm trong gói “java”.

Khi một chương trình Java khác muốn truy cập tới lớp Vidu, nó cần truy cập theo đường dẫn gói

“my.java.Vidu”.

Thực ra, ý nghĩa quan trọng của gói là việc tổ chức một cách logic các lớp vào trong các

domain riêng để người phát triển ứng dụng dễ dàng truy cập. Trong hàng ngàn class được Java hỗ

trợ trong các gói thư viện, chúng đều được nhóm lại theo chức năng và mục đích sử dụng với tên

gói có tính chất gợi ý. Nếu không làm như vậy, chúng ta sẽ rất khó khăn để tìm ra một class để sử

dụng.

2. Nhập thư viện.

Cú pháp: import <tên thư viện>

Nếu có khai báo này, khi sử dụng các class nằm trong gói theo <tên thư viện> ta không

cần viết đầy đủ tên gói mà chỉ cần viết tên class. Java dùng ký từ “*” để ngụ ý việc nhập tất cả

các class trong <tên thư viện>. Ví dụ:

import my.java.Vidu; // Nhập duy nhất class Vidu trong gói my.java

import my.java.*; // Nhập tất cả các class có trong gói my.java, tất nhiên là bao gồm cả

class Vidu.

Sau đây là một chương trình ví dụ sử dụng import:

import java.util.Date; //Khai báo thư viện

/*Chương trình in ra ngày tháng hiện hành*/

public class Application {

public static void main(String[] args) {

Date date = new Date(); //tạo biến đối tượng thuộc class Date

System.out.println(“Hôm nay "+date);

}

}

Ở đây, class Date đã được khai báo import nên không cần khai báo đầy đủ

“java.util.Date” tại dòng số 5.

3. Khai báo class, thuộc tính, hàm thành phần: Các khai báo này sẽ được bàn chi tiết trong

mục “Lập trình hướng đối tượng trong Java”.

4. Khai báo hàm main: Không phải tất cả các class trong Java đều chứa hàm main. Chỉ có

class được gọi thực thi đầu tiên mới cần chứa hàm main.

5. Khai báo các lớp khác: Thông thường 1 file chương trình Java chúng ta chỉ khai báo 1

class. Tuy nhiên khi class đó quá phức tạp chúng ta có thể tách ra thành các class khác.

Trong số 5 phần trên, tất cả các class đều có phần 3, các phần còn lại có thể có hoặc

không tùy theo nhu cầu.

II. Các kiểu dữ liệu trong Java

II.1 Các kiểu dữ liệu số nguyên

Java có 4 kiểu số nguyên:

Page 30: Bai giang JAVA

30

int 4 bytes Từ –2,147,483,648 đến 2,147,483, 647

short 2 bytes Từ –32,768 đến 32,767

long 8 bytes Từ –9,223,372,036,854,775,808

đến9,223,372,036,854,775,807

byte 1 byte Từ –128 đến 127

II.2 Các kiểu số thực

Java có 2 kiểu số thực dấu chấm động:

float 4 bytes Xấp xỉ ±3.40282347E+38F

double 8 bytes Xấp xỉ ±1.79769313486231570E+308

Số dấu chấm động có thể nhận các giá trị:

Vô cực âm/dương.

Số âm/dương.

Số 0.

NaN (không là một số = 0.0/0.0f).

II.3 Kiểu ký tự (character)

Là kiểu dữ liệu về ký tự.

Một biến char sẽ có một giá trị là một ký tự Unicode.

II.4 Kiểu logic (boolean)

Là kiểu dữ liệu chỉ có hai giá trị true và false dùng để xác định kết quả một điều kiện.

Chú ý: kiểu boolean không được thể hiện là 0 và 1.

II.5 Kiểu chuỗi

Java xem chuỗi là một đối tượng.

Biến đối tượng chuỗi thường được khai báo từ lớp String nằm trong gói java.lang.String.

II.6 Chuyển đổi giữa các kiểu số

byte short int

long

double

float

char

Page 31: Bai giang JAVA

31

III. Khai báo biến và hằng trong Java

III.1 Quy tắc đặt tên biến

Khi khai báo các biến trong chương trình Java, ta cần chú ý tuân thủ các điểm sau:

Chỉ bắt đầu bằng một ký tự (chữ), một dấu gạch dưới (_) hay một dấu dollard ($).

Không có khoảng trống giữa tên.

Sau ký tự đầu, có thể dùng các ký tự (chữ), ký tự số, dấu dollard, dấu gạch dưới.

Không trùng với các từ khoá.

III.2 Khai báo biến

Các biến trong Java rơi vào hai trường hợp:

Toán học: Các biến có kiểu nguyên thủy của Java đều thuộc dạng này. Sau khi

khai báo, biến được cấp phát một vùng nhớ cố định tùy theo kích thước của kiểu

dữ liệu của biến đó.

Địa chỉ: Các biến đối tượng được lưu ở dạng này. Biến chỉ lưu giá trị địa chỉ đầu

của một vùng nhớ được cấp phát cho đối tượng.

Ví dụ khai báo cho từng kiểu biến toán học:

byte i;

short j;

int k;

long x;

float y;

double z;

char ch;

boolean bQuit;

Các biến địa chỉ thường sử dụng để lưu trữ các địa chỉ mảng, con trỏ, đối tượng.

Ví dụ về khai báo biến kiểu địa chỉ:

String strHello; //khai báo một chuỗi

AudioClip music; // ví dụ lớp của AudioClip

Khởi động giá trị cho biến

Ví dụ về khởi động biến ngay lúc khai báo:

byte i = 3;

short j = 10;

int k = 1;

long x = 1234567L;

float y = 1.25f;

double z = 23.45d;

char ch = „T‟;

boolean bQuit = true;

String strHello = “Hello everybody”;

Ở đây cần chú ý rằng khi khởi tạo giá trị cho các kiểu số nên xác định rõ kiểu dữ liệu của

giá trị.

Các giá trị mặc định

byte 0

short 0

int 0

Page 32: Bai giang JAVA

32

long 0L;

float 0.0f;

double 0.0d;

char null;

boolean false;

Các biến dẫn suất null

III.3 Biến kiểu mảng

Khi cần làm việc với một tập các giá trị có cùng kiểu dữ liệu, ta có thể sử dụng một biến

mảng để lưu trữ chúng.

Khai báo:

Một biến mảng được khai báo theo hai cách:

Sử dụng cặp ngoặc vuông đặt sau tên biến.

Sử dụng cặp ngoặc vuông đặt sau kiểu dữ liệu.

Ví dụ:

int [] intArray; hoặc int intArray[]; đều cho ta một mảng số nguyên có tên la intArray.

Thông thường ta dùng kiểu khai báo thứ nhất để có thể khai báo nhiều biến mảng cùng

kiểu dữ liệu:

int [] intArray1, intArray2, intArray3;

Định vị mảng

Sau khi khai báo, bản thân mảng chưa xác định hay chưa được định vị vì chưa được cấp

phát vùng nhớ . Do đó, mảng cần được cấp phát vùng nhớ trước khi sử dụng.

Dùng từ khoá new để định vị cho một mảng trong vùng nhớ, ví dụ:

int IntArray[] = new int[100];//tạo mảng 100pt

float floatArray[];

floatArray = new float[10]; //tạo mảng 10 pt

Khởi tạo giá trị cho mảng

Ta cũng có thể khởi tạo một mảng bằng cách liệt kê các phần tử của nó, ví dụ:

int IntArray[] = {1, 2, 3, 4, 5};

char [] charArray = {„a‟, „b‟, „c‟};

IntArray[] = new int[] {1, 2, 3, 4, 5};

Truy cập các phần tử của mảng

Các phần tử trong một mảng luôn được đánh số bắt đầu từ số 0. Kiểu dữ liệu của chỉ số là

kiểu int. Tuy nhiên nếu dùng kiểu char thì Java sẽ tự động chuyển sang mã ASCII tương ứng. Ví

dụ b[„a‟] tương ứng với b[97].

Phần tử đầu tiên là phần tử thứ 0, và phần tử cuối cùng của một mảng có n phần tử là n-1.

Các phần tử của mảng được truy cập một cách trực tiếp bằng chỉ số của nó.

Ví dụ:

int IntArray[] = {1, 2, 3, 4, 5};

int a = IntArray[2];//a=3

int b = IntArray[0];//b=1

Ta có thể gán các giá trị của mảng thông qua truy nhập vào từng phần tử của mảng.

Ví dụ:

int intList[] = new int[10]; //tạo mảng 10pt

intList[0] = 99; //Phần tử thứ 0 (đầu tiên) có giá trị là 99.

for (sort i=1; i<10; i++)

Page 33: Bai giang JAVA

33

intList[i] = 1; //các phần tử còn lại bằng 1

Ví dụ:

int x, y, k;

x = intList[0]; //x=99

y = intList[5]; //y=1

k = intList[y+1]; //k=intList[6]=1

Mảng nhiều chiều:

Khai báo mảng 2 chiều:

<kiểu phần tử>[][] <tên mảng> = {<danh sách phần tử>};

Ví dụ: int[][] b = {{1,2},{3,4}};

Đây là khai báo và khởi tạo giá trị cho một mạng 2 chiều kích thước 2 x 2. {1,2} là các

phần tử của hàng 1; {3,4} là các phần tử trên hàng thứ 2.

Hoặc ta có thể khai báo rõ số hàng và số cột của mảng:

int b[][] = new int[ 3 ][ 4 ];

Thậm chí ta có thể khai báo một mảng 3 chiều hoặc hơn.

int b[][][] = {{{1,2},{3,4}},{{5,6},{7,8}}};

Ta được b[0][0][0] =1; b[0][0][1]=2;b[1][1][1]=8;b[0][1][0]=3;

III.4 Hằng số (literal)

Là một giá trị không đổi được sử dụng trong chương trình. Hằng số được biểu diễn như

chính nó chứ không là một giá trị của biến hay một kết quả của biểu thức. Giá trị của hằng số

không thể bị thay đổi.

Ví dụ: Pi = 3.1415.

Tên của hằng số được đặt tên như tên biến. Cách khai báo hằng cũng tương tự như biến

nhưng có dùng thêm từ khóa final:

<phạm vi> final <kiểu dữ liệu của hằng> <tên hằng> = <giá trị>

Ví dụ: public final String mauda ="vang";

Hằng số có thể là:

Hằng số nguyên:

Hằng có thể được biểu diễn dưới dạng thập phân, bát phân, thập lục phân.

Ví dụ: biểu diễn số 15

dạng int: 15.

dạng long: 15L.

dạng bát phân: 017.

dạng thập lục phân: 0xF.

Hằng số thực:

Tương tự như hằng số nguyên, để chỉ rõ hằng là float ta thêm vĩ ngữ “ f ” hay “F”, hằng là

double ta thêm “d” hay “D”.

Hằng Boolean:

Một hằng số kiểu boolean có giá trị là true hoặc false. Trong Java, các giá trị 0 và 1

không được dùng thay thế cho false và true như trong C hoặc C++.

Hằng ký tự:

Là một ký tự đơn giản hay một chuỗi ESCAPE, hằng ký tự được đặt trong hai dấu ngoặc

đơn „‟. Các chuỗi ESCAPE:

„\b‟ : Xoá lùi.

„\n‟ : Xuống dòng.

„\t‟ : Tab ngang.

Page 34: Bai giang JAVA

34

„\f‟ : đẩy trang.

„\r‟ : dấu enter.

„\”‟ : nháy kép.

„\’‟ : nháy đơn.

„\\‟ : sổ ngược.

„uxxxx‟: ký tự unicode.

Ví dụ:

System.out.println(“Xin chào bạn \n Nguyễn Văn A”);

Sẽ in ra màn hình kết quả:

Xin chào bạn

Nguyễn Văn A

Hằng chuỗi ký tự:

Một hằng chuỗi ký tự có thể có 0 ký tự (hằng chuỗi rỗng) hay nhiều ký tự.

Ví dụ: “A String”, “” //chuỗi rỗng, “dong 1 \t\n dong 2”.

III.5 Phạm vi hoạt động của hằng và biến:

Khối lệnh Block 1 chứa 2 khối lệnh con Block 2, Block 3.

Biến hay hằng sẽ chỉ có ý nghĩa trong phạm vi khối lệnh mà nó được khai báo.

IV. Các toán tử và biểu thức

IV.1 Các toán tử và thứ tự ưu tiên

Các toán tử thường sử dụng:

Toán tử Ý nghĩa Ví dụ

= Gán x=10

!= so sánh khác x!=5

> so sánh lớn hơn x>5

< so sánh nhỏ hơn x<20

>= lớn hơn hoặc bằng x>=10

<= nhỏ hơn hoặc bằng x<=10

+ cộng y=x+1

- trừ y=x-1

* Nhân y=x*3

/ Chia y=x/3

{ Block 1

}

{ Block 2

}

{ Block 3

}

Page 35: Bai giang JAVA

35

% Lấy phần dư 10%3 = 1

++ tăng giá trị lên 1 x++

-- giảm giá trị đi 1 x--

+= cộng kết hợp phép gán x+=y tương đương x=x+y

-= trừ kết hợp phép gán x-=y tương đương x=x-y

*= nhân kết hợp phép gán x*=y tương đương x=x*y

/= chia kết hợp phép gán x/=y tương đương x=x/y

^ phép XOR trên bit x ^ y

| phép OR trên bit x | y

& phép và trên bit

! Toán tử logic NOT

&& Toán tử logic AND

|| Toán tử logic OR

= = So sánh bằng nhau

Thứ tự ưu tiên:

( ), *, /, %, +, -,= =, !=, &, ^, |, &&, ||, =, %=, /=, *=, -=, +=

IV.2 Biểu thức

Biểu thức là sự kết hợp các biến số, các giá trị bởi các toán tử hoặc có thể là một phép gán

giá trị một biểu thức cho một biến số.

Ví dụ: (x+3)/(y-2);

Có 3 loại biểu thức chính là:

Biểu thức số liên kết các biến số, các hằng bằng các phép toán số, kết quả là một

giá trị số.

Biểu thức gán dùng để gán giá trị cho một biến, một hằng.

Biểu thức logic chỉ cho ra kết quả là các giá trị true hay false.

Khi sử dụng câu lệnh gán kết quả của một biểu thức cho một biến, ta cần chú ý tới vấn đề

đồng nhất kiểu dữ liệu giữa hai vế để tránh mất thông tin. Ví dụ:

Double delta = 0.0d; //khai báo một biến số thực có tên delta

delta = 1/ 100; // Gán cho delta kết quả của phép chia 1 cho 100.

Trong tình huống này, ta không thu được delta = 0.01 như mong đợi mà là delta =0. Lý do

là các số 1 và 100 đều được hiểu là các số nguyên và kết quả của phép chia được tự động làm

tròn thành một giá trị nguyên trước khi gán cho delta. Để khắc phục tình trạng này, ta cần xác

định rõ các số 1 và 100 là các số double.

delta = 1d/100d;

V. Các lệnh điều khiển rẽ nhánh

V.1 Lệnh if

Lệnh if...{...}: là một phép kiểm tra giá trị của một biểu thức boolean, nếu cho giá trị là

true thì khối lệnh sẽ được thực hiện.

Cấu trúc:

if <biểu thức boolean>

{

<khối lệnh>;

Page 36: Bai giang JAVA

36

}

Nếu biểu thức boolean đúng, khối lệnh sẽ được thực hiện, còn nếu biểu thức đó sai thì

khối lệnh sẽ bị bỏ qua.

Ví dụ:

public class dkIfThen {

public static void main(String[] args) {

int x=1;

int y=x+1;

if (x<y) {

System.out.println("x>y");

} }}

Dạng 2 của câu lệnh if:

if <biểu thức boolean>

{

<khối lệnh 1>;

}

else

{

<khối lệnh 2>;

}

Nếu biểu thức boolean đúng thì <khối lệnh 1> được thực hiện, còn nếu biểu thức boolean

sai thì <khối lệnh 2> được thực hiện.

Ví dụ:

public class dkIfThen {

public static void main(String[] args) {

int x=1;

int y=x-1;

if (x<y) {

System.out.println("x>y");

} else {

System.out.println("x<y");

}}}

V.2. Lệnh switch …case

Lệnh switch ... case ...: Cho phép chọn nhiều trường hợp xảy ra của giá trị so sánh.

Cấu trúc:

switch <biểu thức>{

case <giá trị 1>: <khối lệnh 1>; break;

case <giá trị 2>: <khối lệnh 2>; break;

...

case <giá trị n>: <khối lệnh n>; break;

default: <khối lệnh default>; break;

}

Một số chú ý khi sử dụng lệnh switch-case:

Các giá trị: <giá trị 1>, <giá trị 2>,…<giá trị n> phải là các hằng số.

Page 37: Bai giang JAVA

37

Nếu không sử dụng lệnh break mỗi khi kết thúc các khối lệnh thì sau khi thực hiện xong

khối lệnh, các lệnh tiếp theo sẽ được thực hiện.

VI. Các lệnh lặp

VI.1. Vòng lặp for

Khi muốn một khối lệnh được thực hiện với một số lần biết trước, ta có thể sử dụng một

vòng lặp for.

Cấu trúc lệnh:

for([<khởi tạo>]; [<biểu thức kiểm tra>]; [<bước nhảy>])

{

<Khối lệnh>;

}

Bắt đầu với giá trị <khởi tạo> của biến đếm, <khối lệnh> được thực hiện. Sau mỗi lần

thực hiện xong <khối lệnh>, biến đếm thay đổi giá trị một lượng bằng <bước nhảy> và <biểu

thức kiểm tra> được tính lại. Nếu biểu thức kiểm tra là true thì lại thực hiện khối lệnh, còn nếu là

false, vòng lặp chấm dứt.

Lưu đồ hoạt động của vòng lặp for như sau:

Ví dụ: tính tổng 1 dãy số thực

public class vdFor {

public static void main(String[] args) {

double accounts[]={1.2,1.4,1.6};

double sum=0;

for (int i=0;i<accounts.length;i++){

sum+=accounts[i];

}

System.out.println(sum);

}

Biểu thức kiểm tra

Thực hiện khối lệnh

Kết thúc vòng for

Biểu thức điều chỉnh theo bước nhảy

Biểu thức biến điều khiển

false

true

Page 38: Bai giang JAVA

38

}//kết quả là: 4.2

Các vòng for có thể được đặt lồng nhau nếu cần

Ví dụ:

for(int i=0; i<10; i++) {

[các câu lệnh; ]

for(int j=0; j<5; j++) {

[các câu lệnh; ]

...

}

[các câu lệnh; ]

}

VI.2. Vòng lặp while

Khi một khối lệnh cần được thực hiện, thường là với một số lần không được biết trước, ta

có thể sử dụng vòng lặp while.

Cấu trúc lệnh:

while <bt boolean> {

<Khối lệnh>;

}

Khối lệnh được thực hiện khi <bt boolean> còn có giá trị true.

Chú ý: trong khối lệnh phải có câu lệnh có tác dụng ảnh hưởng tới kết quả <bt boolean>

để vòng lặp có thể dừng.

Lưu đồ thực hiện:

VI.3. Vòng lặp do... while

Vòng lặp này có ý nghĩa tương tự như vòng lặp while nhưng <khối lệnh> được thực hiện

ngay ở vòng đầu tiên mà chưa cần kiểm tra kết quả <biểu thức boolean>.

Bt boolean

Các câu lệnh

Câu lệnh tiếp theo

false

true

Page 39: Bai giang JAVA

39

Cấu trúc lệnh:

do {

<khối lệnh>;

} while <biểu thức boolean>;

Vòng lặp này cho thực hiện <khối lệnh> rồi mới kiểm tra <biểu thức boolean>. Nếu <biểu

thức boolean> có giá trị true thì tiếp tục thực hiện <khối lệnh>, nếu không sẽ dừng vòng lặp.

Ví dụ tính tổng 10 số đầu tiên:

public class vdDoWhile {

public static void main(String[] args) {

int x=1, sum=0;

do{

sum+=x;

x++;

}

while (x<11);

System.out.println(sum);

}

} //kết quả là: 55

VI.4. Phép nhảy

Trong một số trường hợp, việc thực hiện các vòng lặp đôi khi không theo hết vòng mà có

thể dừng hoặc thoát khỏi vòng lặp.

Ví dụ: Tìm một giá trị nào đó trong một dãy 1000 phần tử. Khi thực hiện vòng lặp duyệt

dãy, so sánh các phần tử của dãy với giá trị cần tìm từ phần tử đầu tiên cho đến phần tử cuối

cùng, nếu tìm thấy phải thôi duyệt dãy ngay.

Việc nhảy ra khỏi vòng lặp được thực hiện với từ khoá break hoặc kết thúc vòng hiện tại

với lệnh continue.

Lệnh break

Lệnh này kết thúc ngay vòng lặp trong cùng (nếu có nhiều vòng lồng nhau) chứa nó.

Ví dụ:

while <bt boolean 1>{

lệnh 1;

lệnh 2;

if <bt boolean 2>

break;

lệnh 3;

}

lệnh 4;

Lệnh continue

Cho phép chương trình bỏ qua vòng hiện tại và nhảy đến vòng tiếp theo.

Ví dụ:

while <bt boolean 1>{

lệnh 1;

lệnh 2;

if <bt boolean 2>

Page 40: Bai giang JAVA

40

{

……..

continue;

}

lệnh 3;

}

lệnh 4;

Khi <bt boolean 2> có giá trị true, lệnh continue được thực hiện, chương trình sẽ không

thực hiện tiếp <lệnh 3> mà quay lại kiểm tra <bt boolean 1>.

VII. Vào dữ liệu từ bàn phím và xuất dữ liệu ra màn hình

VII.1. Lấy giá trị nhập vào từ bàn phím

Để lấy giá trị mà người sử dụng nhập từ bàn phím, ta làm theo các bước sau:

1. Khai báo biến thuộc lớp Scanner”. Lớp Scanner chỉ được hỗ trợ từ phiên bản Java 1.5

và nằm trong gói java.util.

// Khai báo một biến Scanner có tên là “nhap”.

Java.util.Scanner nhap = new java.util.Scanner(System.in);

2. Lấy giá trị nhập vào:

System.out.print("What is your name? "); // In ra màn hình một câu hỏi tên

/* Khai báo và gán giá trị nhập từ bàn phím cho một biến kiểu String có tên name.*/

String name = nhap.nextLine();

Để đọc 1 từ trong chuỗi nhập vào: String firstName = nhap.next();

Nếu đọc vào một số nguyên: int Tuoi = nhap.nextInt();

Tương tự cho các kiểu dữ liệu khác.

Ví dụ:

import java.util.*;

public class InputTest

{

public static void main(String[] args)

{

Scanner nhap = new Scanner(System.in);

// Lay gia trị nhap ho ten

System.out.print("What is your name? ");

String name = nhap.nextLine();

// Lay gia tri nhap tiep theo

System.out.print("How old are you? ");

int age = nhap.nextInt();

// Hien thi ket qua nhap tren man hinh

System.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1));

}

}

Page 41: Bai giang JAVA

41

VII.2 Kết xuất dữ liệu ra màn hình

Trong các chương trình ví dụ trên, ta đã biết dùng hàm System.out.print để in dữ liệu ra

màn hình. Tuy nhiên, trong một số trường hợp ta cần định dạng dữ liệu xuất ra chẳng hạn như

hiển thị một số thực dạng thập phân với độ chính xác nhất định.

System.out.printf(“%8.1f”, 10/3);

System.out.printf(“Hello, %s. You have %f VND ”, name,money);

Sau đây là bảng các ký tự định dạng:

Ký tự định dạng Định dạng Ví dụ

D Số nguyên thập phân 159

X Số nguyên hệ 16 9f

O Số nguyên hệ 8 237

F Số thực float 15.9

E Số thực float theo ký pháp cơ số e 1.59e+01

A Số thực float dạng Hexa 0x1.fccdp3

S String Hello

C Ký tự H

B Boolean True

H Hash code 42628b2

tx Date and time

% Ký hiệu phần trăm %

N Xuống dòng

Sau đây là ví dụ sử dụng các ký tự định dạng khi xuất dữ liệu ra màn hình.

public class TestFormat

{

public static void main(String[] argvs)

{

double sothuc = 10.09898765;

/*In ra số thực chiếm 10 ký tự trên màn hình trong đó phần thập phân chiếm 3 ký tự*/

System.out.printf("Ket qua 3 so sau dau phay la %10.3f \n",sothuc);

int songuyen =100;

/*In ra số nguyên ở hệ cơ số 16*/

System.out.printf("He 16 cua 100 duoc viet la: %x \n",songuyen);

/*In ra số nguyên ở hệ cơ số 8*/

System.out.printf("He 8 cua 100 duoc viet la: %o \n",songuyen);

/*In ra ký tự đặc biệt “” */

System.out.print("\"Mot tram phan tram\" thi in ra the nao: 100%");

}}

Page 42: Bai giang JAVA

42

Lưu ý rằng khi sử dụng các ký tự định dạng ta cần dùng hàm System.out.printf() thay vì

System.out.print() hay System.out.println() như thường lệ.

Bài tập

1. Viết chương trình tính giá trị các biểu thức (Giá trị n, k,…nhập từ bàn phím):

A = 1 + 1/2! + 1/3! + … + 1/n!

B = 1/1! – 1/2! + 1/3! - 1/4! + … + 1/(2k+1)! - ….

2. Viết chương trình đếm số từ có trong một chuỗi ký tự nhập vào. Các từ cách nhau bởi

dấu space,. và ;

3. Viết chương trình đếm tần suất xuất hiện của các từ trong một chuỗi nhập từ bàn phím.

4. Nhập vào một chuỗi họ tên của một người, hãy sửa lại các ký tự đầu các từ cho đúng

quy định viết hoa và khoảng cách giữa các từ. Ví dụ: nguyen van nam -> Nguyen Van Nam

5. Tìm các lỗi trong các đoạn chương trình sau:

a)

For ( x = 100, x >= 1, x++ )

System.out.println( x );

b) Đoạn mã sau sẽ in ra các giá trị chẵn hay lẻ:

switch ( value % 2 ) {

case 0:

System.out.println( "Even integer" );

case 1:

System.out.println( "Odd integer" );

}

c) Đoạn mã sau sẽ in ra các số nguyên lẻ từ 19 đến 1 ?:

for ( x = 19; x >= 1; x += 2 )

System.out.println( x );

d) Đoạn mã sau sẽ in ra các số nguyên chẵn từ 2 đến 100 ?:

counter = 2;

do {

System.out.println( counter );

counter += 2;

} While ( counter < 100 );

6. Đoạn chương trình sau làm gì?

public class Printing {

public static void main( String args[] )

{

for ( int i = 1; i <= 10; i++ ) {

for ( int j = 1; j <= 5; j++ )

System.out.print( '@' );

System.out.println();

}

}

}

7. Viết chương trình tìm số nhỏ nhất trong số các số được nhập vào từ bàn phím. Cho biết

số nguyên đầu tiên nhập vào sẽ chính là số các con số được nhập.

Page 43: Bai giang JAVA

43

8. Viết chương trình in ra màn hình các mẫu như sau:

9. Tính số PI theo công thức sau:

In ra 10 giá trị chính xác hơn 3.141.

Page 44: Bai giang JAVA

44

Đề tài 3. Lập trình hướng đối tượng trong Java

I. Khái niệm lập trình hướng đối tượng (Object-Oriented Programming - OOP)

I.1. Khái niệm OOP

Lập trình hướng đối tượng là sự cài đặt một chương trình theo hướng đối tượng bằng các

ngôn ngữ lập trình, thường là ngôn ngữ OOP.

Như vậy, nếu dùng một ngôn ngữ OOP mà chương trình không theo hướng đối tượng thì

cũng không phải là lập trình OOP. Trong khi nếu dùng một ngôn ngữ không hướng đối tượng để

viết một chương trình OOP (rất khó khăn) thì cũng có thể gọi là lập trình OOP. Thực tế thì ta

không thể viết chương trình hướng đối tượng bằng các ngôn ngữ cấu trúc (như Pascal chẳng hạn)

vì các ngôn ngữ này không hỗ trợ cú pháp cài đặt và kỹ thuật biên dịch các đặc tính của hướng

đối tượng.

Những ngôn ngữ OOP không chỉ bao gồm cú pháp và một trình biên dịch (compiler) mà

còn có một môi trường phát triển toàn diện. Môi trường này bao gồm một thư viện được thiết kế

tốt, thuận lợi cho việc sử dụng kế thừa các đối tượng – tính tái sử dụng. Đây là một điểm mạnh

của OOP và phương pháp trước đây không có được.

Đối với một ngôn ngữ lập trình hỗ trợ OOP thì việc triển khai kỹ thuật lập trình hướng đối

tượng sẽ dễ dàng hơn. Hơn nữa, các dự án phần mềm phân tích và thiết kế theo UML bắt buộc

phải sử dụng kỹ thuật OOP để cài đặt thì mới phát huy hiệu quả.

I.2 Cơ sở lý luận của OOP

Chúng ta thấy rằng thuật ngữ “hướng đối tượng” có nghĩa là lấy đối tượng làm trung tâm

và tất cả nằm trong đối tượng. Quan sát thế giới thực, ta thấy mọi vật đều có vị trí riêng của nó,

chúng sở hữu các tính chất và thuộc tính riêng, cách thức vận động riêng. Chúng ta gọi chúng là

những đối tượng. Theo cách hiểu như vậy thì mọi nghiệp vụ thực tế suy cho cùng chỉ là việc quản

lý các đối tượng, khai thác thông tin cũng như các mối quan hệ từ chúng hoặc thay đổi trạng thái

của chúng.

OOP là phương thức tư duy mới để giải quyết vấn đề bằng máy tính. Để đạt kết quả, lập

trình viên phải nắm được sự tương ứng giữa các các đối tượng thực tế, mối quan hệ giữa chúng

và sự hỗ trợ của ngôn ngữ để cài đặt chúng vào máy tính. Ngôn ngữ OOP cung cấp đầy đủ

phương tiện để thực hiện điều này. Chúng ta sử dụng kỹ thuật hướng đối tượng để ánh xạ những

thực thể chúng ta gặp phải trong đời sống thực thành những thực thể tương tự trong máy tính. Do

đó, phát triển phần mềm theo kỹ thuật lập trình hướng đối tượng có khả năng giảm thiểu sự lẫn

lộn thường xảy ra giữa hệ thống và lĩnh vực ứng dụng.

Tuy nhiên, từ nghiệp vụ thực tế chúng ta không thể ngay lập tức đem vào cài đặt trong

ngôn ngữ OOP mà phải qua một quy trình phân tích và thiết kế theo hướng đối tượng như chúng

ta đã thấy qua việc nghiên cứu ngôn ngữ mô hình hóa UML – một ngôn ngữ giúp chúng ta trừu

tượng hóa thế giới thực.

I.3 Trừu tượng hóa

Quản lý thông tin, các hành vi, các mối quan hệ của các đối tượng là nhiệm vụ mà lập

trình OOP phải làm. Thông tin về đối tượng và mối quan hệ giữa chúng thực tế là vô cùng. Vậy

làm thế nào để đưa chúng vào máy tính? Câu trả lời là chúng ta cần một quá trình trừu tượng hóa.

Page 45: Bai giang JAVA

45

Giả sử đối tượng quản lý là một sinh viên. Một hệ thống quản lý sinh viên có thể chỉ cần

quan tâm tới: Họ và tên, ngày sinh, lớp học, địa chỉ nơi ở, điểm các môn học. Trong khi đó, các

thông tin khác về sinh viên – cũng là một con người – như chiều cao, cân nặng, nhóm

máu,…chúng ta không cần quan tâm. Một quá trình suy luận như vậy là một quá trình trừu tượng

hóa dữ liệu. Ở đây ta không quan tâm tới giá trị cụ thể của các thuộc tính này.

Khi quan tâm tới giá trị của các thuộc tính, chúng ta có một câu hỏi: Cái gì làm cho dữ

liệu này biến đối? Câu trả lời là chính hành vi của đối tượng làm cho thuộc tính của chúng bị thay

đổi. Trong ví dụ trên, một anh sinh viên bất kỳ có thể có hành vi “xin đổi lớp học” hoặc “đổi địa

chỉ nơi ở” làm cho giá trị các thuộc tính “lớp học”, “địa chỉ nơi ở” bị thay đổi. Quá trình xác định

các hành vi của đối tượng phục vụ cho nghiệp vụ quản lý cũng là một quá trình trừu tượng hóa

hành vi.

Tóm lại, chúng ta có một mô hình trừu tượng hóa của một sinh viên:

Sinh viên

Họ và tên

Ngày sinh

Tên lớp

Địa chỉ

Điểm môn học

Thay đổi lớp

Thay đổi nơi ở

Điểm quan trọng là sau khi trừu tượng hóa từ một lớp các sinh viên (tất cả các sinh viên

trong phạm vi quản lý), mô hình này đại diện cho tất cả sinh viên và là khuôn mẫu để tạo ra bất

kỳ sinh viên nào khác.

Qua đây, ta cũng rút ra nhận xét rằng quá trình trừu tượng hóa tùy theo yêu cầu nghiệp vụ

sẽ cho kết quả khác nhau. Cũng là một sinh viên nhưng nếu chẳng may anh ta bị ốm nằm viện,

anh ta được quản lý như một bệnh nhân. Một hệ thống quản lý bệnh nhân tất nhiên không thể bỏ

qua các thông tin về nhóm máu, cân nặng, huyết áp,…và tất nhiên là cũng có các mô hình hành vi

khác.

Tóm lại:

Các thực thể tồn tại trong thế giới thực được mô hình hóa thành các lớp đối tượng.

Các mối quan hệ giữa các thực thể trong thế giới thực được mô hình hóa bằng các mối

quan hệ giữa các lớp đối tượng.

Thế giới thực = Các đối

tượng + Các mối quan hệ

Các lớp đối tượng trong

chương trình - Classes

Trừu tượng hóa

Page 46: Bai giang JAVA

46

II. Tính đóng gói trong Java

II.1 Khái niệm tính đóng gói

Tính đóng gói thể hiện bởi việc thuộc tính mô tả đối tượng và hành vi của đối tượng được

gắn chặt với nhau. Thuộc tính thể hiện trạng thái đối tượng, hành vi làm thay đổi trạng thái đối

tượng thông qua việc thay đổi giá trị các thuộc tính.

Thuộc tính được cài đặt thông qua mã lệnh Java bằng các biến thành phần trong lớp.

Hành vi được cài đặt thông qua mã lệnh Java bởi các phương thức.

Thông tin và hành vi đối tượng được bảo vệ bằng các cấp độ truy cập: public, private. Cấp

độ public cho phép sự truy cập từ bên ngoài lớp trong khi private chỉ cho phép nội bộ lớp truy

cập.

Đối tượng được sinh ra bởi class - một sự mô hình hóa một lớp đối tượng trong thực tế.

object = attributes (các thuộc tính) + operations(các hành vi) + name (tên định danh)

Như vậy tính đóng gói thể hiện việc chuyển mô hình đối tượng thực tế thành các lớp trong

Java.

II.2 Mối quan hệ giữa các class

Các class trong chương trình có thể quan hệ với nhau theo 1 trong 3 dạng:

Phụ thuộc (Dependence): Class A có quan hệ phụ thuộc với class B nếu phương

thức của class A có sử dụng đối tượng thuộc class B.

Bao gồm (Aggregation): Class A có quan hệ bao gồm với class B nếu đối tượng

của class A chứa đối tượng của class B.

Thừa kế (inheritance): Class B gọi là thừa kế class A nếu class B có các phương

thức và thuộc tính của class A, ngoài ra class B còn định nghĩa các phương thức

và thuộc tính khác của riêng nó.

Ví dụ:

Trong hệ thống bán hàng chúng ta có:

class DanhMucMatHang

class TaiKhoan

class HoaDon

class HoaDonThanhToanNhanh

Mỗi HoaDon bao gồm 1 DanhMucMatHang: Quan hệ aggregation.

Khi một HoaDon được tạo ra, nó cần truy cập đến class TaiKhoan để kiểm tra tình trạng

thẻ tín dụng: Quan hệ dependence.

Mỗi HoaDonThanhToanNhanh thừa kế các thuộc tính và phương thức của HoaDon và có

thêm các thuộc tính, phương thức khác: Quan hệ inheritance.

II.3 Một số gợi ý khi thiết kế class

Khai báo dữ liệu private: Điều này tránh việc truy cập tùy ý từ bên ngoài lớp

Khởi tạo cho dữ liệu: Các thuộc tính nên được khởi tạo bằng các phương thức constructor

khi một đối tượng mới được tạo ra.

Không sử dụng quá nhiều kiểu dữ liệu cơ bản trong 1 lớp

Không phải thuộc tính nào cũng cần mutator và accesor: Mỗi thuộc tính bao giờ cũng có

một phương thức thiết đặt giá trị cho nó gọi là mutator (tiền tố set) và một phương thức lấy ra giá

trị của nó gọi là accesor (tiền tố get).

Tách các class phức tạp

Page 47: Bai giang JAVA

47

Đặt tên phương thức và thuộc tính phản ánh theo tính chất và nghiệp vụ của nó.

IV. Sử dụng các Class xây dựng sẵn trong thư viện

Java hỗ trợ cho lập trình viên một thư viện phong phú các lớp đối tượng đã được xây

dựng và thiết kế cẩn thận. Lập trình viên chỉ cần biết cách lấy chúng ra và sử dụng chúng theo

kịch bản của ứng dụng.

Các gói thư viện quan trọng của Java 2 bao gồm:

(tham khảo chi tiết tại: http://java.sun.com/j2se/1.4.2/docs/api/overview-summary.html )

Các gói thường dùng trong Java 2 SE

java.applet Hỗ trợ các class cần thiết cho việc tạo ra các Applet và giao tiếp giữa

Applet với môi trường ngữ cảnh của nó.

java.awt Chứa các lớp dùng để tạo ra các giao diện người dùng và cho các thao tác

vẽ các hình đồ họa và ảnh.

java.awt.color Cung cấp các lớp cho không gian màu.

java.awt.event Cung cấp các giao diện và các lớp cho việc giải quyết các vấn đề về xử lý

các sự kiện trên các thành phần giao diện AWT.

java.awt.font Hỗ trợ các giao diện và lớp liên quan đến font chữ.

java.awt.image Cung cấp các lớp tạo và hiệu chỉnh hình ảnh.

java.awt.print Cung cấp các lớp và giao diện cho mục đích in ấn.

java.beans Chứa các lớp liên quan tới việc phát triển các thành phần (beans) dựa trên

kiến trúc của Java.

java.io Hỗ trợ cho các thao tác vào / ra dữ liệu trên hệ thống file.

java.lang Cung cấp các lớp nền tảng để thiết kế ngôn ngữ lập trình Java.

java.math Hỗ trợ các lớp để thao tác và thuật toán với các số nguyên lớn BigInteger và

BigDecimal.

java.net Cung cấp các lớp cho việc cài đặt các ứng dụng mạng.

java.rmi Cung cấp các gói cho lập trình RMI – Remote Method Invocation.

java.security Cung cấp các lớp và giao diện cho việc xử lý các vấn đề an ninh và bảo mật

trong Java.

java.sql Cung cấp các hàm API cho việc truy cập vào dữ liệu trong một nguồn dữ

liệu – thường là các CSDL quan hệ.

java.text Cung cấp các lớp và giao diện cho việc quản lý text, dates, numbers và các

thông điệp.

java.util Chứa đựng các lớp tiện ích thuộc nhiều loại khác nhau như sinh số ngẫu

nhiên, ngày tháng,….

javax.crypto Hỗ trợ các lớp và giao diện cho các thao tác mã hóa dữ liệu.

javax.net Cung cấp các lớp cho lập trình mạng.

javax.print Cung cấp các lớp cơ bản cho các dịch vụ in ấn qua mạng.

Page 48: Bai giang JAVA

48

javax.sql Cung cấp các hàm API cho việc truy cập dữ liệu phía server.

javax.swing Cung cấp một tập các thành phần được chấp nhận trên hầu hết các hệ thống

máy tính.

javax.swing.event Hỗ trợ cho các sự kiện kích hoạt bởi các thành phần của Swing.

javax.swing.table Cung cấp các lớp và giao diện làm việc với bảng.

javax.swing.tree Cung cấp các lớp và giao diện làm việc với cây javax.swing.JTree.

javax.xml.parsers Hỗ trợ các lớp cho việc xử lý các tài liệu XML.

Sau đây là hướng dẫn ví dụ về sử dụng lớp Date có sẵn trong thư viện của Java:

Khai báo biến đối tượng với toán tử new

Date myDate = new Date();

Date() là phương thức contructor của class Date. Một đối tượng luôn được tạo ra từ

một constructor của lớp đó.

Khai báo:

Date myDate;

Xác định cho ta một biến đối tượng Date nhưng không cho ta một đối tượng Date thực

sự vì trong thực tế, myDate chưa được cấp phát vùng nhớ.

Câu lệnh:

myDate = new Date();

Xác định rằng myDate là một đối tượng thực sự thuộc class Date, ta có thể áp dụng các

phương thức và thuộc tính của class Date cho myDate.

System.out.println(myDate.getMonth()); // In ra tháng hiện tại

V. Xây dựng Class trong Java

Cài đặt các class là công việc thường xuyên của lập trình viên Java. Các vấn đề của công

việc thiết kế một lớp bằng ngôn ngữ Java sẽ được đề cập dưới đây.

V.1 Cấu trúc của class

[<Cách truy xuất>] class <tên lớp> [extends <tên lớp cha>] [implements <tên giao

diện>]{

<các thành phần của lớp>;

}

Ta sẽ lần lượt xem xét từng thành phần:

<Cách truy xuất>:

public: Có thể truy cập lớp từ các lớp khác.

abstract: Lớp trừu tượng, không được khởi tạo đối tượng của lớp này. Các lớp trừu tượng

được thiết kế chỉ cho mục đích kế thừa.

final: Không cho phép kế thừa.

Nếu <cách truy xuất> không được xác định, mặc định là public.

<tên lớp>: Tên của lớp, nếu <cách truy xuất > là public thì tên lớp phải trùng với tên file

chứa lớp.

<tên lớp cha>: Tên của lớp cha mà lớp hiện tại thừa kế.

Page 49: Bai giang JAVA

49

<tên giao diện>: Tên của giao diện được cài đặt tại lớp. Đây có thể là một danh sách các

giao diện phân tách bởi dấu “,”.

<các thành phần của lớp>: đây là phần thân của lớp chứa các định nghĩa cho các thuộc

tính và các phương thức thành phần. Ta sẽ lần lượt xem xét tới các thành phần này.

V.2 Các thuộc tính thành phần:

Khai báo thuộc tính chính là việc khai báo các biến. Khi khai báo trong lớp chúng thường

được xác định phạm vi hoạt động là một trong các dạng:

public: Biến có thể truy cập ở bất cứ lớp nào.

private: Chỉ được truy cập trong chính lớp đó.

protected: Chỉ được truy cập trong lớp đó và các lớp kế thừa.

Mặc định thì phạm vi truy cập của biến là public, các biến thông thường có phạm vi

private.

Ví dụ:

public int Tuoi;

private String HoVaTen;

Cách truy cập biến rất đơn giản, phụ thuộc vào biến thuộc dạng nào trong 2 dạng sau:

1. Biến có phạm vi đối tượng: Đây là biến tồn tại cùng với sự tồn tại của đối tượng. Muốn

truy cập vào biến, trước hết phải khởi tạo một đối tượng thuộc lớp.

SinhVien sv = new SinhVien(20,”Nguyen Van A”);

Truy cập vào biến Tuoi như sau: sv.Tuoi, ví dụ gán Tuoi của sinh viên này bằng 21:

Sv.Tuoi=21;

2. Biến có phạm vi lớp (biến tĩnh): Đây là biến có phạm vi tồn tại trong mọi đối tượng của

lớp được tạo ra trong chương trình đang chạy. Giá trị của biến được dùng chung giữa các đối

tượng.

Khi khai báo một biến có phạm vi lớp, ta cần thêm từ khóa static như ví dụ sau:

public static int MaSo;

Khi truy cập, ta có thể không cần khởi tạo đối tượng mà trực tiếp thông qua tên lớp:

SinhVien.MaSo = 10;

Các biến có phạm vi lớp rất ít khi được sử dụng, trong khi các hằng static lại rất hay được

dùng. Lý do là trong thực tế, các lớp đối tượng thường có các thuộc tính chung, cố định có ở mọi

đối tượng. Hơn nữa, khi chúng đã không phụ thuộc vào một đối tượng cụ thể nào thì ta cũng

không cần khởi tạo một đối tượng để truy cập. Do đó, ta sẽ cài đặt chúng như là các hằng static.

Ví dụ:

public static final String MauDa = “Vang”; // Mọi sinh viên đều có màu da là “Vang”

hoặc khái báo hằng số PI:

public static final double PI = 3.14159265358979323846;

Là hằng số của lớp Math. Khi truy cập ta chỉ cần gọi: Math.PI

Chú ý: Các biến rất ít khi được khai báo là public vì có thể thay đổi giá trị của nó bên

ngoài lớp nên khó quản lý. Trong khi đó các hằng thường luôn được khai báo là public vì chúng

được dùng chung và không thể bị thay đổi do từ khóa final (hằng).

Biến this

Biến this là biến đối tượng của lớp tồn tại ngầm trong mỗi lớp.

Thường dùng biến this để truy cập đến các thuộc tính của lớp bị khai báo trùng trong

phạm vi các phương thức của lớp.

Ví dụ:

Page 50: Bai giang JAVA

50

public class TestThis

{

private int number = 10;

public void PrintNumber()

{ int number =20; // khai báo trùng với biến của lớp

System.out.println(number); //in bien number = 20

System.out.println(this.number);//in bien number =10

}

}

V.3 Các phương thức thành phần

Phương thức thành phần là sự cài đặt các hành vi của đối tượng. Cú pháp khai báo một

phương thức trong lớp như sau:

[<Cách truy xuất> <cách cập nhật>] <Kiểu giá trị trả về> <Tên phương thức>([<danh

sách biến hình thức>]) [<mệnh đề throws>]

{

<Nội dung của phương thức>;

}

<Cách truy xuất>:

private: phương thức này chỉ được truy xuất bên trong lớp chứa nó.

public: có thể truy xuất từ bất kỳ lớp bên ngoài nào.

protected: chỉ các lớp là dẫn xuất của lớp chứa phương này mới truy xuất được nó.

Nếu không khai rõ cách truy xuất, các phương thức sẽ có cách truy xuất mặc định

là public.

Các phương thức khai báo chồng ở lớp dẫn xuất phải có mức độ truy cập mạnh hơn hoặc

giống với mức độ truy cập ở lớp cha.

< Cách cập nhật>

static: phương thức tác động không phụ thuộc vào các đối tượng cụ thể, nó có thể

được gọi mà không cần khởi tạo đối tượng của lớp.

abstract: phương thức đơn giản nhất, không cài đặt gì ở trong lớp khai báo nó, tức

là nó không có phần thân. Phương thức này sẽ được phát triển trong các lớp là dẫn

xuất của lớp chứa nó. Lớp có chứa phương thức abstract cũng phải được khai báo

abstract.

final: phương thức này được bảo vệ không cho các lớp dẫn xuất khai báo và cài

đặt lại.

native: là phương thức được viết bằng ngôn ngữ khác java.

synchronyzed: đảm bảo dữ liệu không bị sai lạc khi cùng một lúc 2 phương thức

truy cập cùng một dữ liệu.

<Kiểu giá trị trả về>:

integer, String, char, float, ...: là các kiểu dữ liệu mà phương thức trả về.

void: phương thức không trả về giá trị.

Khi xác định kiểu giá trị trả về, khi kết thúc các luồng xử lý trong phương thức nhất thiết

phải có câu lệnh return để trả về một giá trị thuộc kiểu đó.

public static int max(int num1, int num2)

{

if(num1>num2)

Page 51: Bai giang JAVA

51

return num1;

else

return num2;

}

Về <mệnh đề throws> chúng ta sẽ xem xét kỹ trong phần xử lý ngoại lệ.

V.4 Gọi và truyền tham số cho phương thức

Các tham số kiểu cơ bản được truyền theo kiểu tham trị.

Các tham số có kiểu đối tượng được truyền theo kiểu tham chiếu.

Các chú ý khi truyền tham số cho phương thức:

Các phương thức không thể làm thay đổi giá trị của các tham số có kiểu nguyên

thủy

Phương thức có thể làm thay đổi trạng thái của tham số kiểu đối tượng

Phương thức không thể làm cho tham số đối tượng tham chiếu tới một đối tượng

mới.

Gọi một phương thức:

Có 2 cách gọi phương thức:

Nếu phương thức trả về giá trị, việc gọi phương thức thường được xử lý như một giá trị.

Ví dụ: int larger = max(3, 5);

hoặc ta có thể in giá trị trả về của cuộc gọi phương thức: System.out.println(max(3, 5));

Nếu phương thức trả về void, việc gọi phương thức là câu lệnh.

Ví dụ phương thức println() trả về void: System.out.println("Hello!");

V.6 Các hàm và phương thức đặc biệt

Phương thức khởi tạo:

Phương thức khởi tạo (constructor) dùng để khởi tạo một đối tượng của lớp và đặt trạng

thái ban đầu cho đối tượng bằng cách xác định giá trị cho các thuộc tính của lớp.

Mỗi lớp có thể có 1 hoặc nhiều phương thức khởi tạo.

Phương thức khởi tạo có cùng tên với tên lớp và không có kiểu dữ liệu trả về.

Khi không khai báo phương thức khởi tạo, đối tượng được tạo ra bằng phương thức khởi

tạo mặc định với các giá trị mặc định của các thuộc tính.

Constructor không được kế thừa, nó chỉ được định nghĩa cho chính lớp cha. Vấn đề sử

dụng phương thức khởi tạo của lớp cha trong các lớp dẫn xuất sẽ bàn trong phần “Tính thừa kế”

Phương thức hủy:

Trái với phương thức khởi tạo, phương thức hủy được gọi khi đối tượng được giải phóng.

Tuy nhiên, trong Java công việc này được làm tự động, lập trình viên không cần quan tâm. Trong

trường hợp cần thiết ta có thể khai báo phương thức hủy theo cú pháp:

protected void finalize() {

// Body of Method

}

Hàm main()

Đây là một hàm đặc biệt được cài đặt trong lớp được gọi thực thi đầu tiên trong chương

trình. Vì nó được gọi khi chưa có đối tượng nào được tạo ra nên nó luôn được khai báo là static.

Hơn nữa, việc gọi hàm main() đương nhiên là diễn ra bên ngoài lớp nên nó cũng cần có mức độ

truy cập là public.

Hàm main() thường không trả về giá trị nào nên kiểu giá trị trả về của nó là void.

Page 52: Bai giang JAVA

52

Hàm main() có một tham số là một mảng các chuỗi chứa nội dung các tham số dòng lệnh.

V.7 Khai báo chồng các phương thức

Các phương thức trong cùng một lớp có thể có cùng tên nhưng nhất định số lượng các

tham số hoặc kiểu của chúng phải khác nhau. Điều này gọi là khai báo chồng phương thức.

Từ phiên bản Java 1.5, kiểu giá trị trả về cũng được xem như một yếu tố để phân biệt các

phương thức.

Sau đây là chương trình ví dụ về xây dựng các class trong Java:

abstract class People // Lớp trừu tượng

{

protected int Tuoi;

protected String HoVaTen;

public static final String MauDa=”Vang”; //hằng số

// Phương thức khởi tạo

public People(int t,String ht)

{

Tuoi=t;

HoVaTen=ht;

}

// Phương thức hiển thị tên và tuổi của một người

public String toString(){

return HoVaTen + "," + String.valueOf(Tuoi);

};}

Sau đó, ta có một lớp SinhVien kế thừa từ lớp People trên:

public class SinhVien extends People

{

private String Lop;

private double DiemTongKet;

public static int MaSo; // biến lớp

// Phương thức khởi tạo

public SinhVien(int t,String ht,String l,double dtk)

{

super(t,ht); // Gọi phương thức khởi tạo của lớp cha cho các thuộc tính kế thừa

// Các thuộc tính không kế thừa được gán tường minh

Lop = l;

DiemTongKet=dtk;

}

// Hàm main

public static void main(String[] argvs)

{

// Truy cập vào biến lớp không cần khởi tạo đối tượng

SinhVien.MaSo=10;

// Khởi tạo một đối tượng sinh viên, MaSo của sinh viên này sẽ là 10

SinhVien k = new SinhVien(23,"Nguyen Thi Mai","Letio3",7.15);

System.out.print(k.MaSo);

Page 53: Bai giang JAVA

53

SinhVien.MaSo=11;

// Khởi tạo một đối tượng sinh viên, MaSo của sinh viên này sẽ là 11

SinhVien k1 = new SinhVien(20,"Pham Anh Thu","Letio3",8.15);

System.out.print(k.toString());

People p = new People(20,"Pham Anh Hoa"); // Báo lỗi dòng này

}

}

Trong chương trình trên, việc khởi tạo một đối tượng thuộc lớp People sẽ bị báo lỗi do

lớp này là lớp trừu tượng. Chúng ta sẽ trở lại vấn đề này trong phần “Tính kế thừa”.

V.8 Lớp lồng nhau – lớp nội

Có thể định nghĩa một lớp bên trong một lớp khác . Lơp như vây goi la lơp lông (Nested

Class) và được cài đặt như sau :

class EnclosingClass{ // Lơp bao bên ngoai

. . .

static class StaticNestedClass { // Lơp lông tinh

. . .

}

class InnerClass { // Lơp lông phi tinh hay lơp nôi bô

. . .

}

}

Lơp lông chi đươc biêt bên trong phạm vi của lớp bao bên ngoài . Trình biên dịch Java sẽ

báo lỗi nếu môt đoan ma bât ky của lớp bên ngoài truy cập trưc tiêp lơp lông.

Môt lơp lông c ó quyên truy câp đên cac thanh viên cua lơp bao bên ngoai , thâm chi nêu

chúng được khai báo private . Tuy nhiên , lơp bao không thê truy xuât cac thành phần của lớp

lông.

Có hai kiểu lớp lồng : tĩnh và phi tĩnh .

Lớp lông tinh (static nested class) đươc bô sung tư khoa static . Nó không thể tham chiếu

trưc tiêp đên biên hay phương thưc đôi tương đươc đinh nghia trong lơp bao , mà chỉ dùng chúng

thông qua đôi tương . Vì giới hạn này nên lớp lồng tĩnh ít được dùng . Hầu hết các lớp lồng là lớp

nôi bô .

Lớp lông phi tinh (nonstatic nested class ) không bô sung tư khoa static , còn đươc goi la

lơp nôi bô (inner class). Nó có thể truy cập trực tiếp đến các biến và phương thức đối tượng.

class Outer {

int outer_x = 100;

void test() {

Inner inner = new Inner();

inner.display_x();

}

class Inner { // có thể truy xuât trưc tiêp biên đôi tương của lớp Outer

int inner_y = 10;

void display_x() {

System.out.println(“display : outer_x = “ + outer_x);

Page 54: Bai giang JAVA

54

}

}

void display_y() { // không thể truy xuất biến đối tượng của lớp Inner

System.out.println(“display : inner_y = “ + inner_y); // Error

}

}

class InnerClassDemo {

public static void main(String args[]) {

Outer outer = new Outer();

outer.test();

}

}

Trong Java có sử dụng một kỹ thuật cài đặt lớp nội nặc danh, tức là không có tên, khi xử

lý các sự kiện. Ví dụ:

frame.addWindowListener(new WindowAdapter()

{

public void windowClosing(WindowEvent event)

{

System.exit(0);

}

public void windowIconified(WindowEvent e) {System.exit(0);}

} );

Ở đây, ta có một lớp nặc danh kế thừa từ lớp WindowAdapter. Nó được khai báo chồng 2

phương thức của WindowAdapter.

VI. Tính kế thừa trong Java

Để theo dõi tính kế thừa trong Java được cài đặt như thế nào, trong phần này chúng ta sẽ

xem xét một ví dụ về quản lý nhân sự tại một công ty.

VI.1 Sự kế thừa các thuộc tính và phương thức

Giả sử trong công ty, đội ngũ quản lý (managers) được đối xử khác với nhân viên

(employees) bình thường. Lớp Employee được định nghĩa như sau:

import java.util.Date;

import java.util.GregorianCalendar;

class Employee

{

// Phương thức khởi tạo

public Employee(String n, double s, int year, int month, int day)

{

HoVaTen = n;

Luong = s;

GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);

// GregorianCalendar coi 0 là Tháng 1

NgayBatDau = calendar.getTime();

}

Page 55: Bai giang JAVA

55

// Phương thức lấy họ tên

public String getHoVaTen()

{

return HoVaTen;

}

// Phương thức lấy lương

public double getLuong()

{

return Luong;

}

//phương thức lấy ngày bắt đầu làm việc

public Date getNgayBatDau()

{

return NgayBatDau;

}

// Phương thức tăng lương

public void raiseSalary(double PhanTram)

{

double PhanTang = Luong * PhanTram / 100;

Luong += PhanTang;

}

// Các thuộc tính thành phần

private String HoVaTen;

private double Luong;

private Date NgayBatDau;

}

Ta thấy rằng cả Manager và Employee đều có những điểm chung về mặt quản lý như họ

cùng được trả lương. Tuy nhiên, với Employee chỉ được trả lương theo một hợp đồng có sẵn

trong khi Manager ngoài lương ra còn được hưởng một khoản tiền thưởng. Đây chính là ngữ

cảnh tốt để cài đặt tính kế thừa.

Chúng ta sẽ thiết kế một lớp Manager nhưng kế thừa lại những gì đã viết ở lớp Employee.

class Manager extends Employee

{

//Các thuộc tính và phương thức bổ sung

}

Từ khóa extends xác định rằng chúng ta đang tạo ra một lớp mới được dẫn xuất từ một

lớp đang tồn tại. Lớp đang tồn tại còn được gọi là lớp cha, supperclass, hoặc lớp cơ sở (base

class), lớp kế thừa còn được gọi là lớp dẫn xuất, lớp con. Các lớp dẫn xuất thường được cài đặt

nhiều tính năng hơn lớp cha.

Lớp Manager có thêm thuộc tính TienThuong và phương thức để thiết đặt giá trị cho nó:

class Manager extends Employee

{

. . .

public void setTienThuong(double b)

{

Page 56: Bai giang JAVA

56

TienThuong = b;

}

private double TienThuong;

}

Việc sử dụng các thuộc tính và phương thức này không có gì đặc biệt. Nếu ta có một đối

tượng Manager có tên boss, ta có thể gọi:

boss.setTienThuong(10000);

Tất nhiên là đối tượng của lớp Emplyee không thể gọi phương thức setTienThuong() vì

nó không phải là phương thức được định nghĩa trong lớp Employee.

Tuy nhiên, chúng ta có thể sử dụng các phương thức getHoVaTen(), getLuong(),

getNgayBatDau() đối với các đối tượng của lớp Manager vì chúng được tự động kế thừa từ lớp

Employee. Tương tự như thế, các thuộc tính HoVaTen, Luong và NgayBatDau cũng được kế

thừa. Lớp Manager có 4 thuộc tính là HoVaTen, Luong, NgayBatDau và TienThuong.

Đến đây ta có thể rút ra rằng khi thiết kế các lớp trong Java, ta đặt các thuộc tính và

phương thức phổ biến vào các lớp cha, lớp con chỉ việc khai báo thêm các thuộc tính và phương

thức đặc biệt.

Tuy nhiên, một số phương thức của lớp cha có thể không còn phù hợp ở lớp con. Ở đây,

phương thức getLuong() đối với lớp Manager phải là tổng của Luong và TienThuong. Do đó, ta

cần định nghĩa một phương thức mới trong lớp Manager đè lên phương thức cũ:

class Manager extends Employee

{

. . .

public double getLuong()

{

. . .

}

. . .

}

Chúng ta có thể nghĩ việc cài đặt cho phương thức mới này rất đơn giản như:

public double getLuong()

{

return Luong + TienThuong; // Không thực hiện

}

Tuy nhiên nó không thực hiện. Lý do là vì sự truy cập vào Luong ở đây là không hợp lệ.

Thuộc tính Luong trong Employee được khai báo là private nên chỉ các phương thức trong lớp

Employee mới được phép truy cập. Theo lý thuyết, việc xác định cho các thuộc tính lớp

Employee cấp độ truy cập là protected có vẻ là hợp lý. Tuy nhiên điều này có thể cho phép tất cả

các lớp dẫn xuất từ Employee thay đổi giá trị các thuộc tính này làm tính đóng gói của OOP bị

phá vỡ.

Đến đây chúng ta nghĩ rằng Luong phải được truy cập thông qua một cơ chế public khác

là phương thức getLuong() được định nghĩa public trong Employee.

public double getLuong()

{

double LuongCoBan = getLuong(); // vẫn không thực hiện

return LuongCoBan + TienThuong;

}

Page 57: Bai giang JAVA

57

Tuy nhiên, đoạn mã này cũng chưa thực hiện được. Lý do là phương thức getLuong() lúc

này được coi là chính phương thức getLuong() của lớp Manager nên nó không có tác dụng.

Để gọi được phương thức getLuong() của lớp Employee, ta dùng từ khóa super để chỉ lớp

cha.

public double getLuong()

{

double LuongCoBan = super.getLuong(); // OK

return LuongCoBan + TienThuong;

}

Nếu không cho phép lớp con kế thừa một phương thức của lớp cha, ta dùng từ khóa final

khi khai báo phương thức.

VI.2 Sự kế thừa đối với các constructor

Như đã đề cập, các phương thức khởi tạo không được tự động kế thừa cho lớp con. Tuy

nhiên ta có thể sử dụng phương thức khởi tạo của lớp cha để khởi tạo giá trị cho các thuộc tính

được kế thừa ở lớp con:

public Manager(String n, double s, int year, int month, int day)

{

super(n, s, year, month, day);

TienThuong = 0;

}

Ở đây, super(n, s, year, month, day); thay cho việc gọi constructor của Employee với 5

tham số n, s, year, month và day. Lưu ý là lệnh gọi super phải là lệnh đầu tiên trong phương thức

constructor ở lớp con.

Đến đây, ta đã có một lớp Manager được định nghĩa đúng đắn:

class Manager extends Employee

{

// Phương thức khởi tạo

public Manager(String n, double s, int year, int month, int day)

{

super(n, s, year, month, day);

TienThuong = 0;

}

// Phương thức tính lương

public double getLuong()

{

double LuongCoBan = super.getLuong(); // OK

return LuongCoBan + TienThuong;

}

//Phương thức đặt tiền thưởng

public void setTienThuong(double b)

{

TienThuong = b;

}

private double TienThuong;

}

Page 58: Bai giang JAVA

58

VII. Tính đa hình trong Java

Tính đa hình là một khả năng của OOP cho phép một phương thức thực thi theo ngữ cảnh

lúc chương trình đang chạy. Cho dùng là cùng một tên gọi, thậm chí là cùng danh sách tham số,

phương thức vẫn được gọi theo đúng đối tượng sở hữu nó.

Trong khi chúng ta cài đặt tính chất thừa kế của OOP, cơ sở của tính đa hình cũng đã

được cài đặt. Trong ví dụ trên, phương thức getLuong() được định nghĩa ở cả lớp cha và lớp con,

chúng ta sẽ xem nó được gọi như thế nào.

VII.1 Sự ép kiểu và gán tham chiếu đối tượng

Trong quan hệ thừa kế, đôi khi có sự chuyển đổi vai trò của các lớp cha và con. Ta có thể

gán tham chiếu một đối tượng của lớp con cho một đối tượng của lớp cha. Trường hợp ngược lại

là không thể. Đây chính là thể hiện tính đa hình của đối tượng. Một đối tượng của lớp cha có thể

được gán tham chiếu tới bất kỳ lớp con nào dẫn xuất từ nó nhưng không ép kiểu sang lớp con

được. Ngược lại, đối tượng lớp con không thể được gán tham chiếu tới một đối tượng lớp cha

nhưng có thể chuyển kiểu sang lớp cha.

Ví dụ:

Employee me = new Employee("Nguyen Anh Minh", 50000, 2000, 10, 1);

Employee you = new Employee("Nguyen Anh Tai", 52000, 2000, 10, 1);

Manager boss = new Manager ("Nguyen Tan Minh", 80000, 1987, 12, 15);

boss.setTienThuong(5000);

Manager boss1 = new Manager ("Nguyen Tan Phat", 81000, 1987, 12, 15);

boss1.setTienThuong(15000);

boss = me; // không gán tham chiêu được

me=boss1; //OK.

hoặc:

you = (Employee)boss; // Chuyển kiểu OK

boss1 = (Manager) me; // Cha không chuyển kiểu sang con được

Thậm chí một mảng các đối tượng Employee có thể được gán cho một mảng các đối

tượng Manager mà không cần chuyển kiểu:

Manager[] managers = new Manager[10];

Employee[] staff = managers; // OK

Tuy vậy, sự chuyển đổi này chỉ diễn ra trong thời gian chạy chương trình. Nếu khi lập

trình ta viết:

you = boss; // OK

you.setTienThuong(2000);// Không được

Lý do là việc chuyển kiểu chỉ xảy ra lúc chương trình chạy nên khi biên dịch “you” vẫn là

một đối tượng Employee, nó không có phương thức setTienLuong().

VII.2 Sự ràng buộc động –Dynamic Binding

Xét ví dụ sau:

// Khai báo một đối tượng Manager

Manager boss = new Manager("Phan Thanh Ha", 80000, 1987, 12, 15);

boss.setTienThuong(5000);

// Khai báo một mảng 3 đối tượng Employee

Employee[] staff = new Employee[3];

// Gán boss cho đối tượng thứ 0

Page 59: Bai giang JAVA

59

staff[0] = boss;

// Khởi tạo cho 2 đối tượng còn lại

staff[1] = new Employee("Nguyen Hai Nam", 50000, 1989, 10, 1);

staff[2] = new Employee("Pham Quyet Tan", 40000, 1990, 3, 15);

// Dùng vòng lặp để in ra tên và lương từng người

for (Employee e : staff)

System.out.println(e.getHoVaTen() + " " + e.getLuong());

Kết quả in ra là:

Phan Thanh Ha 85000.0

Nguyen Hai Nam 50000.0

Pham Quyet Tan 40000.0

Ở đây chúng ta thấy đối tượng thứ 1 và 2 in ra các giá trị vốn có của nó theo phương thức

getLuong() của Employee. Tuy nhiên đối tượng thứ 0 đã gọi phương thức getLuong() của

Manager. Mặt khác, nếu viết:

staff[0].setTienThuong(2000); thì không được phép khi biên dịch.

Ta gọi việc getLuong() của Manager được gọi trong tình huống này là sự ràng buộc muộn

hay ràng buộc động (Dynamic Binding). Đặc trưng thể hiện tính đa hình trong Java.

Để kết thúc phần này ta sẽ xem xét cơ chế của việc gọi phương thức của một đối tượng

trong Java được thực hiện như thế nào:

1. Trình biên dịch kiểm tra kiểu của đối tượng và tên của phương thức, giả sử là

x.f(param). Trong đó x được khai báo là đối tượng của lớp C. Trong lớp C có thể có nhiều

phương thức có cùng tên f nhưng khác nhau ở tham số, ví dụ f(int) và f(String). Trình biên dịch

sẽ liệt kê tất cả các phương thức tên f trong lớp C và phương thức tên f có mức độ truy cập public

trong các lớp cha của C.

2. Tiếp theo, trình biên dịch sẽ xác định kiểu của tham số của phương thức được gọi. Nếu

trong danh sách phương thức có tên f chỉ có 1 phương thức có kiểu tham số phù hợp thì phương

thức này được gọi. Ví dụ câu lệnh là x.f(“Chao ban”) thì hàm f(String) được gọi chứ không phải

f(int). Cơ chế này gọi là nạp chồng (overloading). Nếu trình biên dịch không thể tìm thấy phương

thức có tham số phù hợp hoặc có nhiều hơn 1 phương thức phù hợp, nó sẽ đưa ra thông báo lỗi.

Bây giờ, trình biên dịch đã biết rõ phương thức nào được gọi (tên và danh sách tham số).

3. Nếu phương thức là private, static và final hoặc là một constructor, trình biên dịch sẽ

biết chính xác phương thức cần phải gọi đó là phương thức f của lớp C. Điều này gọi là ràng

buộc tĩnh (static binding). Ngược lại, phương thức được gọi tùy theo kiểu hiện tại của đối tượng,

giả sử kiểu hiện tại của x là D, một lớp dẫn xuất từ C (Ban đầu x là một đối tượng lớp C nhưng

sau đó được gán tham chiếu tới một đối tượng của D). Nếu D có định nghĩa một phương thức

f(String) thì phương thức này sẽ được gọi. Nếu lớp D không có, nó sẽ tìm lên các lớp cha của D

(trong đó có lớp C). Cơ chế này gọi là ràng buộc động.

VIII. Lớp Object

Lớp Object là lớp cha của mọi lớp trong Java. Tuy nhiên chúng ta không bao giờ phải

khai báo:

class Employee extends Object

Mọi lớp đều là hậu duệ của Object, do đó, đối tượng thuộc lớp Object có thể được tham

chiếu tới bất kỳ đối tượng nào khác.

Object obj = new Employee("AAA", 35000);

Employee[] staff = new Employee[10];

Page 60: Bai giang JAVA

60

obj = staff; // OK

obj = new int[10]; // OK

IX. Giao diện

IX.1 Cấu trúc của giao diện

Trong Java không hỗ trợ tính đa thừa kế. Tuy nhiên, Java hỗ trợ một kỹ thuật thay thế và

rất linh hoạt, đó là các interface hay còn gọi là các giao diện.

Giao diện không phải là một class nhưng nó chỉ ra các phương thức sẽ được định nghĩa

trong các lớp cài đặt nó. Các lớp có sử dụng tới các phương thức này phải khai báo cài đặt giao

diện bằng từ khóa implement.

Cấu trúc của một giao diện rất đơn giản:

public interface <tên giao diện>

{

//Danh sách các phương thức

}

Tại lớp có cài đặt giao diện:

public class <tên lớp> implements <tên giao diện>

{

//Phân thân lớp có chứa định nghĩa phương thức của giao diện

}

Ví dụ:

Trong lớp Arrays của Java có phương thức sort dùng để sắp xếp các đối tượng trong một

mảng. Tuy nhiên, muốn sắp xếp được thì trong định nghĩa lớp của các đối tượng này phải có cài

đặt một phương thức so sánh compareTo(Object objKhac). Mở rộng hơn, tất cả các lớp muốn sử

dụng phương thức sort của Array đều phải cài đặt phương thức này trong định nghĩa của nó. Điều

này dẫn đến việc thiết kế một giao diện:

public interface Comparable

{

int compareTo(Object objKhac);

}

Phương thức compareTo nhận một đối tượng khác làm tham số và là đối tượng đem ra

so sánh, kết quả so sánh biểu hiện qua một số nguyên.

Từ phiên bản Java 5.0 (1.5), các giao diện có thể được xác định cho một kiểu tổng quát:

public interface Comparable<T>

{

int compareTo(T objKhac);

}

Ví dụ các lớp muốn cài đặt giao diện Comparable<Employee> phải cài đặt phương thức

int compareTo(Employee objKhac);

Tất cả các phương thức khai báo trong interface mặc định là public nên ta không cần khai

báo public cho nó.

Bây giờ chúng ta định nghĩa:

x.compareTo(y) <0 nếu x < y

x.compareTo(y) =0 nếu x = y

x.compareTo(y) >0 nếu x > y

Page 61: Bai giang JAVA

61

Trong interface ta đang xem xét thì nó chỉ có một phương thức. Các interface thường có

nhiều phương thức, các hằng số. Tuy nhiên trong interface ta không thể khai báo các biến thành

phần và không thể cài đặt nội dung của các phương thức. Các interface có thể xem như các lớp

trừu tượng không có thuộc tính thành phần tuy rằng chúng có nhiều điểm khác biệt.

Trong phần sau đây chúng ta sẽ cài đặt một phương thức compareTo cho việc so sánh các

đối tượng Employee.

Khai báo cài đặt Comparable cho Employee:

class Employee implements Comparable

Giả sử các Employee được so sánh thông qua tiêu chí Luong, ta cài đặt compareTo như

sau:

public int compareTo(Object objKhac)

{

Employee other = (Employee) objKhac; // Chuyển kiểu

if (Luong < other.Luong) return -1;

if (Luong > other.Luong) return 1;

return 0;

}

Chú ý rằng các phương thức trong interface không khai báo public nhưng khi cài đặt

chúng, nhất định ta phải có khai báo public.

Đối với phiên bản Java 5.0, ta có thể cài đặt:

class Employee implements Comparable<Employee>

{

public int compareTo(Employee objKhac)

{

if (Luong < objKhac.Luong) return -1;

if (Luong > objKhac.Luong) return 1;

return 0;

}

. . .

}

Đối với lớp Manager thì sao. Rõ ràng là một đối tượng Manager vẫn có thể được so sánh

với một đối tượng Employee về tiền lương. Tuy nhiên nếu ta cũng khai báo chồng một phương

thức compareTo() thì không được do vi phạm quy tắc chuyển kiểu:

class Manager extends Employee

{

public int compareTo(Employee objKhac)

{

Manager otherManager = (Manager) objKhac; // không được

. . .

}

. . .

}

May mắn là ta không cần làm điều này vì tính kế thừa đã đảm bảo Manager cài đặt

Comparable<Employee> chứ không phải Comparable<Manager>. Khi đưa một đối tượng

Manager vào làm tham số so sánh, nó tự động được ép sang kiểu Employee. Việc so sánh vì thế

diễn ra thoải mái giữa các đối tượng Employee và Manager với nhau.

Page 62: Bai giang JAVA

62

IX.2 Các tính chất của giao diện

Khi sử dụng interface ta cần chú ý mấy điểm sau:

Giao diện không phải là class nên không dùng từ khóa new để tạo một đối tượng

kiểu giao diện:

x = new Comparable(. . .); // Lỗi

Có thể khai báo một biến interface

Comparable x; // OK

Biến interface phải tham chiếu tới một đối tượng của một lớp có cài đặt interface đó.

x = new Employee(. . .); // OK

Có thể dùng toán tử instanceof để kiểm tra xem một đối tượng có được cài đặt

interface hay không: if (anObject instanceof Comparable) { . . . }

Các interface cũng có thể được kế thừa

Có thể khai báo các hằng số trong interface

public interface Comparable<Employee>

{

double greater = 1;

int compareTo(Employee other);

}

Trong interface, khai báo “double greater =1” được tự động hiểu là:

public static final double greater =1;

Các lớp có cài đặt interface cũng tự động được thừa kế các hằng số này.

Một lớp chỉ có thể kế thừa từ một lớp khác trong khi có thể cài đặt nhiều giao

diện.

X. Package

X.1 Sử dụng các package trong thư viện Java

Để sử dụng các class nằm trong một gói thư viện của Java mà không cần viết đường dẫn

đầy đủ của gói, ta khai báo nhập thư viện:

import java.util.*;

Vị trí của dấu “*” có thể là tên một class cụ thể. Dấu “*” đại diện cho tất cả class.

Trong một số trường hợp, sử dụng dấu “*” có thể gây ra lỗi. Ví dụ:

import java.util.*;

import java.sql.*;

Trong cả hai gói này đều có lớp Date nên trong dòng lệnh:

Date myDate = new Date();

Thì trình biên dịch báo lỗi vì không biết Date của gói nào. Khi này ta phải khai báo rõ

ràng cho Date ở gói nào:

import java.util.Date;

import java.sql.*;

Nếu muốn sử dụng cả hai Date trong chương trình ta phải khai báo trực tiếp:

java.util.Date deadline = new java.util.Date();

java.sql.Date today = new java.sql.Date(...);

Ta cũng có thể có một khai báo nhập thư viện với từ khóa static:

import static java.lang.System.*;

Page 63: Bai giang JAVA

63

Khi đó các phương thức và thuộc tính tĩnh của lớp System được truy cập mà không cần có

tên lớp:

out.print(“Khong co ten lop System”);

Ta thường dùng phương pháp này với các hàm của class Math: sqrt(pow(x, 2) + pow(y,

2)).

X.2 Đặt lớp vào package

Để đặt một lớp vào một package, ta phải có khai báo package ở dòng đầu tiên của chương

trình:

package com.horstmann.corejava;

public class Employee

{

. . .

}

Nếu không có khai báo đó, lớp tự động thuộc vào một package mặc định không có tên.

Các lớp trong gói sẽ tự động thuộc vào một đường dẫn đầy đủ theo tên của package.

Trong ví dụ trên Employee.class sẽ nằm trong thư mục: com\horstmann\corejava tính từ thư mục

hiện thời. Do đó, khi biên dịch hoặc chạy chương trình từ cửa sổ dòng lệnh CommandLine, ta

phải có đường dẫn đầy đủ:

Javac com\horstmann\corejava\Employee.java

Bài tập

1. Thực hành cài đặt các ví dụ trong đề tài trên.

2. Xây dựng các class trong java để cài đặt các lớp đối tượng: Khách hàng, sản phẩm, hóa

đơn, giỏ hàng trong một hệ thống quản lý bán hàng ở siêu thị.

3. Trong hệ thống đồ họa:

a. Hãy xây dựng các class điểm, đoạn thẳng, hình vuông, đa giác, tứ giác, hình chữ nhật,

tam giác, hình thoi.

b. Hãy cho biết một thứ tự phân cấp kế thừa của các lớp này.

c. Hãy cài đặt một phương thức toString() cho các lớp trên theo kỹ thuật ràng buộc động.

Phương thức toString() in ra màn hình giá trị tất cả các thuộc tính của một đối tượng.

4. Xây dựng một lớp PhuongTrinhBac1 để giải phương trình bậc 1.

5. Xây dựng một lớp đối tượng phương trình bậc 2 sao cho ta có thể khởi tạo một phương

trình bậc 2 và biết ngay các tình trạng của nó như có nghiệm hay không và giá trị nghiệm.

5. Xây dựng một giao diện GiaiPhuongTrinh dùng cho việc giải các phương trình bậc 1

và bậc 2 sau đó xây dựng lại các lớp PhuongTrinhBac1, PhuongTrinhBac2 có cài đặt giao diện

này.

6. Xây dựng một lớp đối tượng để cài đặt cho lớp đối tượng lớp học bao gồm các thuộc

tính như: Sĩ số, Tên lớp, Khóa học, danh sách lớp và các phương thức như: Thêm sinh viên, Xóa

Sinh viên, Sắp xếp danh sách, Xem danh sách, thống kê học tập, thống kê giới tính. Trong đó các

thành viên của lớp là các đối tượng Sinh viên có các thuộc tính như Họ và tên, Tuổi, Giới tính,

Điểm tổng kết và các phương thức phù hợp (sinh viên tự xác định xem cần những phương thức

gì). Các đối tượng sinh viên được so sánh theo tiêu chí điểm tổng kết.

Page 64: Bai giang JAVA

64

Đề tài 4. Lớp và phương thức trừu tượng

I. Khái niệm lớp trừu tượng

Những khái niệm trừu tượng trong thế giới thực được cài đặt trong chương trình như là

các lớp trừu tượng. Chúng thường làm cơ sở để giúp ta có được các định nghĩa cụ thể hơn: Ví dụ:

Các con trâu là động vật bốn chân được nuôi phục vụ cày bừa.

Các con hổ là động vật bốn chân sống trong các khu rừng.

Các con mèo là động vật bốn chân hay bắt chuột.

…….

Trong các định nghĩa trên, một khái niệm chung cần được làm rõ là “động vật bốn chân”.

Để cho các định nghĩa này thêm sáng tỏ, ta cần một định nghĩa về “động vật bốn chân”

Động vật bốn chân là động vật có bốn chân để di chuyển.

Đến đây ta lại bắt gặp một khái niệm trừu tượng hơn là “động vật” v.v…và có rất nhiều

khái niệm dùng đến khái niệm này như động vật ăn cỏ, động vật ăn thịt, động vật bò sát,….

Trong lập trình cũng vậy, những lớp đối tượng sinh ra chỉ để cho các lớp khác kế thừa gọi

là các lớp trừu tượng. Chúng thực sự không có một biểu hiện nào (hoặc nếu ta bắt buộc chúng có

biểu hiện thì biểu hiện đó cũng không có ý nghĩa trong phạm vi đang xét.)

II. Cài đặt lớp và phương thức trừu tượng trong Java

Khai báo: Lớp trừu tượng được khai báo như lớp thông thường nhưng có thêm từ khóa

abstract. Ví dụ:

abstract class People

{

private int NamSinh;

private String HoTen;

public People(int ns, String ht)

{

NamSinh= ns;

HoTen = ht;

}

public String getHoTen()

{

return HoTen;

}

abstract String toString();

}

Ta thấy rằng một lớp trừu tượng thực sự là một lớp với đầy đủ các thành phần, không

giống như interface.

Giả sử trong chương trình có các đối tượng SinhVien, GiaoVien. Các đối tượng này đều

có một phương thức toString để trả về một chuỗi bao gồm toàn bộ thông tin về chúng. Đây là tình

huống sử dụng phương thức trừu tượng một cách hiệu quả.

abstract String toString();

Chú ý là các phương thức trừu tượng không có phần thân.

Lớp SinhVien kế thừa từ People được cài đặt như sau:

Page 65: Bai giang JAVA

65

public class SinhVien extends People

{

private String Lop;

private double DiemTongKet;

// Phương thức khởi tạo

public SinhVien(int ns,String ht,String l,double dtk)

{

//Dùng phương thức khởi tạo của lớp cha

super(ns,ht);

Lop = l;

DiemTongKet=dtk;

}

// Cài đặt phương thức toString

public String toString()

{

return String.valueOf(NamSinh) + String.valueOf(DiemTongKet) + HoTen;

}

}

Khi một phương thức được khai báo là abstract thì lớp chứa nó cũng phải là một lớp

abstract. Khi sử dụng phương thức abstract cho một lớp thì nhất thiết phải có một lớp khác kế

thừa và khai báo cài đặt chồng thì mới có tác dụng. Khi kế thừa một lớp có chứa phương thức

trừu tượng thì phương thức đó bắt buộc phải được cài đặt.

Bài tập

1. Trong hệ thống quản lý bệnh nhân ở bệnh viện có 2 loại bệnh nhân là nội trú và ngoại

trú trong đó bệnh nhân nội trú có tính tiền giường nằm. Xây dựng một lớp BenhNhan trừu tượng

có các thuộc tính như họ và tên, tiền điều trị, có phương thức tính tiền phải thanh toán bằng tiền

điều trị cộng với tiền giường nằm. Sau đó xây dựng hai lớp BenhNhanNoiTru và

BenhNhanNgoaiTru kế thừa lớp BenhNhan. (Gợi ý: Phương thức TinhTien ơ lớp BenhNhan khai

báo trừu tượng sau đó được khai báo chồng tại các lớp thừa kế).

3. Một nhà máy sử chữa phương tiện vận chuyển có các loại xe ô tô thuộc nhiều hàng

khác nhau như Honda, Toyota, Mishubishi, Mercedec, Ford, Kia. Mỗi hãng ô tô lại có nhiều kiểu

khác nhau như 2 chỗ, 4 chỗ, 7 chỗ, 12 chỗ và 24 chỗ. Ngoài ra, nhà máy còn nhận bảo dưỡng cho

các loại xe mô tô tay ga và xe số. Nhà máy có các chế độ khuyến mại và bảo hành khác nhau tùy

theo xe của từng hãng.

a. Hãy xây dựng một lớp PHUONG_TIEN trừu tượng có phương thức trừu tượng là

Xac_Dinh_Gia() trong đó việc tính giá sửa cho một phương tiện bằng giá của nhà máy trừ đi tiền

khuyến mại.

b. Hãy xây dựng một giao diện trong đó có phương thức so sánh phương tiện theo tiêu chí

giá sửa.

c. Xây dựng chương trình nhập vào dữ liệu cho 5 chiếc xe cả ô tô và mô tô và in ra màn

hình theo thứ tự tăng dần của giá sửa.

Page 66: Bai giang JAVA

66

Đề tài 5. Lưu trữ và xử lý đối tượng

Trong phần này chúng ta sẽ đề cập tới các lớp tiện ích của Java trong gói java.util dùng

cho việc lưu trữ và xử lý các đối tượng.

I. Lớp Vector và giao diện Enumeration

I.1 Lớp Vector

Lập trình viên dùng lớp Vector để lưu trữ các đối tượng có kiểu giống nhau nhưng có thể

thay đổi động về kích thước tùy theo nhu cầu. Chúng ta sẽ xem xét việc sử dụng interface

Enumeration để cho phép duyệt lặp trên các cấu trúc như Vector.

Kích thước của Vector được tăng theo một lượng đặt trước hoặc được tự động tăng gấp

đôi khi ta cần tăng dung lượng của nó. Vì vậy thao tác chèn một phần tử mới vào một Vector sẽ

nhanh hơn khi kích thước của nó còn đủ dùng.

Vector lưu trữ tham chiếu của các đối tượng nên chương trình có thể dùng Vector để lưu

tham chiếu đến bất kỳ đối tượng nào. Để lưu các giá trị dữ liệu nguyên thủy, ta phải sử dụng các

lớp trong java.lang như Integer, Long hay Float thay vì dùng chính kiểu đó.

Sau đây là một ví dụ nhập vào 10 số nguyên, lưu vào một Vector rồi in ra để kiểm tra:

// Nhâp 10 doi tuong so nguyen

1. java.util.Vector v = new java.util.Vector(5,2);

2. for (int i=0;i<10;i++)

3. {

4. System.out.print("Nhap so nguyen thu " + String.valueOf(i) + ":");

5. java.lang.Integer p = new java.lang.Integer(nhap.nextInt());

6. v.addElement(p);

7. }

8. // In ra de kiem tra

9. for (int i=0;i<10;i++)

10. {

11. System.out.print("So nguyen thu " + String.valueOf(i) + " la:");

12. System.out.println(v.get(i));

13. }

14. System.out.println(v.size());

15. System.out.println(v.capacity());

Dòng 1: Khai báo một đối tượng v thuộc lớp Vector. Ở đây ta đã dùng một constructor

với 2 tham số là số phần tử ban đầu và số sẽ tăng khi Vector có nhu cầu tăng (mặc định sẽ gấp

đôi số hiện có). Lớp Vector có 3 constructor:

Nếu dùng constructor không tham số thì Java tự động cấp cho ta số phần tử ban đầu

là 10 và nhân đôi mỗi khi có nhu cầu mở rộng.

Nếu là 1 tham số thì đâu là số phần tử ban đầu, khi cần cũng tự động nhân đôi.

Nếu là 2 tham số thì tham số thứ nhất chỉ số phần tử ban đầu, tham số thứ 2 chỉ số

phần tử được thêm vào mỗi khi dung lương của Vector bị hết.

Dòng 2-7: Vòng lặp để nhập và lưu kết quả nhập vào Vector. Ở đây ta phải khai báo một

biến đối tượng kiểu Integer chứ không phải là một kiểu nguyên thủy int. Sau đó dùng phương

thức addElement() để thêm đối tượng này vào vị trí cuối của Vector.

Page 67: Bai giang JAVA

67

Ngoài ra ta cũng có thể sử dụng insertElementAt() để chèn phần tử vào một vị trí xác định

hoặc sử dụng setElementAt() để đặt giá trị cho một phần tử tại một vị trí.

Sử dụng removeElement(Object) để xóa một phần tử xuất hiện đầu tiên trong Vector có

giá trị bằng với Object.

Dòng 12: Dùng phương thức get(chỉ số) để in ra giá trị của phần tử có chỉ số tương ứng.

Thực ra thì phương thức get(chỉ số) cho ta một tham chiếu đến đối tượng có chỉ số tương ứng

được lưu trong Vector nhưng ở đây đối tượng số nguyên đã tự động in ra giá trị.

Dòng 14: Phương thức trả về kích thước thực tế của Vector, tức là số phần tử thực sự

Vector lưu trữ (=10) .

Dòng 15: Kích số lượng các phần tử tối đa hiện có của Vector (=11).

Một số phương thức của Vector:

removeElementAt: Xóa một phần tử ở một vị trí xác định.

removeAllElements(): Xóa tất cả các phần tử.

firstElement(): Trả về tham chiếu tới phần tử đầu tiên.

lastElement(): Trả về tham chiếu tới phần tử cuối cùng trong Vector.

isEmpty(): Xác định liệu Vector là trống.

contains(key): để kiểm tra xem trong vector có phần tử so khớp với key hay không. Đối

tượng key và các phần tử của Vector đươck so sánh với nhau bởi phương thức equals(). Các lớp

thường khai báo chồng phương thức equals() để dùng trong việc so sánh các đối tượng của mình.

indexOf(Object): Trả về chỉ số của đối tượng đầu tiên so khớp với Object.

trimToSize(): Giảm số lượng phần tử của Vector.

I.2 Giao diện Enumeration

Sử dụng phương thức elements() của một đối tượng Vector sẽ trả về một đối tượng

Enumeration cho phép chương trình duyệt lặp trên danh sách phần tử của Vector.

Đối tượng Enumeration có các phương thức quan trọng sau:

hasMoreElement(): Trả về true nếu vẫn còn phần tử trong Vector.

nextElement(): Trả về tham chiếu tới phần tử tiếp theo trong Vector.

Đoạn chương trình sau duyệt và in ra danh sách các sinh viên:

abstract class People

{

protected int NamSinh;//Nam Sinh

protected String HoVaTen; //Ho Va Ten

//constructor

public People(int ns,String ht)

{

NamSinh=ns;

HoVaTen=ht;

}

// Phuong thuc tinh tuoi

protected abstract int TinhTuoi();

public abstract String toString();

}

// Ke thua lop People

public class SinhVien extends People

{

Page 68: Bai giang JAVA

68

private String Lop;// Ten lop

private double DiemTongKet; // Diem tong ket

public final String mauda ="vang";//Hang so

private int ID;// Ma so SinhVien

protected static int MaSo;// ma so chung de cap phat cho moi sinh vien

// constructor

public SinhVien(int ns,String ht,String l,double dtk)

{

super(ns,ht);//goi constructor cua lop cha la People

Lop = l;

DiemTongKet=dtk;

// Id cua SinhVien duoc gan bang gia tri MaSo hien thoi cua lop

ID=MaSo;

// Tang ma so len 1 den gan cho SinhVien sau

MaSo+=1;

}

// Phuong thuc tinh tuoi

protected int TinhTuoi()

{

java.util.Date homnay = new java.util.Date();

return (homnay.getYear() - NamSinh +1);

}

// Khai bao chong phuong thuc toString()

public String toString()

{

return "Ma so:" + String.valueOf(ID)+ "\n"

+"Tuoi:"+ String.valueOf(this.TinhTuoi()) + "\n"

+"Diem Tong Ket:"+ String.valueOf(DiemTongKet)+"\n"

+"Ho va ten:"+ HoVaTen;

}

// Ham main

public static void main(String[] argv)

{

// Dat gia tr? bien static, sinh vien dau tien co ma so 1

SinhVien.MaSo=1;

// bien doi tuong Vector

java.util.Vector sv = new java.util.Vector(5);

SinhVien k1 = new SinhVien(80,"Nguyen Thi Mai 1","Letio3",5);

sv.addElement(k1); // Them sinh vien vao Vector

SinhVien k2 = new SinhVien(81,"Tran Thi Mai 2","Letio3",6);

sv.addElement(k2);

SinhVien k3 = new SinhVien(82,"Pham Thi Mai 3","Letio3",7);

sv.addElement(k3);

SinhVien k4= new SinhVien(83,"Phan Thi Mai 4","Letio3",8);

sv.addElement(k4);

SinhVien k5= new SinhVien(84,"Hoang Thi Mai 5","Letio3",9);

sv.addElement(k5);

Page 69: Bai giang JAVA

69

// Dung interface Enumeration de duyet cac phan tu cua Vector

java.util.Enumeration enu = sv.elements();

while (enu.hasMoreElements())

{

// Ep kieu, kieu Object la kieu cha cua moi kieu nen luon ep duoc

SinhVien g = (SinhVien)enu.nextElement();

System.out.println(g.toString());

}

//People p = new People(20,"Pham Anh Hoa"); bao loi vi People là lớp trừu

tượng

}

}

Kết quả thực hiện như sau:

II. Mảng trong Java và lớp ArrayList

II.1 Mảng trong Java

Trong phần “Ngôn ngữ Java căn bản” ta đã xem xét một biến mảng được khai báo và sử

dụng như thế nào. Trong phần này ta sẽ đi sâu khai thác các đặc tính của mảng và một số thuật

toán thông dụng thông qua các ví dụ.

Ví dụ: Đếm tần suất của các phần tử của một mảng:

import javax.swing.*;

public class StudentPoll {

// Hàm main

public static void main( String args[] )

Page 70: Bai giang JAVA

70

{

// Khai báo một mảng các câu trả lời

int TraLoi[] = { 1, 2, 6, 4, 8, 5, 9, 7, 8, 10, 1, 6, 3, 8, 6, 10, 3, 8, 2, 7, 6, 5, 7, 6, 8, 6, 7, 5,

6, 6, 5, 6, 7, 5, 6, 4, 8, 6, 8, 10 };

// Mảng đếm tần suất

int TanSuat[] = new int[ 11 ];

// Với mỗi phần tử của mang TraLoi, sử dụng giá trị đó như là chỉ số của mảng TanSuat

sau đó đếm sự xuất hiện của nó trong TraLoi, lưu giá trị vào mảng TanSuat tại vị trí tương ứng.

for ( int answer = 0; answer < TraLoi.length; answer++ )

++frequency[ TraLoi[ answer ] ];

// Đưa kết quả vào một chuỗi

for ( int rating = 1; rating < TanSuat.length; rating++ )

output += rating + "\t" + TanSuat[ rating ] + "\n";

// In ra

System.out.print(out);

} }

Trong ví dụ này, các câu trả lời nằm trong khoảng từ 1 đến 10 nên khai báo một mảng 11

phần tử để có thể sử dụng chính giá trị 10 làm chỉ số của mảng. Chỉ cần duyệt mảng TraLoi 1 lần

ta đã có ngay kết quả.

II.2. Các thuật toán cơ bản trên mảng

Ví dụ: Sắp xếp tuyến tính

Đây là một ví dụ sắp xếp các phần tử của mảng tăng dần theo thuật toán “nổi bọt” - tức là

sau mỗi vòng lặp duyệt, phần tử nào lớn nhất sẽ bị đẩy xuống cuối cùng.

// Sắp xếp các phần tử của mảng

public void bubbleSort( int array2[] )

{

// Duyệt qua mỗi phần tử của mảng

for ( int pass = 1; pass < array2.length; pass++ ) {

// Vòng lặp so sánh và đổi chỗ

for ( int element = 0; element < array2.length - pass; element++ ) {

// So sánh 2 phần tử liền kề và đổi chỗ nếu cần

if ( array2[ element ] > array2[ element + 1 ] )

swap( array2, element, element + 1 );

} }

}

// Hàm đổi chỗ 2 phần tử của một mảng

public void swap( int array3[], int first, int second )

{

int hold; // Biến trung gian để hoán đổi

hold = array3[ first ];

array3[ first ] = array3[ second ];

array3[ second ] = hold;

}

Page 71: Bai giang JAVA

71

Ví dụ: Tìm kiếm nhị phân trên mảng đã được sắp xếp:

Thông thường việc tìm kiếm diễn ra bằng phép duyệt lần lượt các phần tử của mảng. Ta

gọi phương pháp này là tìm kiếm tuyến tính.

Đối với các mảng đã được sắp xếp, ta có một phương pháp tìm kiếm hiệu quả hơn, gọi là

tìm kiếm nhị phân.

Giả sử ta có một mảng: int[] b={1,5,7,8,34,56,67,89,100};

Đã được sắp xếp tăng dần.

Giả sử ta cần tìm vị trí của một phần tử có giá trị 7. Trước tiên, ta so sánh 7 với vị trí đứng

giữa của mảng là 34 thì 7 < 34 nên ta chắc chắn nếu có thì 7 sẽ nằm ở nửa trước của mảng. Tiếp

tục làm việc này với nửa trước của mảng, so sánh 7 với 5 thì 7>5 nên phần tử cần tìm nếu có sẽ

nằm ở phần sau của nửa này gồm 2 phần tử 7,8. Lần phân đôi cuối cùng này cho ta kết quả.

Thủ tục này được cài đặt như sau:

public int binarySearch( int array2[], int key )

{

int low = 0; // Chỉ số dưới

int high = array.length - 1; // Chỉ số trên

int middle; // chỉ số của phần tử trung gian

// Lặp cho đến khi chỉ số dưới lớn hơn hoặc bằng chỉ số trên

while ( low <= high ) {

// Xác định chỉ số phần tử giữa

middle = ( low + high ) / 2;

// Nếu khóa cần tìm trùng với phần tử giữa thì trả về kết quả ngay

if ( key == array[ middle ] )

return middle;

// Nếu khóa nhở hơn phần tử giữa, đặt lại chỉ số trên

else if ( key < array[ middle ] )

high = middle - 1;

// Khóa lớn hơn phần tử giữa, đặt lại chỉ số dưới

else

low = middle + 1;

}

return -1; // Không tìm thấy

}

II.3 Class Arrays

Java hỗ trợ một lớp mảng trong thư viện java.util.Arrays để lập trình viên thao tác trên

mảng. Chủ yếu các phương thức của lớp này là static. Thay vì phải lập trình, Arrays hỗ trợ các

phương thức:

fill: để nạp giá trị cho mảng.

sort: để sắp xếp mảng

binarySearch: Tìm kiếm nhị phân trên mảng đã được sắp.

Page 72: Bai giang JAVA

72

equals: So sánh mảng

Sau đây là ví dụ về sử dụng lớp Arrays:

import java.util.*;

public class UsingArrays {

private int intValues[] = { 1, 2, 3, 4, 5, 6 };

private double doubleValues[] = { 8.4, 9.3, 0.2, 7.9, 3.4 };

private int filledInt[], intValuesCopy[];

// Khởi tạo các mảng

public UsingArrays()

{

filledInt = new int[ 10 ];

intValuesCopy = new int[ intValues.length ];

Arrays.fill( filledInt, 7 ); // Nạp giá trị cho mảng filledInt với giá trị 7

Arrays.sort( doubleValues ); // Sắp xếp mảng doubleValues

System.arraycopy( intValues, 0, intValuesCopy, 0, intValues.length ); // Sao chép mảng

}

// In giá trị của các mảng

public void printArrays()

{

System.out.print( "doubleValues: " );

for ( int count = 0; count < doubleValues.length; count++ )

System.out.print( doubleValues[ count ] + " " );

System.out.print( "\nintValues: " );

for ( int count = 0; count < intValues.length; count++ )

System.out.print( intValues[ count ] + " " );

System.out.print( "\nfilledInt: " );

for ( int count = 0; count < filledInt.length; count++ )

System.out.print( filledInt[ count ] + " " );

System.out.print( "\nintValuesCopy: " );

for ( int count = 0; count < intValuesCopy.length; count++ )

System.out.print( intValuesCopy[ count ] + " " );

System.out.println();

}

// Tìm một giá trị trong mảng intValues

public int searchForInt( int value )

Page 73: Bai giang JAVA

73

{

return Arrays.binarySearch( intValues, value );

}

// So sánh nội dung mảng

public void printEquality()

{

boolean b = Arrays.equals( intValues, intValuesCopy );

System.out.println( "intValues " + ( b ? "==" : "!=" ) + " intValuesCopy" );

b = Arrays.equals( intValues, filledInt );

System.out.println( "intValues " + ( b ? "==" : "!=" ) + " filledInt" );

}

// Hàm main

public static void main( String args[] )

{

UsingArrays usingArrays = new UsingArrays();

usingArrays.printArrays();

usingArrays.printEquality();

int location = usingArrays.searchForInt( 5 );

System.out.println( ( location >= 0 ? "Tìm thấy 5 tại vị trí " + location : "Không thấy" ) +

" trong mảng intValues" );

location = usingArrays.searchForInt( 8763 );

System.out.println( ( location >= 0 ? "Tìm thấy 8763 tại " + location : "Không thấy 8763"

) + " trong mảng intValues" );

} }

III Danh sách trong java và giao diện Lists

Lists là một chuỗi có thứ tự các phần tử cho phép các phần tử có thể giống nhau. Lists là

một giao diện kế thừa giao diện Collections nên nó cho phép lập trình viên truy cập các phần tử

qua chỉ số. Các lớp tập hợp cài đặt Lists là ArrayList, LinkedList và Vector.

ArrayList là một lớp tập hợp có thể thay đổi kích thước. Về cơ bản thì ArrayList giống

với Vector chúng ta đã xem xét ở trên.

Sau đây là chương trình ví dụ sử dụng ArrayList. Ở đây ta đặt các đối tượng String và

Color vào cùng một ArrayList sau đó xóa đi các phần tử String sử dụng một đối tượng Iterator.

import java.awt.Color;

import java.util.*;

public class CollectionTest {

private String colors[] = { "red", "white", "blue" };

// Tạo một ArrayList, thêm các phần tử cho nó

public CollectionTest()

{

ArrayList list = new ArrayList();

// Thêm đối tượng cho nó

list.add( Color.magenta ); // Thêm một đối tượng Color

// Thêm các đối tượng String

Page 74: Bai giang JAVA

74

for ( int count = 0; count < colors.length; count++ )

list.add( colors[ count ] );

list.add( Color.cyan ); // Thêm một đối tượng Color

// In ra nội dung

System.out.println( "\nArrayList: " );

for ( int count = 0; count < list.size(); count++ )

System.out.print( list.get( count ) + " " );

// Xóa tất cảcác đối tượng String

removeStrings( list );

// output list contents

System.out.println( "\n\nArrayList sau khi gọi removeStrings: " );

for ( int count = 0; count < list.size(); count++ )

System.out.print( list.get( count ) + " " );

}

public void removeStrings( Collection collection )

{

// Khai báo đối tượng iterator

iterator iterator = collection.iterator();

// Lặp trong khi tập hợp vẫn còn phần tử

while ( iterator.hasNext() )

if ( iterator.next() instanceof String )

iterator.remove(); // Xóa phần tử

}

// Hàm main

public static void main( String args[] )

{

new CollectionTest();

}

}

Bài tập

1. Viết chương trình quản lý danh sách một lớp học với các chức năng

- Tìm kiếm sinh viên

- Thêm sinh viên.

- Xóa sinh viên

- Sắp xếp danh sách theo tên

2. Viết chương trình nhập vào n số nguyên và số thực, n nhập từ bàn phím. Sau đó:

- Tính tổng của n số này.

- Sắp xếp n số theo thứ tự tăng dần

- Nhập vào từ bàn phím 1 số khác và tìm xem số đó có trong số n số vừa nhập không.

Page 75: Bai giang JAVA

75

Đề tài 6. Các luồng vào ra dữ liệu với file

Một khả năng quan trọng mà các ngôn ngữ lập trình phải có là việc quản lý các luồng dữ

liệu vào ra hệ thống máy tính giúp các chương trình có thể giao tiếp dữ liệu với thế giới bên

ngoài.

I. Khái niệm luồng vào ra (I/O stream)

Luồng là dòng chảy của dữ liệu. Có 2 loại luồng:

Luồng nhập (input stream): là tất cả gì từ thế giới bên ngoài được đưa vào máy

tính, như đọc từ bàn phím, đọc từ tập tin...

Luồng xuất (output stream): là tất cả những gì được gửi từ máy tính ra ngoài thông

qua các thiết bị ngoại vi, như màn hình, máy in, tệp tin, ...

Đối với mội luồng lại có các dòng bao gồm:

Lớp System.out: Dòng xuất chuẩn dùng để hiển thị kết quả trên màn hình.

Lớp System.in: Dòng nhập chuẩn thường đến từ bàn phím và được dùng để đọc

các ký tự dữ liệu.

Lớp System.err: Đây là dòng lỗi chuẩn cho phép một chương trình đưa ra các

thông báo lỗi trên màn hình.

Các dòng này có thể bị đổi hướng đến nhiều nguồn khác nhau. Ví dụ System.err có thể

đưa thông báo lỗi ra một file.

Khi cần làm việc với luồng, ta khai báo khối thư viện:

import java.io.*;

Thư viện này cho phép ta làm việc với các luồng nhập xuất qua việc cung cấp các lớp:

FileInputStrem, FileOutputStream, FileReader, FileWriter và rất nhiều lớp khác.

Sự phân cấp các class trong gói java.io thể hiện qua bảng sau:

java.lang.Object

File

FileDescriptor

InputStream

ByteArrayInputStream

FileInputStream

FilterInputStream

BufferedInputStream

DataInputStream

PushbackInputStream

ObjectInputStream

PipedInputStream

SequenceInputStream

OutputStream

ByteArrayOutputStream

FileOutputStream

FilterOutputStream

BufferedOutputStream

DataOutputStream

PrintStream

ObjectOutputStream

Page 76: Bai giang JAVA

76

PipedOutputStream

RandomAccessFile

Reader BufferedReader

LineNumberReader

CharArrayReader

FilterReader

PushbackReader

InputStreamReader

FileReader

PipedReader

StringReader

Writer

BufferedWriter

CharArrayWriter

FilterWriter

OutputStreamWriter

FileWriter

PipedWriter

PrintWriter

StringWriter

Sau đây chúng ta xem xét các class quan trọng thường được sử dụng:

II. Lớp InputStream:

Là một lớp trừu tượng định nghĩa cách thức nhận dữ liệu. Có các phương thức chính sau:

read(): Đọc các byte dữ liệu từ một dòng. Nếu như không có byte dữ liệu nào, nó

phải chờ. Khi một phương thức phải chờ, các luồng đang thực hiện phải tạm dừng

cho đến khi có dữ liệu.

read(byte[]): Trả về số byte đọc được hay „-1‟ nếu như đã đọc đến cuối dòng. Nó

gây ra ngoại lệ IOException nếu có lỗi xảy ra.

read(byte[],int,int): Nó cũng đọc vào một mảng byte. Nó trả về số byte thực sự đọc

được cho đến khi kết thúc dòng. Nó gây ra ngoại lệ IOException nếu lỗi xảy ra.

available(): Phương pháp này trả về số lượng byte có thể đọc được mà không phải

chờ. Nó trả về số byte hiện tại có trong dòng. Nó không phải là phương thức tin

cậy để thực hiện tiến trình xử lý đầu vào.

close(): Phương thức này đóng dòng. Nó dùng để giải phóng mọi tài nguyên dòng

đã sử dụng. Luôn luôn đóng dòng để chắc chắn rằng dòng xử lý được kết thúc. Nó

gây ra ngoại lệ IOException nếu lỗi xảy ra.

mark(): Đánh dấu vị trí hiện tại của dòng.

markSupported(): Trả về giá trị boolean chỉ ra rằng dòng có hỗ trợ các khả năng

mark và reset hay không. Nó trả về true nếu dòng hỗ trợ ngược lại trả về false.

reset(): Phương thức này định vị lại dòng theo vị trí được đánh lần cuối cùng. Nó

gây ra ngoại lệ IOException nếu lỗi xảy ra.

skip(): Phương thức này bỏ qua „n‟ byte dòng vào. ‟-n‟ chỉ định số byte được bỏ

qua. Nó gây ra ngoại lệ IOException nếu lỗi xảy ra. Phương thức này sử dụng để

di chuyển tới vị trí đặc biệt bên trong dòng vào.

Page 77: Bai giang JAVA

77

III. Lớp OutputStream

Là lớp trừu tượng định nghĩa cách ghi các kết xuất đến dòng. Nó cung cấp một tập các

phương thức trợ giúp tạo ra, ghi và xử lý kết xuất các dòng. Các phương thức bao gồm:

write(int): Phương thức này ghi một byte.

write(byte[]): Phương thức này phong toả cho đến khi một byte được ghi. Dòng

phải chờ cho đến khi tác vụ ghi hoàn tất. Nó gây ra ngoại lệ IOException nếu lỗi

xảy ra.

write(byte[], int, int): Phương thức này ghi mảng các byte. Lớp OutputStream định

nghĩa ba dạng khác nhau của phương thức để có thể ghi một byte riêng lẻ, một

mảng các byte, hay một đoạn của một mảng byte.

flush(): Phương thức này xả sạch dòng. Đệm dữ liệu được ghi ra dòng. Nó kích

hoạt IOException nếu lỗi xảy ra.

close(): Phương thức đóng dòng. Nó được dùng để giải phóng mọi tài nguyên gắn

với dòng. Nó kích hoạt IOException nếu lỗi xảy ra.

IV. Lớp FileInputStream

Kế thừa từ InputStream, lớp này cho phép đọc vào từ một tập tin dưới dạng một stream.

Các đối tượng của lớp này được tạo ra nhờ đường dẫn tới file, đối tượng File, hoặc đối tượng

FileDescriptor làm một đối số.

Lớp này có 3 phương thức khởi tạo sau:

FileInputStream(String name): Tham số là tên của tập tin để tạo luồng.

FileInputStream(File f): Tham số là đối tượng file để tạo luồng.

FileInputStream(FileDescriptor fdObj): Tham số là đối tượng FileDescriptor để

tạo luồng.

Ví dụ:

InputStream in = new FileInputStream(“C:\\LETI\\JAVA\\Account.txt”);

V. Lớp FileOutputStream

Lớp này cung cấp khả năng ghi dữ liệu xuống tập tin, được dẫn xuất từ lớp cha

OutputStream.

Có 3 phương thức khởi tạo:

FileOutputStream(String name);

FileOutputStream(File f);

FileOutputStream(FileDescriptor fdObj)

VI. Lớp File

Lớp này được sử dụng để truy cập các đối tượng tập tin và thư mục. Các tập tin đặt tên

theo qui ước đặt tên tập tin của hệ điều hành. Lớp này cung cấp các phương thức thiết lập các tập

tin và các thư mục. Tất cả các thao tác thư mục và tập tin được thực hiện thông qua các phương

thức của lớp File. Như vậy, ta dùng File trong tất cả các thao tác quản lý file và thư mục.

Có 3 cách để tạo các đối tượng từ lớp File:

File(String path);

File(String path, String name);

File(File dir, String name);

Ví dụ:File f = new File("C:\jdk1.4\bin\hello.java");

Page 78: Bai giang JAVA

78

hoặc

File f = new File("C:\jdk1.4\bin", "hello.java");

hoặc

File curDir = new File(".");

File f = new File(curDir, "Hello.java");

Các phương thức:

public String getName(): lấy tên đối tượng tập tin.

public String gePath(): lấy đường dẫn của tập tin.

public String getAbsolutePath(): lấy đường dẫn tuyệt đối của tập tin.

public String getParent(): lấy tên thư mục cha.

public Boolean createNewFile(): tạo một tập tin mới.

public void createTempFile(String pattern, File dir): tạo tập tin tạm thời.

public void deleteOnExit(): yêu cầu xoá tập tin khi chương trình chấm dứt.

public boolean canWrite(): cho biết tin có cho phép ghi hay không (true nếu có).

public boolean canRead(): cho biết tập tin được phép đọc hay không (true nếu có)

public void setReadOnly(): đặt thuộc tính chỉ đọc.

public boolean isFile(): cho biết tệp tin có hợp lệ hay không (true nếu có).

public boolean isDirectory(): cho biết tập tin có phải thư mục hay không (true nếu

có).

public boolean isHidden(): kiểm tra xem tập tin có ẩn hay không (true nếu có).

public long length(): cho biết kích thước tập tin (byte).

public boolean mkdir(): tạo một thư mục từ đối tượng file, true nếu thành công.

renameTo(File dest): đổi tên tập tin hiện tại sang tên mới.

public String[ ] list(): lấy danh sách các tập tin và thư mục.

public String[ ] list(FilenameFilter filter): lấy danh sách tập tin thoả mãn điều kiện

lọc, ví dụ *.gif.

public booean delete(): xoá tập tin, true nếu xoá thành công.

public String toString(): trả về đường dẫn của tập tin.

public String toURL(): trả về đối tượng URL tương ứng với tập tin.

Chương trình ví dụ:

public class Test

{

public static void main(String args[])

{

File f = new File("test");

System.out.println(f.getAbsolutePath()); // Lấy đường dẫn tuyệt đối

System.out.println(f.exists()); // Kiểm tra sự tồn tại

}

}

VII. Nhập xuất lọc

Là một kiểu dòng có được từ việc thay đổi cách xử lý dòng hiện có. Các lớp, các dòng

nhập xuất lọc của java sẽ giúp ta lọc vào/ra theo một số cách.

Bộ lọc nằm giữa một dòng nhập và một dòng xuất. Nó thực hiện xử lý một quá trình nào

đó trên các byte được truyền từ đầu vào đến đầu ra.

Page 79: Bai giang JAVA

79

Các bộ lọc có thể ghép với nhau khi đó đầu ra của bộ lọc này trở thành đầu vào của bộ

lọc kia.

VII.1 Lớp FilterInputStream:

Đây là lớp trừu tượng. Nó là cha của tất cả các lớp dòng nhập lọc. Một dòng có thể được

đọc và đưa kết quả cho một dòng khác.

Lớp FilterInputStream được thiết kế sao cho có khả năng kết chuỗi nhiều bộ lọc. Để thực

hiện điều này chúng ta dùng vài tầng lồng nhau.

VII.2 Lớp FilterOutputStream

Lớp này là một dạng bổ trợ cho lớp FilterInputStream. Nó là lớp cha của tất cả các lớp

dòng xuất lọc. Dữ liệu ghi vào lớp này có thể sửa đổi theo nhu cầu để thực hiện tác vụ lọc và sau

đó được chuyển tới đối tượng OutputStream.

VIII. Vào/ra có sử dụng bộ đệm

Vùng đệm là kho lưu trữ dữ liệu. Chúng ta có thể lấy dữ liệu từ vùng đệm thay vì quay trở

lại nguồn ban đầu của dữ liệu.

Java sử dụng cơ chế nhập/xuất có lập vùng đệm để tạm thời lập cache dữ liệu vào/ra của

một dòng. Nó giúp chương trình đọc/ghi lượng dữ liệu nhỏ không ảnh hưởng lớn đến hiệu năng

chung của hệ thống.

VIII.1 Lớp BufferedInputStream:

Lớp này tự động tạo ra và duy trì vùng đệm để hỗ trợ thao tác vào. Nhờ đó chương trình

có thể đọc dữ liệu từ dòng từng byte một mà không ảnh hưởng đến tốc độ thực hiện của hệ thống.

VIII.2 Lớp BufferedOutputStream

Lớp này định nghĩa hai phương thức thiết lập, một cho phép chỉ định kích cỡ của vùng

đệm xuất, một sử dụng kích cỡ vùng đệm ngầm định. Lớp này định nghĩa chồng tất cả các

phương thức của OutputStream và không đưa thêm bất kì phương thức mới nào.

Chương trình sau đây đọc và ghi thông tin của đối tượng SinhVien theo một format, mỗi

sinh viên nằm trên một dòng trong file:

// Ke thua lop People

import java.io.*;

import java.util.StringTokenizer;

public class SinhVien extends People

{

private String Lop;// Ten lop

private double DiemTongKet; // Diem tong ket

public final String mauda ="vang";//Hang so

private int ID;// Ma so SinhVien

protected static int MaSo;// ma so chung de cap phat cho moi sinh vien

public SinhVien(int ns,String ht,String l,double dtk)

{

super(ns,ht);//goi constructor cua lop cha la People

Lop = l;

Page 80: Bai giang JAVA

80

DiemTongKet=dtk;

// Id cua SinhVien duoc gan bang gia tri MaSo hien thoi cua lop

ID=MaSo;

// Tang ma so len 1 den gan cho SinhVien sau

MaSo+=1;

}

// Phuong thuc tinh tuoi

protected int TinhTuoi()

{

java.util.Date homnay = new java.util.Date();

return (homnay.getYear() - NamSinh +1);

}

// Khai bao chong phuong thuc toString()

public String toString()

{

return String.valueOf(ID)+ "|"

+ String.valueOf(this.TinhTuoi()) + "|"

+ String.valueOf(DiemTongKet)+"|"

+ HoVaTen;

}

// Ghi thông tin sinh viên vào file

public void GhiData(PrintWriter out) throws IOException

{

out.println(this.toString());

}

// Đọc thông tin 1 sinh viên từ bộ đệm đọc

public void DocData(BufferedReader in) throws IOException

{

String s = in.readLine(); // Đọc một dòng trong bộ đệm

StringTokenizer t = new StringTokenizer(s, "|");

MaSo = Integer.parseInt(t.nextToken());

NamSinh = Integer.parseInt(t.nextToken());

DiemTongKet = Double.parseDouble(t.nextToken());

HoVaTen = t.nextToken();

}

// Ham main

public static void main(String[] argv)

{

// Dat gia trị bien static, sinh vien dau tien co ma so 1

SinhVien.MaSo=1;

// bien doi tuong Vector lưu các sinh viên

java.util.Vector sv = new java.util.Vector(5);

SinhVien k1 = new SinhVien(80,"Nguyen Thi Mai 1","Letio3",5);

sv.addElement(k1); // Them sinh vien vao Vector

SinhVien k2 = new SinhVien(81,"Tran Thi Mai 2","Letio3",6);

sv.addElement(k2);

Page 81: Bai giang JAVA

81

SinhVien k3 = new SinhVien(82,"Pham Thi Mai 3","Letio3",7);

sv.addElement(k3);

SinhVien k4= new SinhVien(83,"Phan Thi Mai 4","Letio3",8);

sv.addElement(k4);

SinhVien k5= new SinhVien(84,"Hoang Thi Mai 5","Letio3",9);

sv.addElement(k5);

// Dung interface Enumeration de duyet cac phan tu cua Vector

java.util.Enumeration enu = sv.elements();

try

{

PrintWriter out = new PrintWriter(new FileWriter("C:\\LETI\\JAVA\\Sinhvien.dat"));

while (enu.hasMoreElements())

{

// Ep kieu, kieu Object la kieu cha cua moi kieu nen luon ep duoc

SinhVien g = (SinhVien)enu.nextElement();

g.GhiData(out);

}

out.close();

} catch(Exception ep) {}

// Doc tu file ra

SinhVien[] svs = new SinhVien[5];

try

{

BufferedReader in = new BufferedReader(new

FileReader("C:\\LETI\\JAVA\\Sinhvien.dat"));

for(int i=0;i<svs.length;i++)

{

svs[i] = new SinhVien(0,"","",0.0);

svs[i].DocData(in);

}

}

catch(IOException ep)

{}

for(int i=0;i<svs.length;i++)

System.out.println(svs[i].toString());

}}

IX. Lớp RandomAccessFile

Lớp RandomAccessFile cung cấp khả năng thực hiện vào/ra theo một vị trí cụ thể bên

trong một tập tin. Trong lớp này, dữ liệu có thể đọc hoặc ghi ở vị trí ngẫu nhiên thay vì liên tục.

Lớp RandomAccessFile thực hiện cả hai việc nhập và xuất. Do vây, có thể thực hiện I/O

bằng các kiểu dữ liệu nguyên thuỷ. Lớp này cũng hỗ trợ các quyền cơ bản về đọc hoặc ghi tập

tin, điều này cho phép đọc tập tin theo chế độ chỉ đọc hoặc đọc-ghi.

Đối tượng thuộc lớp RandomAccessFile có thể được khởi tạo theo hai cách:

RandomAccessFile(String name, String mode);

Page 82: Bai giang JAVA

82

RandomAccessFile(File f, String mode);

Trong đó mode là chế độ mở tập tin:

mode = "r" - chế độ chỉ đọc.

mode = "rw" - chế độ ghi và đọc.

Ví dụ:

RandomAccessFile file = new RandomAccessFile(“C:\\LETI\\JAVA\\Account.txt”, "r");

Lớp này hỗ trợ một số phương thức mới khác với phương thức đã thừa kế từ các lớp

DataInput và DataOutput.

Các phương thức mới thêm vào bao gồm:

seek( ): Thiết lập con trỏ tập tin tới vị trí cụ thể bên trong tập tin.

getFilePointer( ): Trả về vị trí hiện hành của con trỏ tập tin.

length( ): Trả về chiều dài của tập tin tính theo byte.

X. Đối tượng System.in

Là một đối tượng đặc biệt được tạo ra từ lớp InputStream. Nó giúp ta đọc các ký tự được

người dùng gõ vào từ bàn phím, ta có thể sử dụng phương thức read() hoặc kết nối với một luồng

trung gian khác.

XI. Truy cập file ở chế độ tuần tự

Khi làm việc với Java, tất cả đều là đối tượng. Trong các ứng dụng quản lý ta thường

xuyên phải đọc và ghi dữ liệu về các đối tượng lên ổ cứng. Các lớp ObjectInputStream và

ObjectOutputStream cho phép chúng ta đọc và ghi đối tượng vào file.

Để cho phép một đối tượng của một lớp có thể sử dụng với ObjectInputStrems và

ObjectOutputStreams, lớp đó phải khai báo cài đặt giao diện Serializable.

Giao diện Serializable được biết đến như là một giao diện “đính kèm” bởi vì bản thân nó

không chứa bất kỳ một phương thức nào. Một class cài đặt giao diện này được gán một thông báo

rằng đối tượng của lớp là một đối tượng Serializable. Điều này rất quan trọng bởi vì một đối

tượng ObjectOutputStream sẽ không xuất một đối tượng trừ khi đó là một đối tượng Serializable.

Trong một lớp cài đặt Serializable, lập trình viên phải đảm bảo rằng mọi biến của lớp phải

có kiểu Serializable hoặc phải khai báo một biến là transient để bỏ qua trong quá trình tuần tự

hóa. Mặc định thì tất cả các kiểu dữ liệu nguyên thủy đều là tuần tự hóa. Với các kiểu không

nguyên thủy, phải kiểm tra xem định nghĩa của lớp (hoặc lớp cha) có cài đặt Serializable hay

không.

Sau đây là một ví dụ về xây dựng một lớp đối tượng khách hàng cho một ứng dụng ngân

hàng sau đó ghi chúng vào file:

import java.io.Serializable;

public class AccountRecord implements Serializable {

private int account;

private String firstName;

private String lastName;

private double balance; // Chỉ số nắm giữ hàng hóa và dịch vụ của khách hàng, số dư tài

khoản

public AccountRecord()// constructor không tham số

{

this( 0, "", "", 0.0 );

}

Page 83: Bai giang JAVA

83

public AccountRecord( int acct, String first, String last, double bal ) // Constructor có

tham số

{

setAccount( acct );

setFirstName( first );

setLastName( last );

setBalance( bal );

}

public void setAccount( int acct ) // Ðặt số tài khoản

{

account = acct;

}

public int getAccount()// Lấy số tài khoản

{

return account;

}

public void setFirstName( String first ) // Ðặt giá trị cho phần họ đệm

{

firstName = first;

}

public String getFirstName()// Lấy phần họ đệm

{

return firstName;

}

public void setLastName( String last ) // Ðặt giá trị cho tên

{

lastName = last;

}

public String getLastName()// Lấy tên

{

return lastName;

}

public void setBalance( double bal ) // Đặt giá trị cho balance

{

balance = bal;

}

public double getBalance()// Lấy số dư

{

return balance;

}

}

Chương trình sau đây sẽ ghi các đối tượng vào file C:\LETI\JAVA\Account.txt

import java.io.*;

public class GhiFile

Page 84: Bai giang JAVA

84

{

ObjectOutputStream output;

public void openFile()

{

try {

output = new ObjectOutputStream(new FileOutputStream(

"C:\\LETI\\JAVA\\Account.txt") );

}

catch ( IOException ioException ) {

System.out.print("Loi mo file");

}

}

public void closeFile() // Phương thức đóng file

{

try {

output.close();

System.exit( 0 );

}

// Nếu có lỗi đóng file

catch ( IOException ioException )

{

System.exit( 1 );

}

}

public void addRecord(AccountRecord record) // Phương thưc thêm 1 bản ghi vào file

{

try

{

output.writeObject( record );

output.flush();

}

catch(IOException ex)

{

System.out.print("Loi ghi file");

}

}

// Hàm main

public static void main(String[] argvs)

{

AccountRecord record1= new AccountRecord( 12345,"Nguyen Van ","Hai",5.12);

AccountRecord record2= new AccountRecord( 12346,"Phan Tien ","Minh",-5.12);

GhiFile g = new GhiFile();

g.openFile();

g.addRecord(record1);

g.addRecord(record2);

g.closeFile();

} }

Page 85: Bai giang JAVA

85

Chương trình sau đây đọc ra 2 bản ghi vừa được ghi ở chương trình trên và in ra màn

hình:

import java.io.*;

public class DocFile

{

java.io.ObjectInputStream input;

public void openFile() // Mở file

{

try

{

input = new java.io.ObjectInputStream(new FileInputStream("C:\\LETI\\JAVA\\Account.txt"));

} catch(IOException e)

{

System.out.print("Loi mo file");

}

}

public void closeFile() //Đóng file

{

try {

input.close();

System.exit( 0 );

}

catch ( IOException ioException )

{

System.exit( 1 );

}

}

// Phương thức đọc 1 bản ghi

public String readFile()

{

String account="";

try {

AccountRecord a = (AccountRecord)input.readObject();

account =String.valueOf( a.getAccount() ) + "\n "

+ a.getFirstName() + "\n "

+ a.getLastName() + "\n "

+ String.valueOf( a.getBalance());

}

catch(Exception p){}

finally {return account;}

}

public static void main(String[] argvs)

{

DocFile d = new DocFile();

Page 86: Bai giang JAVA

86

d.openFile();

System.out.println(d.readFile());

System.out.println(d.readFile());

d.closeFile();

}}

XII. Truy cập file nhị phân

Ngoài các công cụ thao tác trên file văn bản, Java hỗ trợ cả các thao tác với file nhị phân

dùng các đối tượng:

DataOutputStream: Hỗ trợ ghi file ở chế độ nhị phân tức là từng byte.

DataInputStream: Hỗ trợ đọc file ở chế độ nhị phân.

Tất nhiên là các file văn bản cũng có thể đọc ghi ở chế độ nhị phân.

Chương trình sau đây copy dữ liệu giữa hai file dạng .doc:

import java.io.*;

public class BinaryAccess

{

public static void main(String[] argvs)

{

java.io.DataOutputStream out; // Luồng ra hỗ trợ ghi file nhị phân

java.io.DataInputStream in; // Luồng vào hỗ trợ đọc file nhị phân

try

{

in = new java.io.DataInputStream(new FileInputStream("C:\\P.doc"));

out = new java.io.DataOutputStream(new FileOutputStream("C:\\G.doc"));

int bytesAvailable = in.available(); // số byte của file

if (bytesAvailable > 0)

{

byte[] data = new byte[bytesAvailable];

in.read(data); // Đọc các byte ra một mảng byte

out.write(data); // Ghi mảng byte này vào một file khác

}

in.close();

out.close();

}

catch (Exception ex)

{}

}}

Bài tập

1. Viết một chương trình nhập vào một chuỗi từ bàn phím sau đó ghi chuỗi ra file.

2. Cho một file có dữ liệu về thí sinh thi hoa hậu như sau:

001, Tran Thi Mong Mo, 1.98, Ha Tay

002, Bùi Thị Thanh Nhàn, 1.89, Ha Noi

003, Nguyen Thu Thuy, 1.70, Ha Nam

Page 87: Bai giang JAVA

87

009, Phan Anh Thu, 1.78, Thanh Hoa

Các dữ liệu lần lượt mô tả về: Mã số, Họ và tên, chiều cao, Quê quán.

Viết một chương trình đọc dữ liệu của file ra và gán mỗi dòng cho một đối tượng

HOAHAU.

3. Viết một chương trình copy dữ liệu từ một file văn bản sang một file văn bản khác.

4. Viết chương trình copy dữ liệu từ một file ảnh GIF sang một file ảnh GIF khác.

Page 88: Bai giang JAVA

88

Đề tài 7. Xử lý ngoại lệ

Khi viết một chương trình nói chung và trong Java nói riêng, lỗi có thể xảy ra với rất

nhiều lý do. Khi lỗi xảy ra, người sử dụng chương trình muốn rằng chương trình có thể:

Quay lại trạng thái an toàn trước đó và cho phép người dùng thực hiện các công

việc khác

Ghi lại các dữ liệu hiện thời và kết thúc chương trình

Tuy nhiên điều này là rất khó khăn bởi lỗi có thể đến do một trong các nguyên nhân:

Người dùng nhập dữ liệu sai

Lỗi thiết bị

Lỗi phần cứng như thiếu ổ cứng hay bộ nhớ.

Trong một đoạn chương trình mà lập trình viên không thể biết trước được liệu có chuyện

gì xảy ra làm cho đoạn chương trình đó gây ra lỗi hay không , chúng ta gọi đó là một ngoại lệ

(exception) – những điều xảy ra khác thường. Java cho phép người lập trình quản lý các lỗi xảy

ra theo cách khi nó xảy ra, chương trình sẽ thực hiện những việc do chính lập trình viên đặt ra,

gọi là exception handling.

I. Các tình huống sử dụng ngoại lệ

Việc quản lý các ngoại lệ nên được sử dụng khi:

Một phương thức không thể hoàn thành nhiệm vụ của nó vì một lý do rằng nó

không thể điều khiển được mọi chuyện.

Xử lý các ngoại lệ từ một thành phần chương trình chưa được quản lý ngoại lệ

Trong các dự án lớn, đưa vào các xử lý ngoại lệ để xử lý theo một cách riêng

thống nhất.

II. Cơ sở quản lý ngoại lệ trong Java

Khi một phương thức không thể hoàn thành nhiệm vụ của nó, nó có thể “quăng,

ném”(throws) ra một Exception, nếu có một Exception handler - đoạn code xử lý khi lỗi xảy ra –

thì Exception này sẽ bị “bắt” (catch) và “được quản lý”(handled).

Cú pháp để thực hiện điều này như sau:

try

{

// Đoạn chương trình có thể gây ra exception

}

catch (<Kiểu exception> <tên biến>)

{

// Đoạn code chạy khi exception xảy ra

}

finally

{

// Đoạn code luôn được thực hiện bất kể exception có xảy ra hay không

}

Một khối try có thể không có hoặc có nhiều khối catch. Mỗi khối catch xác định một kiểu

exception mà nó có thể bắt và chứa đoạn code xử lý trong trường hợp tương ứng.

try{

//code có thể throw exceptions

Page 89: Bai giang JAVA

89

}

catch (MalformedURLException e1)

{

//code xử lý

}

catch (UnknownHostException e2)

{

//code xử lý

}

catch (IOException e3)

{

//code xử lý

}

Sau khối catch cuối cùng, có thể có hoặc không một khối finally chứa code xử lý bất kể

exception có xảy ra hay không.

Mỗi khối try bắt buộc phải có một khối catch hoặc finally.

Khi lỗi xảy ra, chương trình sẽ tìm đến khối catch có kiểu đối tượng Exception phù hợp

để thực hiện. Để lấy được thông báo từ hệ thống về lỗi, sử dụng phương thức getMessage() của

các lớp Exception, ví dụ:

e3.getMessage();

Trong một phương thức ta có thể khai báo một mệnh đề throws để phương thức “quăng”

ra các ngoại lệ. Các ngoại lệ này được quăng ra bởi các lệnh throw hoặc việc gọi một phương

thức khác trong phương thức này. Tại điểm quăng ra ngoại lệ (throw point), Java sử dụng cơ chế

kết thúc chương trình thay vì cơ chế qua trở lại điểm xảy ra ngoại lệ và tiếp tục.

Ví dụ:

int functionName( parameterList ) throws ExceptionType1, ExceptionType2,

ExceptionType3,..

{

// Thân phương thức

}

III. Cấu trúc cây kế thừa các xử lý ngoại lệ

Trong Java có hàng trăm lớp ngoại lệ để “bắt” các lỗi tương ứng như lỗi vào/ra file, lỗi

truy cập CSDL SQL,…Các ngoại lệ trong Java đều kế thừa từ lớp Throwable theo cấu trúc như

sau:

Page 90: Bai giang JAVA

90

Danh sách các ngoại lệ thường dùng trong Java

Ngoại lệ Ý nghĩa

RuntimeException Lớp cơ sở cho nhiều ngoại lệ java.lang

ArthmeticException Lỗi về số học, ví dụ như „chia cho 0‟.

IllegalAccessException Lớp không thể truy cập.

IllegalArgumentException Đối số không hợp lệ.

ArrayIndexOutOfBoundsExeption Lỗi tràn mảng.

NullPointerException Khi truy cập đối tượng null.

SecurityException Cơ chế bảo mật không cho phép thực hiện.

ClassNotFoundException Không thể nạp lớp yêu cầu.

NumberFormatException Việc chuyển đối từ chuỗi sang số thực không thành công.

AWTException Ngoại lệ về AWT

IOException Lớp cha của các lớp ngoại lệ I/O

FileNotFoundException Không thể định vị tập tin

EOFException Kết thúc một tập tin.

NoSuchMethodException Phương thức yêu cầu không tồn tại.

InterruptedException Khi một luồng bị ngắt.

IV. Sử dụng ngoại lệ được kiểm soát

Trong phần trên đã bàn về cách sử dụng các exception để bắt các lỗi không được kiểm

soát. Trong phần này chúng ta sẽ xem cách sử dụng ngoại lệ để quản lý các tình huống có thể

kiểm soát được.

Các ngoại lệ dạng này được khai báo ở phần đầu các phương thức. Ví dụ trong phương

thức khởi tạo sau:

public FileInputStream(String name) throws FileNotFoundException

Ở đây phương thức nhận một tham số kiểu String như là tên file, tuy nhiên rất có thể file

không tồm tại hoặc là một file rỗng và không có gì để đọc. Khi gặp lỗi như vậy, chương trình sẽ

tìm tới vị trí định nghĩa để quản lý lỗi này.

Một vấn đề là lập trình viên không biết throws ra ngoại lệ nào hoặc không thể khai báo

hết tất cả các ngoại lệ. Tuy nhiên, có 4 tình huống để đưa ra ngoại lệ:

Khi gọi một phương thức có throw một ngoại lệ, chẳng hạn như FileInputStream.

Khi ta xác định được một lỗi và throws một exception bằng một lệnh throw

Khi viết một chương trình bị lỗi, chẳng hạn a[-1] = 0, sẽ dẫn đến việc kích hoạt

một ngoại lệ, chẳng hạn ở đây là ArrayIndexOutOfBoundsException.

Khi một lỗi bên trong hệ thống như trong JVM hoặc các thư viện động.

Một phương thức cần khai báo ngoại lệ phù hợp:

class MyAnimation

{

. . .

public Image loadImage(String s) throws IOException

{

. . .

}

}

Phương thức có thể throws nhiều ngoại lệ nếu cần:

Page 91: Bai giang JAVA

91

class MyAnimation

{

. . .

public Image loadImage(String s) throws EOFException, MalformedURLException

{

. . .

}

}

Các ngoại lệ bắt lỗi nội bộ của Java thường không nên được khai báo, đó là các ngoại lệ

kế thừa từ lớp Error vì chúng vượt khỏi tầm kiểm soát của chúng ta. Đối với các ngoại lệ không

được kiểm soát, chúng kế thừa từ lớp RuntimeException cũng vậy, ta không nên khai báo chúng.

Ví dụ:

class MyAnimation

{

. . .

void drawImage(int i) throws ArrayIndexOutOfBoundsException // Không phù hợp

{

. . .

}

}

Đối với các ngoại lệ dạng RuntimeException, nếu chúng ta có kế hoạch để khai báo nó thì

tốt nhất là tìm cách để khắc phục không cho chúng xảy ra.

V. Xây dựng một ngoại lệ

Chúng ta có thể tự xây dựng một ngoại lệ để throws trong những trường hợp cụ thể. Các

class ngoại lệ này được kế thừa từ lớp Exception hoặc lớp con của nó như IOException chẳng

hạn. Ví dụ:

class FileFormatException extends IOException

{

public FileFormatException() {}

public FileFormatException(String gripe)

{

super(gripe);

}

}

Sau đó, ta có thể sử dụng ngoại lệ này trong chương trình:

String readData(BufferedReader in) throws FileFormatException

{

. . .

while (. . .)

{

if (ch = = -1) // Điểm cuối file

{

if (n < len)

throw new FileFormatException();

}

Page 92: Bai giang JAVA

92

. . .

}

return s;

}

VI. Bài tập

1. Viết chương trình đọc một file trên ổ đĩa và in ra màn hình. Chú ý dùng các ngoại lệ để

kiểm soát tất cả các tình huống có thể.

2. Khai báo một lớp ngoại lệ để kiểm soát tình huống điểm một sinh viên vượt quá 10 hay

tuổi của sinh viên vượt quá 100 trong ứng dụng quản lý sinh viên ở đề tài “Lập trình hướng đối

tượng trong Java”.

3. Viết chương trình nhập một số nguyên từ bàn phím. Bắt ngoại lệ khi người dùng nhập

vào ký tự hoặc số thực có phần thập phân.

Page 93: Bai giang JAVA

93

Đề tài 8. Xử lý các sự kiện trong Java

I. Khái niệm và cơ sở xử lý sự kiện

Bất kỳ chương trình có giao diện đồ họa nào thường hỗ trợ việc kích hoạt các sự kiện từ

con chuột hoặc bàn phím. Môi trường điều hành sẽ gửi các sự kiện này tới chương trình đang

chạy. Lập trình viên được hoàn toàn quyết định điều gì sẽ xảy ra khi các sự kiện này được kích

hoạt.

Trong Java sử dụng một cách tiếp cận dựa trên các khái niệm:

- Các nguồn của sự kiện (event source)

- Các bộ lắng nghe sự kiện (event listener)

Các nguồn sự kiện chính là các đối tượng điều khiển, chúng có các phương thức để lập

trình viên đăng ký các bộ lắng nghe cho chúng. Khi một sự kiện xảy ra đối với một nguồn sự

kiện, nó sẽ gửi thông báo này tới tất cả các bộ lắng nghe sự kiện được đăng ký cho sự kiện đó.

Đối với một ngôn ngữ OOP như Java thì toàn bộ thông tin về sự kiện được đóng gói trong

một lớp event. Tất cả các lớp event đều dẫn xuất từ lớp java.util.EventObject. Mỗi loại sự kiện

tương ứng với một lớp dẫn xuất, chẳng hạn như ActionEvent và WindowEvent. Sau đây là cây

phân cấp chỉ sự kế thừa giữa các lớp sự kiện trong Java:

Page 94: Bai giang JAVA

94

Các sự kiện trên được gửi cho các đối tượng lắng nghe tương ứng như: ActionListener

MouseMotionListener

AdjustmentListener MouseWheelListener

FocusListener WindowListener

ItemListener WindowFocusListener

KeyListener WindowStateListener

MouseListener

Các nguồn sự kiện khác nhau có thể phát sinh các sự kiện khác nhau. Ví dụ một button

(nút bấm) thì phát sinh sự kiện ActionEvent trong khi một cửa sổ lại phát sinh sự kiện

WindowEvent.

Tóm lại, một sự kiện được quản lý dựa trên các khái niệm:

1. Một đối tượng lắng nghe là một biểu hiện của một lớp có cài đặt giao diện lắng

nghe sự kiện

2. Một nguồn sự kiện là một đối tượng mà có thể đăng ký các đối tượng lắng nghe và

gửi cho chúng các đối tượng sự kiện.

3. Nguồn sự kiện gửi đối tượng sự kiện tới tất cả các đối tượng lắng nghe được đăng

ký cho sự kiện đó.

4. Đối tượng lắng nghe sẽ sử dụng thông tin trong các đối tượng sự kiện để phản ứng

với các sự kiện đó.

Cú pháp để đăng ký các đối tượng lắng nghe cho các nguồn sự kiện theo cú pháp sau:

<nguồn sự kiện>.add<sự kiện>Listener(<đối tượng lắng nghe sự kiện>)

Ví dụ:

ActionListener listener = . . .; // đối tượng lắng nghe

JButton button = new JButton("Ok"); // Nguồn sự kiện

button.addActionListener(listener); // đăng ký đối tượng lắng nghe sự kiện

Trong đoạn code trên, vấn đề còn lại là đối tượng lắng nghe sự kiện phải có một phương

thức để nhận về sự kiện từ nguồn sự kiện đăng ký nó và xử lý. Ở đây, đối tượng listener phải

thuộc một lớp có cài đặt giao diện ActionListener. Trong giao diện này có khai báo một phương

thức actionPerformed để nhận về một sự kiện ActionEvent:

class MyListener implements ActionListener

{

. . .

public void actionPerformed(ActionEvent event)

{

// Đoạn mã xử ký sự kiện đặt ở đây

. . .

}

}

Bất cứ khi nào người dùng click chuột vào đối tượng Jbutton trên màn hình, một sự kiện

ActionEvent được phát sinh và gửi cho đối tượng lắng nghe listener. Đối tượng này có cài đặt

một phương thức để xử lý sự kiện là actionPerformed, lấy đối số là đối tượng ActionEvent nhận

được.

Có thể có nhiều bộ lắng nghe được đăng ký cho một nguồn sự kiện, khi đó sự kiện cũng

được gửi tới tất cả các bộ lắng nghe và tới phương thức actionPerformed của chúng.

Sơ đồ sequence cho đoạn code trên như sau:

Page 95: Bai giang JAVA

95

Sau đây là một ví dụ về xử lý sự kiện click cho 3 đối tượng Jbutton:

Một Button được tạo ra như sau bằng cách gọi constructor của JButton với một chuỗi

nhãn hoặc một ảnh hay cả hai:

JButton yellowButton = new JButton("Yellow");

JButton blueButton = new JButton(new ImageIcon("blue-ball.gif"));

Thêm 3 Button vào 1 panel như sau:

Class ButtonPanel extends JPanel

{

public ButtonPanel()

{

JButton yellowButton = new JButton("Yellow");

JButton blueButton = new JButton("Blue");

Page 96: Bai giang JAVA

96

JButton redButton = new JButton("Red");

add(yellowButton);

add(blueButton);

add(redButton);

}

}

Bây giờ chúng ta định nghĩacác bộ lắng nghe cho các Button này gọi là ColorAction như

sau:

public class ColorAction implements ActionListener

{

public ColorAction(Color c)

{

backgroundColor =c;

}

public void actionPerformed(ActionEvent e)

{

setBackground(backgroundColor); // Thay đổi màu nền của panel khi Button được click

}

private Color backgroundColor;

}

Mỗi đối tượng Button được đăng ký cho bộ lắng nghe này:

Class ButtonPanel extends JPanel

{

public ButtonPanel()

{

JButton yellowButton = new JButton("Yellow");

JButton blueButton = new JButton("Blue");

JButton redButton = new JButton("Red");

add(yellowButton);

add(blueButton);

add(redButton);

ColorAction yellowAction = new ColorAction(Color.Yellow);

ColorAction blueAction = new ColorAction(Color.Blue);

ColorAction redAction = new ColorAction(Color.Red);

yellowButton.addActionListener(yellowAction);

blueButton.addActionListener(blueAction);

redButton.addActionListener(redAction);

}

}

Một vấn đề đặt ra là phương thức setBackground() không được định nghĩa trong lớp

ColorAction mà chỉ được định nghĩa cho lớp Panel. Giải pháp ở đây là đưa lớp ColorAction

Page 97: Bai giang JAVA

97

thành lớp nội của lớp ButtonPanel, khi đó trong lớp ColorAction, ta có thể truy cập các phương

thức của lớp Panel (được ButtonPanel kế thừa) như setBackground chẳng hạn.

Class ButtonPanel extends JPanel

{

public ButtonPanel()

{

JButton yellowButton = new JButton("Yellow");

JButton blueButton = new JButton("Blue");

JButton redButton = new JButton("Red");

add(yellowButton);

add(blueButton);

add(redButton);

ColorAction yellowAction = new ColorAction(Color.Yellow);

ColorAction blueAction = new ColorAction(Color.Blue);

ColorAction redAction = new ColorAction(Color.Red);

yellowButton.addActionListener(yellowAction); // Đăng ký bộ lắng nghe sự kiện

blueButton.addActionListener(blueAction);

redButton.addActionListener(redAction);

}

private class ColorAction implements ActionListener

{

public ColorAction(Color c)

{

backgroundColor =c;

}

public void actionPerformed(ActionEvent e)

{

setBackground(backgroundColor); // Thay đổi màu nền của panel khi Button được click

}

private Color backgroundColor;

}

}

Chương trình sau đây kiểm tra sự thực hiện đáp ứng các sự kiện vừa thiết kế ở trên:

import javax.swing.JFrame;

public class testPanel extends JFrame

{

public testPanel()

{

ButtonPanel pn = new ButtonPanel();

this.add(pn);

}

public static void main(String[] argvs)

Page 98: Bai giang JAVA

98

{

testPanel p = new testPanel();

p.setSize(300,400);

p.setVisible(true);

}

}

Thông thường, các lớp lắng nghe sự kiện có thể được cài đặt ngay trong phương thức

addActionListener như sau:

yellowButton.addActionListener(

new ActionListener()

{

public void actionPerformed(ActionEvent event)

{

setBackground(Color.YELLOW);

}

});

Làm như vậy ta không cần thiết kế riêng một lớp ColorAction.

II. Truy cập thông tin sự kiện

Một phương pháp khác để lập trình sự kiện đó là gán cho tất cả các đối tượng nguồn sự

kiện chung một đối tượng lắng nghe. Tùy theo thông tin về sự kiện nhận được, phương thức

actionPerformed sẽ có sự hành xử khác nhau. Muốn vậy, lớp chứa các nguồn sự kiện phải cài đặt

giao diện ActionListener.

import javax.swing.*;

import java.awt.event.*;

public class ButtonPanel extends JPanel implements ActionListener

{ JButton yellowButton;

JButton blueButton;

JButton redButton;

public ButtonPanel()

{

yellowButton = new JButton("Yellow");

blueButton = new JButton("Blue");

redButton = new JButton("Red");

add(yellowButton);

add(blueButton);

add(redButton);

yellowButton.addActionListener(this);

blueButton.addActionListener(this);

redButton.addActionListener(this);

}

public void actionPerformed(ActionEvent event)

{

if (event.getSource()==yellowButton) setBackground(Color.YELLOW);

if (event.getSource()==redButton) setBackground(Color.RED);

Page 99: Bai giang JAVA

99

if (event.getSource()==blueButton) setBackground(Color.BLUE);

}

}

Trong ví dụ trên, bản thân lớp component ButtonPanel đóng vai trò là lớp lắng nghe sự

kiện vì nó có cài đặt giao diện ActionListener. Do đó, khi đăng ký đối tượng lắng nghe cho các

Button, ta chỉ việc sử dụng biến this, đại diện cho đối tượng ngầm định của chính lớp

ButtonPanel. Các đối tượng Button bây giờ cũng phải khai báo là biến thành phần của lớp vì

chúng được truy cập trong 2 phương thức khác nhau. Tuy nhiên phương pháp này sẽ trở nên khó

dùng khi trên panel có nhiều đối tượng nguồn sự kiện.

III. Xử lý các sự kiện trên window

Phần trên đã cho thấy cách thức chúng ta làm việc với các nguồn sự kiện là các đối tượng

nằm trong một window. Phần này ta sẽ xem xét các sự kiện xảy ra đối với bản thân một window.

Muốn bắt các sự kiện của window, ta cũng qua các bước căn bản sau:

WindowListener listener = new .....

frame.addWindowListener(listener);

Trong đó frame là một đối tượng của lớp JFrame, là đối tượng nguồn sự kiện phát sinh

các sự kiện WindowEvent. Đối tượng listener bắt buộc phải thuộc một lớp có cài đặt giao diện

WindowListener. Cấu trúc của giao diện này như sau:

public interface WindowListener

{

void windowOpened(WindowEvent e);

void windowClosing(WindowEvent e);

void windowClosed(WindowEvent e);

void windowIconified(WindowEvent e); // thu nhỏ của sổ

void windowDeiconified(WindowEvent e);

void windowActivated(WindowEvent e);

void windowDeactivated(WindowEvent e);

}

Do đó các lớp cài đặt giao diện này phải khai báo định nghĩa tất cả các phương thức trên.

Tuy nhiên, ta chỉ viết code cho phương thức nào ta xử lý mà thôi, ví dụ:

class Terminator implements WindowListener

{

public void windowClosing(WindowEvent e)

{

System.exit(0);

}

public void windowOpened(WindowEvent e) {}

public void windowClosed(WindowEvent e) {}

public void windowIconified(WindowEvent e) {}

public void windowDeiconified(WindowEvent e) {}

public void windowActivated(WindowEvent e) {}

public void windowDeactivated(WindowEvent e) {}

}

Page 100: Bai giang JAVA

100

IV. Các lớp thích nghi

Ta thấy rằng việc khai báo đầy đủ 7 phương thức, có những phương thức không xử lý gì

cả làm cho chương trình không được tối ưu. Giải pháp ở đây sẽ là định nghĩa một lớp trung gian,

khai báo cài đặt giao diện WindowListener với đầy đủ 7 phương thức nhưng các phương thức

này cũng không làm gì cả. Các lớp muốn cài đặt nội dung cho một sự kiện chỉ việc khai báo kế

thừa lớp này và định nghĩa chồng phương thức cần thiết. Các lớp có vai trò trung gian như vậy

gọi là các lớp thích nghi. Với mỗi giao diện lắng nghe, ta có một lớp thích nghi tương ứng. Ví dụ:

WindowListener có lớp thích nghi WindowAdapter, MouseListener có MouseAdapter. Các lớp

thích nghi thường dùng là:

FocusAdapter MouseMotionAdapter

KeyAdapter WindowAdapter

MouseAdapter

class Terminator extends WindowAdapter

{

public void windowClosing(WindowEvent e)

{

System.exit(0);

}

}

Vấn đề là các lớp window thường phải khai báo kế thừa từ JFrame rồi nên không thể khai

báo kế thừa thêm lớp WindowAdapter. Lúc này, kỹ thuật định nghĩa lớp nội nặc danh được phát

huy:

frame.addWindowListener(new WindowAdapter()

{

public void windowClosing(WindowEvent event)

{

System.exit(0);

}

public void windowIconified(WindowEvent e) {System.exit(0);}

} );

Đoạn code này thực hiện các công việc sau:

1. Định nghĩa một class nặc danh kế thừa lớp WindowAdapter

2. Thêm 2 phương thức windowClosing và windowIconified cho lớp nặc danh đó

3. Kế thừa 5 phương thức còn lại từ WindowAdapter

4. Tạo ra một đối tượng của lớp đó, đối tượng cũng không có tên

5. Gửi đối tượng này cho phương thức addWindowListener

Ta có thể định nghĩa chồng nhiều hơn một phương thức của WindowAdapter.

Tất nhiên là không phải khi nào ta cũng phải sử dụng lớp nội nặc danh. Một cách làm

khác là khai báo một lớp (thường là lớp nội) dạng như class Terminator ở trên, sau đó đăng ký

lắng nghe sự kiện cho frame mà không cần một đối tượng có tên rõ ràng của Terminator:

frame.addWindowListener(new Terminator());

Để kết thúc đề tài này ta liệt kê các phương thức xử lý sự kiện như bảng sau:

Page 101: Bai giang JAVA

101

Interface Methods Parameter/Accessors Nguồn sự kiện

ActionListener actionPerformed ActionEvent

getActionCommand

getModifiers

AbstractButton

JComboBox

JTextField

Timer

AdjustmentListener adjustmentvalueChanged AdjustmentEvent

getAdjustable

getAdjustmentType

getValue

JScrollbar

ItemListener ItemstateChanged ItemEvent

getItem

getItemSelectable

getStateChange

AbstractButton

JComboBox

FocusListener FocusGained

focusLost

FocusEvent

isTemporary

Component

KeyListener keyPressed

keyReleased

keyTyped

KeyEvent

getKeyChar

getKeyCode

getKeyModifiersText

getKeyText

isActionKey

Component

MouseListener mousePressed

mouseReleased

mouseEntered

mouseExited

mouseClicked

MouseEvent

getClickCount

getX

getY

getPoint

TRanslatePoint

Component

MouseMotionListener mouseDragged

mouseMoved

MouseEvent Component

Page 102: Bai giang JAVA

102

Interface Methods Parameter/Accessors Nguồn sự kiện

MouseWheelListener mousewheelMoved MouseWheelEvent

getWheelRotation

getScrollAmount

Component

WindowListener windowClosing

windowOpened

windowIconified

windowDeiconified

windowClosed

windowActivated

windowDeactivated

WindowEvent

getWindow

Window

WindowFocusListener windowGainedfocus

windowlostFocus

WindowEvent

getOppositeWindow

Window

WindowStateListener WindowStateChanged WindowEvent

getOldState

getNewState

Window

V. Xử lý các sự kiện chuột

Các sự kiện với chuột được xử lý bởi giao diện MouseListener. Khi một nguồn sự kiện

được kích hoạt bởi việc click chuột, các phương thức xử lý cho các sự kiện tương ứng được liệt

kê trong bảng trên, đặc biệt hay dùng là mouseClicked(). Thông thương ta cũng không cài đặt xử

lý cho tất cả các sự kiện này nên ta không cài đặt giao diện MouseListener mà khai báo một lớp

nội nặc danh kế thừa từ lớp thích nghi MouseAdapter.

Giả sử có một đối tượng JFrame tên là frame, sau đây là một ví dụ quản lý sự kiện click

chuột trên nó:

frame. addMouseListener( new MouseAdapter()

{

public void mouseClicked(MouseEvent e) // Mac dinh la chuot trai

{ // Kiem tra neu la chuot phai duoc click

if( (e.getModifiers() & InputEvent.BUTTON3_MASK)== InputEvent.BUTTON3_MASK)

// hien thi mot popup menu tai vi tri click

jp.show(getContentPane(),e.getX(),e.getY());

}

} );

Tham khảo thêm tại:

http://java.sun.com/docs/books/tutorial/uiswing/events/handling.html

Page 103: Bai giang JAVA

103

và http://java.sun.com/docs/books/tutorial/uiswing/events/mouselistener.html

Bài tập

1. Viết chương trình xử lý sự kiện chuột click trên các Botton, nếu là chuột trái thì thông báo

là “Bạn vừa click chuột trai”, nếu là chuột phải thì thông báo “Bạn vừa click chuột phải”.

2. Viết chương trình sau khi chọn một Button trên màn hình, nhấn phím x thì chương trình

kết thúc.

Page 104: Bai giang JAVA

104

Đề tài 9. Applet

Applet là một trong những kỹ thuật vượt trội của Java so với các ngôn ngữ khác. Một

Applet là một chương trình Java được nhúng vào trong các trang web, nó đứng một vị trí độc lập

bên cạnh các phần khác của trang web.

I. Xây dựng một Applet đơn giản

1. Soạn thảo một tệp có tên “Hello.java” như sau:

import java.applet.Applet; //khai báo thư viện

import java.awt.Graphics;

//Khai báo đồ hoạ

public class Hello extends Applet {

//cài đặt phương thức cho Applet

public void paint(Graphics g){

g.drawString("Hello!", 50, 25);

}

2. Biên dịch tệp Hello.java

3. Soạn thảo một trang HTML có tên hello.htm

<html><body>

<applet>

<applet code="Hello.class" width=150 height=25>

</applet>

</body></html>

4. Đặt file Hello.class và hello.htm vào trong cùng một thư mục

5. Mở file hello.htm.

Tuy nhiên để các applet có thể chạy được, nó cần một JVM trên máy cục bộ. Để có được

JVM cho các trình duyệt ta cần cài phiên bản Java lên máy tính cục bộ và tích hợp vào trình

duyệt như một plug-in.

Trong các phiên bản Java gần đây, người lập trình có thể sử dụng thư viện swing nằm

trong gói javax.swing để có được giao diện GUI thống nhất trên mọi hệ thống. Các lớp trong

swing có tên gọi khác so với các lớp trong awt bởi thêm ký tự đầu tiên “J”.

II. Cấu trúc cơ bản và vòng đời của một Applet

Một chương trình Applet đầy đủ sẽ bao gồm các thành phần như sau:

import java.applet.Applet;

public class myApplet extends Applet{

public void init(){ ...... }

public void start(){ ...... }

public void stop() { ...... }

public void destroy() { ...... }

.... //Các phương thức khác

}

Nếu dùng JApplet thì ta có khai báo phần đầu như sau:

import javax.swing.JApplet;

public class myApplet extends JApplet{…}

Page 105: Bai giang JAVA

105

Vòng đời của một Applet được đánh dấu bởi các sự kiện diễn ra ở mỗi giai đoạn, lập trình

viên cần nắm được ý nghĩa của từng giai đoạn để có thể viết code điều khiển Applet:

1. Giai đoạn init: Thực hiện các công việc khởi tạo một Applet. Giai đoạn này được

bắt đầu ngay sau khi thẻ <param> nằm trong thẻ <applet> được xử lý. Các hành

động như thêm các thành phần giao diện người dùng GUI được thực hiện ở đây.

2. Giai đoạn start: Được thực hiện ngay sau khi giai đoạn init được thực hiện xong.

Nó cũng được gọi bất cứ khi nào người dùng chuyển sang một trang web khác rồi

quay lại trang có applet. Do đó, code nằm trong start có thể được thực hiện nhiều

lần trong khi code trong init chỉ được thực hiện 1 lần.

3. Giai đoạn stop: Được thực hiện khi người dùng rời khỏi trang web chứa applet.

Do đó, code nằm trong stop cũng có thể được thực hiện nhiều lần.

4. Giai đoạn destroy: Được thực hiện khi người sử dụng tắt trình duyệt.

Khi viết một applet, chúng ta không phải khi nào cũng cài đặt đầy đủ 4 phương thức mà

tùy theo nhu cầu.

Ví dụ sau xây dựng một applet cho phép vẽ liên tiếp bắt đầu từ vị trí giữa applet.

import java.applet.*;

import java.awt.*;

import java.awt.event.*;

public class AppletSample extends Applet

{

Point curentPoint; // Lưu tọa độ điểm hiện tại

public void init()

{

curentPoint = new Point(this.getWidth()/2,this.getHeight()/2);

this.setBackground(Color.CYAN); // đặt màu nền của applet

}

public void start()

{

this.addMouseListener( new MouseAdapter()

{

public void mouseClicked(MouseEvent e)

{

drawOnApplet(curentPoint,e.getPoint());

curentPoint = e.getPoint();

}

}

);

}

public void drawOnApplet(Point p1, Point p2)

{

Graphics g = this.getGraphics();

g.drawLine(p1.x,p1.y,p2.x,p2.y);

}

}

Page 106: Bai giang JAVA

106

III. An ninh và khả năng của Applet

Vì applet được download từ xa và thực hiện trên máy tính cụ bộ nên vấn đề về an ninh

được quan tâm đặc biệt. Các nguyên tắc về an ninh của một applet là:

Applet không bao giờ thực hiện một chương trình của máy cục bộ.

Applet không thể giao tiếp với các máy tính khác trên mạng trừ máy tính mà nó

được download về.

Applet không thể đọc và ghi dữ liệu lên máy tính cục bộ

Applet không thể tìm thấy thông tin gì về máy tính cuc bộ, trừ các thông tin như

phiên bản Java, tên và phiên bản hệ điều hành, ký tự phân tách file, đường dẫn.

Applet không thể tìm thấy các thông tin cá nhân như email, password,…

Tất cả các cửa sổ trình duyệt có applet được tải về đều có thông báo.

Những yêu cầu về an ninh của applet là rất quan trọng. Trong một số trường hợp ta có thể

cấu hình để applet được tin cậy và có thể truy cập vào máy tính cục bộ giống như một chương

trình đang chạy trên máy tính đó.

Applet cũng có những khả năng như:

Tạo kết nối đến máy đang chạy nó.

Applet dễ dàng dùng các siêu văn bản hiển thị.

Có thể gọi đến các phương thức toàn cục của các applet khác trên cùng trang web.

Applet có thẻ giao tiếp với các applet khác trên trang web cũng như với các đối

tượng khác trên trang web thông qua cơ chế riêng.

Các applet được nạp từ hệ thống tập tin cục bộ sẽ không bị các giới hạn của các

applet được nạp từ mạng xuống.

Không nhất thiết là các applet sẽ ngừng lại khi ta thoát khỏi các trang web chứa

nó.

IV. Ứng dụng Applet với của sổ Popup

Với Applet chúng ta hoàn toàn có thể có thêm các cửa sổ pop-up để mở rộng không gian

làm việc. Sau đây là một Japplet có thể mở một Frame mới.

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class PopupCalculatorApplet extends JApplet

{

public void init()

{

// Tạo một frame với một cửa sổ panel

final JFrame frame = new JFrame();

frame.setTitle("Calculator");

frame.setSize(200, 200);

// Thêm một Button để ẩn/ hiện frame pop-up

JButton calcButton = new JButton("Calculator");

add(calcButton);

calcButton.addActionListener(new

ActionListener()

{

Page 107: Bai giang JAVA

107

public void actionPerformed(ActionEvent event)

{

frame.setVisible(!frame.isVisible());

}

});

}

}

V. Các thẻ HTML của Applet

Một khai báo applet trong trang HTML thường có dạng:

<applet code="NotHelloWorldApplet.class" width="300" height="100">

Thong tin duoc hien thi khi applet khong hien thi

</applet>

Sau đây ta sẽ tìm hiểu các thuộc tính của applet:

Các thuộc tính về vị trí:

height: Chiều cao của applet. Các applet không thể thay đổi kích thước khi đã

chạy.

width: Chiều rộng của applet

align: Xác định vị trí của applet so với các văn bản xung quanh nó. Các giá trị của

align có thể là: left, right, middle, top, texttop, absmiddle, baseline, bottom,

absbottom, vspace và hspace.

Các thuộc tính về chương trình nguồn- code:

code : Thuộc tính này cho biết tên của class chứa chương tình applet. Tên này là tương

đối so với giá trị codebase hoặc với thư mục hiện hành nếu không có codebase. Đường dẫn phải

phù hợp với đường dẫn gói của class applet. Ví dụ: nếu applet có tên MyApplet.class được đặt

trong gói com.mycompany thì đường dẫn phải là:

code="com/mycompany/MyApplet.class".

hoặc:

code="com.mycompany.MyApplet.class" cũng được chấp nhận.

- codebase: Là một thuộc tính tùy chọn để xác định đường dẫn tuyệt đối nơi chứa class ở

giá trị code.

archive: Chứa tên các gói chương trình hoặc tài nguyên khác được tải về kèm theo applet.

Các gói chương trình được nén ở dạng file JAR và được đặt cách nhau bởi dấu ,. Ví dụ:

<applet code="CalculatorApplet.class"

archive="CalculatorClasses.jar,corejava/CoreJavaClasses.jar"

width="100" height="150">

object: Chứa tên file đã được tuần tự hóa của một applet.

name: Tên của applet. Trong các trình duyệt của Netscape hoặt Windows đều cho phép

applet giao tiếp với các đối tượng javascript khác trên trang web. Khi đó applet cần có tên để truy

cập.

Ngoài ra Java cho phép ta định nghĩa các tham số cho applet thông qua các thẻ <param>

Ví dụ:

<applet code="FontParamApplet.class" width="200" height="200">

<param name="font" value="Helvetica"/>

<param name="size" value="24"/>

Page 108: Bai giang JAVA

108

</applet>

Khi đó trong chương trinh applet, ta có thể lấy ra để sử dụng:

public class FontParamApplet extends JApplet

{

public void init()

{

String fontName = getParameter("font");

int fontSize = Integer.parseInt(getParameter("size"));

. . .

}

}

VI. Các phương thức, lập trình đồ họa và bắt sự kiện của applet

public void paint(Graphics g) {...}: Là phương thức hiển thị cơ bản, thường các

applet dùng paint() để biểu diễn các hoạt động của mình trên trang web.

public void update(Graphics g) {...}: là phương thức ta dùng sau khi thực hiện

pain() nhằm làm tăng hiệu quả vẽ.

Ngoài ra Applet còn thừa hưởng các phương thức từ lớp AWT.

Phương thức repaint() được dùng khi cửa sổ cần cập nhật lại. Phương thức này chỉ

cần một tham số là đối tượng của lớp Graphics.

getDocumentBase(): cho biết địa chỉ dạng URL của thư mục chứa tập tin HTML

chứa applet.

getCodeBase(): Cho biết địa chỉ dạng URL của thư mục chứa tập tin .CLASS của

applet.

getImage(URL url, String name): trả về một đối tượng ảnh hiển thị trên nền.

getLocale(): Xác định vị trí applet.

getAudioClip(URL url, String name): cho đối tuợng audio.

showStatus(String st): hiển thị xâu st trên thanh trang thái.

drawChars(char array[ ], int offset, int length, int xCoor, int yCoor): xuất các ký

tự. Chú thích các tham số: array: Mảng các ký tự; offset: Vị trí bắt đầu, nơi các ký

tự được vẽ.; length: Số các ký tự cần được vẽ; xCoor: Toạ độ X, nơi các ký tự cần

được vẽ; yCoor: Toạ độ Y, nơi các ký tự cần được vẽ.

drawBytes(byte array[ ], int offset, int length, int xCoor, int yCoor): xuất các byte

ra.Trong đó array: Mảng các byte.;Vị trí offset hay vị trí bắt đầu; length: Số byte

cần vẽ; xCoor: Toạ độ X; yCoor: Toạ độ Y.

drawLine(int x1, int y1, int x2, int y2): Vẽ đường thẳng từ A(x1, y1) đến B(x2,

y2).

drawOval(int xCoor, int yCoor, int width, int height): Vẽ đường oval.

fillOval(int xCoor, int yCoor, int width, int height): Vẽ hình oval đặc.Trong đó:

width là Chiều rộng của hình, height là Chiều cao của hình.

drawRect(int xCoor, int yCoor, int width, int height): Vẽ hình chữ nhật.

fillRect(int xCoor, int yCoor, int width, int height): Vẽ hình chữ nhật đặc.

drawRoundRect(int xCoor, int yCoor, int width, int height, int arcwidth, int

archeight): Vẽ hình chữ nhật có bo góc.

Page 109: Bai giang JAVA

109

fillRoundRect(int xCoor, int yCoor, int width, int height, int arcwidth, int

archeight): vẽ hình chữ nhật bo góc đặc.

Trong đó: arcwidth: làm tròn góc trái và góc phải của hình chữ nhật.

archeight: làm tròn góc trên đỉnh và góc đáy của hình chữ nhật.

Ví dụ, arcwidth = 20 có nghĩa là hình chữ nhật được làm tròn cạnh trái và cạnh phải mỗi

cạnh 10 pixel.

draw3Drect(int xCoord, int yCoord, int width, int height, boolean raised): Vẽ hình

chữ nhật 3D.

drawArc(int xCoord, int yCoord, int width, int height, int arcwidth, int archeight):

Vẽ hình cung.

fillArc(int xCoord, int yCoord, int width, int height, int arcwidth, int archeight):

Vẽ hình cung đặc.

Trong đó: xCoord: Toạ độ x; yCoord: Toạ độ y.

width: Chiều rộng của cung được vẽ; height: Chiều cao của cung được vẽ.

arcwidth: Góc bắt đầu; archeight: Độ rộng của cung (góc của cung) so với góc ban đầu.

drawPolyline(int xArray[ ], int yArray[ ], int totalPoints): Vẽ nhiều đường thẳng

Trong đó: xArray: Mảng lưu trữ toạ độ x của các điểm; yArray: Mảng lưu trữ toạ độ y của

các điểm; totalPoints: Tổng số điểm cần vẽ.

setFont(new Font(“Times Roman”, Font.BOLD, 15)): Đặt Font cho chữ,

(Font.BOLD, Font.PLAIN, Font.ITALIC)

drawPolygon(int x[ ], int y[ ], int numPoints):Vẽ đa giác.

fillPolygon(int x[ ], int y[ ], int numPoints): Vẽ đa giác đặc.

Trong đó: x[ ]: Mảng lưu trữ toạ độ x của các điểm; y[ ]: Mảng lưu trữ toạ độ y của các

điểm; numPoints: Tổng số điểm cần vẽ; setColor(Color c): Đặt màu vẽ.

Bảng một số màu cơ bản:

Color.white Color.black

Color.orange Color.gray

Color.lightgray Color.darkgray

Color.red Color.green

Color.blue Color.pink

Color.cyan Color.magenta

Color.yellow

Page 110: Bai giang JAVA

110

Đề tài 10. Lập trình giao diện đồ họa GUI

I. Giới thiệu AWT

Abstract Windows Toolkit – AWT: Là thư viện của Java cung cấp cho lập trình viên các

giải pháp giao diện người dùng đồ hoạ (Graphical User Interface - GUI) thân thiện.

Một giao diện người dùng được hình thành từ các phần tử của GUI. Một phần tử GUI

được thiết lập bằng cách sử dụng các thủ tục:

1. Tạo đối tượng.

2. Xác định sự xuất hiện ban đầu của đối tượng.

3. Chỉ ra nó nằm ở đâu.

4. Thêm phần tử vào giao diện trên màn hình.

Để làm việc với các đối tượng GUI chúng ta cần nhập gói java.awt.*.

AWT cung cấp các thành phần khác nhau để tạo GUI hiệu quả, các thành phần này có thể

là:

Vật chứa (Container).

Thành phần (Component).

Trình quản lý cách trình bày (Layout manager).

Đồ hoạ (Graphics) và các tính năng vẽ (draw).

Phông chữ (Font).

Sự kiện (Event).

Từ phiên bản 1.4, Java phát triển một thư viện mở rộng mới với đa số các lớp GUI kế

thừa từ AWT nhưng có khả năng di động tốt hơn. Các lớp GUI trong swing có thêm tiền tố “J” so

với các lớp trong AWT. Sau đây, chúng ta sẽ xét các thành phần GUI trong swing.

Sơ đồ phân cấp thừa kế các đối tượng GUI trong swing như sau:

Page 111: Bai giang JAVA

111

II. Vật chứa (Container)

Là vùng mà ta có thể đặt các thành phần (component) của giao diện. Một vật chứa có thể

chứa nhiều phần tử. Vật chứa thường được sử dụng là:

JPanel - khung chứa đơn giản nhất, để nhóm các đối tượng con lại và sắp xếp theo

cách thích hợp.

JFrame - là một cửa sổ như mọi ứng dụng của windows, để tạo các ứng dụng

windows.

JDialogs - là cửa sổ nhưng không đầy đủ chức năng như Frame, nó là cửa sổ hộp

thoại đưa ra những lời thông báo.

JScrollPanel - khung chứa như Panel nhưng có hai thanh trượt.

II.1 JFrame

Tạo đối tượng khung chứa JFrame bằng phương thức khởi tạo: void JFrame();

Tạo Frame với tiêu đề bên trên: void JFrame(String FrameTitle);

Ví dụ:

JFrame frame1 = new JFrame();

JFrame frame2 = new JFrame("Cua so Frame");

import javax.swing.*;

public class FrameSample {

public static void main(String[] argvs)

{

JFrame f = new JFrame();

f.setSize(400,400);

f.setVisible(true);

}

}

Một số phương thức hay sử dụng:

Đặt lại kích thước cho JFrame: frame1.setSize(int width, int height);

Đưa cửa sổ hiện ra màn hình: frame1.show();

frame1.setVisible(boolean b); trong đó: b = true cho hiển thị, b = false cho

ẩn.

Bỏ hoàn toàn đối tượng JFrame: frame1.dispose();

Thay đổi tiêu đề cho JFrame: frame1.setTitle(String newTitle);

Lấy tiêu đề của JFrame: public String getTitle();

Co dãn JFrame: public void setResizable(boolean b); trong đó: b = true thì Frame

có thể thay đổi kích thước, b = false thì không đổi.

Xác định JFrame đang ở tình trạng nào: public boolean isResizable();

Thay đổi biểu tượng JFrame: public setIconImage(Image img);

II.2 JPanel

JPanel không thể nhìn thấy trực tiếp, nó là đối tượng dùng để chứa các thành phần GUI

trên màn hình. Do đó chúng ta cần gắn JPanel vào đối tượng nào đó như: JFrame, JApplet, ...

Tạo khung chứa JPanel bằng phương thức khởi tạo: JPanel panel1 = new JPanel();

Ví dụ sau tạo một đối tượng JPanel và đặt vào nó một đối tượng nút bấm JButton.

Page 112: Bai giang JAVA

112

import javax.swing.*;

public class FrameSample {

public static void main(String[] argvs)

{

JFrame f = new JFrame();

JPanel p = new JPanel();

p.add(new JButton("OK"));

f.add(p); // gắn JPanel vào JFrame

f.setSize(400,400);

f.setVisible(true);

}

}

II.3 JDialog

Như JFrame, nhưng ít chức năng hơn, còn được gọi là popup-window.

Ta có thể tạo JDialog dưới hai hình thức:

modal: là cửa sổ JDialog khi thực hiện sẽ khoá chặt các cửa sổ khác. Cửa sổ này

thường yêu cầu một tác vụ nào đó cần phải hoàn thành ngay.

non-modal: ngược lại với modal, cửa sổ này thích ứng với các thao tác mang t ính

tuỳ biến.

Cách tạo khung chứa JDialog từ phương thức khởi tạo:

public JDialog(JFrame parentWindow, boolean isModal);

trong đó: isModal - quyết định xem JDialog được tạo ra ở dạng nào: isModal = true cho

modal còn isModal = false cho non-modal.

Ví dụ: JDialog myDialog = new JDialog(myWindow, true)

Tạo JDialog có tiêu đề định trước:

public JDialog(Frame parentWindow, String title, boolean isModal)

JDialog không thể gắn với Applet, muốn đưa ra một JDialog từ JApplet ta phải tạo ra một

JFrame giả tạo.

Đưa đối tượng JDialog ra màn hình bằng phương thức show().

Giấu cửa sổ JDialog ta dùng phương thức: hide().

Ẩn hiện JDialog ta còn có phương thức: setVisible(boolean).

Các đặc điểm thường sử dụng với đối tượng JDialog thể hiện tương tự với JFrame.

Lấy và thay đổi kích thước JDialog: public setResizable(boolean), boolean isResizable()

Đặt và lấy tiêu đề của JDialog: void setTitle(String), String getTitle();

Xác minh một JDialog đang thuộc dạng nào ta gọi phương thức: public boolean isModal()

Chương trình sau đây sẽ ẩn hoặc hiện một Jdialog mỗi khi nhất vào một nút bấm:

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class FrameSample extends JFrame

{ private JDialog d;

public FrameSample() // Constroctor

{

Page 113: Bai giang JAVA

113

d = new JDialog(this,"Day la Jdialog",false);

d.setSize(100,100);

JPanel p = new JPanel();

JButton b = new JButton("Xem/Tat mot JDialog");

b.addActionListener( new ActionListener()

{

public void actionPerformed(ActionEvent e)

{

d.setVisible(!d.isVisible());

}

}

);

p.add(b);

add(p);

}

public static void main(String[] argvs)

{

FrameSample fs = new FrameSample();

fs.setSize(400,400);

fs.setVisible(true);

}

}

II.4 JScrollPane

Đây không phải là một cửa sổ nhưng có tính chất như khung chứa JPanel dùng để chứa

các đối tượng. Tính chất khác là khi đối tượng nó chứa quá lớn thì JScrollPane sẽ xuất hiện thanh

trượt đứng và ngang ở hai bên viền để ta có thể xem được toàn bộ. JScrollPane được ứng dụng

trong các danh sách chọn.

III. Giới thiệu về các thành phần GUI cơ bản

Jlabel: Chỉ một vùng hiển thị văn bản hoặc các icon.

JtextField: Chỉ một đối tượng cho phép nhập dữ liệu từ bàn phím.

JButton: Đối tượng nút bấm

JcheckBox: Đối tượng nút chọn.

JcomboBox: Đối tượng ComboBox

Jlist: Danh sách

JPanel: Nơi đặt các thành phần GUI nói trên.

III.1 Nút nhấn

Cách tạo nút nhấn

Ta gọi phương thức khởi dựng: public Button(String label) label là tên nhãn của nút nhấn

Ví dụ: Button nutOK = new Button("OK");

Đư nút nhấn vào Applet hay cửa sổ chương trình bằng lệnh: add(nutOK);

Để đổi tên nhãn cho nút nhấn ta gọi phương thức public void setLabel(String newLabel).

Để xem tên nhãn hiện tại của nút nhấn, ta gọi phương thức public String getLabel()

Page 114: Bai giang JAVA

114

Ví dụ: Button nutOK = new Button(); nutOK.setLabel("OK");

Sử dụng nút nhấn

Khi kích chuột vào nút nhấn sẽ thực hiện một công việc nào đó. Vấn đề này chúng ta đã

xem xét trong phần xử lý các sự kiện

III.2 Nhãn (Label)

Tạo nhãn không có nội dung gì: public Label() hoặc tạo nhãn có nội dung: public

Label(String nameLabel).

hoặc thêm chế độ căn lề: pubic Label(String name, int align)

Một số phương thức hay sử dụng:

setText(String nameLabel): Đặt lại nội dung mới cho nhãn.

Label.CENTER, Label.LEFT, Label.RIGHT: những giá trị căn lề.

Lấy nội dung hiện hành của nhãn: public String getText();

Xem nhãn đang được căn lề ở chế độ nào: public int getAlignment();

Thiết lập lại chế độ căn lề: public void setAlignment(int align) throws

IlligalArgumentException

Sau đây là ví dụ sử dụng JLabel:

// Minh họa về JLabel

// Nhập các gói thư viện

import java.awt.*;

import java.awt.event.*;

// Gói Java mở rộng

import javax.swing.*;

public class LabelTest extends JFrame {

private JLabel label1, label2, label3;

// Tạo giao diện GUI

public LabelTest()

{

super( "Testing JLabel" ); // Contructor của JFrame

// Lấy đối tượng pane của một JFrame

Container container = getContentPane();

container.setLayout( new FlowLayout() );

// constructor của JLabel

label1 = new JLabel( "Label with text" );

label1.setToolTipText( "This is label1" ); // hiển thị khi di chuột đến

container.add( label1 ); // thêm vào container

// Tạo Jlabel với icon hoặc text

Icon bug = new ImageIcon( "bug1.gif" );

label2 = new JLabel( "Label with text and icon", bug, SwingConstants.LEFT );

label2.setToolTipText( "This is label2" );

container.add( label2 );

Page 115: Bai giang JAVA

115

// JLabel không tham số

label3 = new JLabel();

label3.setText( "Label with icon and text at bottom" );

label3.setIcon( bug );

label3.setHorizontalTextPosition( SwingConstants.CENTER );

label3.setVerticalTextPosition( SwingConstants.BOTTOM );

label3.setToolTipText( "This is label3" );

container.add( label3 );

setSize( 275, 170 );

setVisible( true );

}

// hàm main

public static void main( String args[] )

{

LabelTest application = new LabelTest();

application.setDefaultCloseOperation(

JFrame.EXIT_ON_CLOSE );

}

}

III.3 Nút đánh dấu (checkbox)

Một nút đánh dấu có hai phần: nhãn và dấu biểu hiện trạng thái.

Ta có thể tạo nút đánh dấu theo 5 phương thức khởi dựng:

public Checkbox(): tạo ô đánh dấu không có nhãn.

public Checkbox(String cbLabel): tạo ô đánh dấu với một nhãn cbLabel gắn kèm.

public Checkbox(String cbLabel, boolean state): Tạo ô đánh dấu với một nhãn

cbLabel gắn kèm với trạng thái ban đầu của ô đó.

public Checkbox(String cbLabel, boolean state, CheckboxGroup g);

public Checkbox(String cbLabel , CheckboxGroup g, boolean state): dùng để tạo ô

đánh dấu có nhãn với trạng thái đánh dấu ban đầu, nút tạo ra được nhóm trong

nhóm g. Nhóm các ô đánh dấu trở thành nút chọn.

Kiểm tra và thiết lập trạng thái:

Để kiểm tra một ô có được đánh dấu không ta dùng phương thức: public boolean

getState();

Nếu muốn thiết lập trạng thái, ta dùng phương thức: setState(boolean state).

Xử lý tình huống khi ô đánh dấu thay đổi trạng thái:

Để lắng nghe ô đánh dấu, ta dùng phương thức: addItemListener(ItemListener L)

Để loại bỏ lắng nghe đó ta dùng phương thức: removeItemListener(ItemListener L)

// Java core packages

import java.awt.*;

import java.awt.event.*;

Page 116: Bai giang JAVA

116

// Java extension packages

import javax.swing.*;

public class CheckBoxTest extends JFrame {

private JTextField field;

private JCheckBox bold, italic;

// Thiết lập GUI

public CheckBoxTest()

{

super( "JCheckBox Test" );

// lấy pane

Container container = getContentPane();

container.setLayout( new FlowLayout() );

// Đặt ô nhập và font chữ

field = new JTextField( "Theo dõi font chữ thay đổi", 20 );

field.setFont( new Font( "Serif", Font.PLAIN, 14 ) );

container.add( field );

// tạo đối tượng checkbox

bold = new JCheckBox( "Bold" );

container.add( bold );

italic = new JCheckBox( "Italic" );

container.add( italic );

// Đăng ký đối tượng lắng nghe

CheckBoxHandler handler = new CheckBoxHandler();

bold.addItemListener( handler );

italic.addItemListener( handler );

setSize( 275, 100 );

setVisible( true );

}

// execute application

public static void main( String args[] )

{

CheckBoxTest application = new CheckBoxTest();

application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

}

// Lớp nội lắng nghe sự kiện

private class CheckBoxHandler implements ItemListener {

private int valBold = Font.PLAIN;

private int valItalic = Font.PLAIN;

// Đáp ứng sự kiện chọn ô

public void itemStateChanged( ItemEvent event )

{

// xử lý chọn ô chữ đậm

if ( event.getSource() == bold )

Page 117: Bai giang JAVA

117

III.4 Nút chọn (radio button)

Tạo nút chọn:

Đây là trường hợp đặc biệt của ô đánh dấu. Ta tạo ra ô đánh dấu và đặt nó vào một nhóm,

ta có phương thức sau: public CheckboxGroup();

Với một nhóm các nút ta có thể lấy ra đối tượng hiện tại đang được chọn bằng cách gọi

phương thức getSelectedCheckbox().

Đặt lựa chọn ta dùng: setSelectedCheckbox().

Cách sử dụng nút chọn:

Ta tạo một đối tượng giao tiếp ItemListener để lắng nghe tình huống.

Phương thức getItemSelectable sẽ trả về đối tượng nơi mà tình huống phát sinh:

public ItemSelectable getItemSelectable();

Phương thức getItem của đối tượng ItemEvent sẽ cho ta biết giá trị nút chọn:

public Object getItem();

Sau đây là ví dụ về sử dụng ô chọn:

// Đăng ký đối tượng lắng nghe cho mỗi ô chọn radio

RadioButtonHandler handler = new RadioButtonHandler();

plainButton.addItemListener( handler );

boldButton.addItemListener( handler );

italicButton.addItemListener( handler );

boldItalicButton.addItemListener( handler );

// Nhóm các ô lại

radioGroup = new ButtonGroup();

radioGroup.add( plainButton );

radioGroup.add( boldButton );

radioGroup.add( italicButton );

radioGroup.add( boldItalicButton );

Về bắt các sự kiện cũng tương tự ô đánh dấu.

if ( event.getStateChange() = = ItemEvent.SELECTED )

valBold = Font.BOLD;

else

valBold = Font.PLAIN;

// Chọn ô chứ nghiêng

if ( event.getSource() == italic )

if ( event.getStateChange() == ItemEvent.SELECTED )

valItalic = Font.ITALIC;

else

valItalic = Font.PLAIN;

// Đặt lại font chữ của ô text

field.setFont(new Font( "Serif", valBold + valItalic, 14 ) );

} } }

Page 118: Bai giang JAVA

118

III.5 Hộp thoại Combo

Java hỗ trợ hộp thoại Combo thông qua đối tượng của class JComboBox. Đây là một danh

sách xổ xuống, đưa ra một danh sách các mục và ta chỉ được chọn 1 mục trong đó. JComboBox

cũng phát sinh sự kiện ItemEvent giống như JRadioButton và JCheckBox.

Chương trình sau đây minh họa việc sử dụng JComboBox với các phần tử là các ảnh GIF.

// Java core packages

import java.awt.*;

import java.awt.event.*;

// Java extension packages

import javax.swing.*;

public class ComboBoxTest extends JFrame {

private JComboBox imagesComboBox;

private JLabel label;

private String names[] = { "bug1.gif", "bug2.gif", "travelbug.gif", "buganim.gif" };

private Icon icons[] = { new ImageIcon(names[0]), new ImageIcon(names[1]), new

ImageIcon(names[2]), new ImageIcon(names[3])};

// Thiết lập GUI

public ComboBoxTest()

{

super( "Testing JComboBox" );

// Đặt layout

Container container = getContentPane();

container.setLayout( new FlowLayout() );

// khởi tạo combo

imagesComboBox = new JComboBox( names );

imagesComboBox.setMaximumRowCount( 3 );

imagesComboBox.addItemListener( new ItemListener() {

// bắt sự kiện

public void itemStateChanged( ItemEvent event )

{

// liệu có phần tử được chọn

if ( event.getStateChange() == ItemEvent.SELECTED )

label.setIcon( icons[imagesComboBox.getSelectedIndex() ] );

} } );

container.add( imagesComboBox );

// đặt một JLabel hiển thi ImageIcons tương ứng

label = new JLabel( icons[ 0 ] );

Page 119: Bai giang JAVA

119

container.add( label );

setSize( 350, 100 );

setVisible( true );

}

// hàm main

public static void main( String args[] )

{

ComboBoxTest application = new ComboBoxTest();

aplication.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

} }

III.6 Danh sách (Lists)

Lớp List cho phép ta tạo một danh sách các phần tử cho ta lựa chọn

Tạo một danh sách:

Phương thức khởi dựng mặc định: public List(). vd: List list = new List();

hoặc để chỉ định bao nhiêu phần tử sẽ được hiển thị cùng một lúc trong danh sách: public

List(int rows)

hoặc tạo một danh sách cho phép lựa chọn nhiều phần tử cùng một lúc: public List(int

rows, boolean multiMode)

Sử dụng danh sách chọn:

Đưa từng phần vào danh sách bằng lệnh add(String item).vd: list.add("Mau do");

Chèn một phần tử vào danh sách bằng phương thức add(String item, int index), index là

vị trí phần tử mà ta muốn chèn.

Thay thế một phần tử ở vị trí pos bằng phần tử mới: replaceItem(String newItem, int pos)

vd: list.replaceItem("Xanh", 4);

Loại bỏ một phần tử trong danh sách ta dùng phương thức remove(int pos).

Loại bỏ hết danh sách: removeAll().

Trả về vị trí của phần tử được chọn, nếu không có phần tử nào được chọn thì giá trị sẽ là -

1: getSelectedIndex(). Nếu được chọn nhiều thì dùng: int[] getSelectedIndex()

Lấy ra phần tử được chọn: getSelectedItem(). Chọn nhiều thì dùng: String[]

getSelectedItem().

Để chọn một phần tử mà ta biết vị trí: select(int index)

Nếu phần tử đang ở trạng thái chọn chuyển sang trạng thái bình thường: deselect(int

index)

Trạng thái của một phần tử: isSelected(int index)

Chuyển chế độ đơn chọn sang đa chọn: setMultiplesSelections(boolean bl)

Cho biết một danh sách là đơn chọn hay đa chọn: boolean isMultipleMode().

Sử dụng đối tượng danh sách:

Cài đặt giao tiếp ItemListener để tạo đối tượng biết lắng nghe sự thay đổi trạng thái của

các phần tử trong danh sách.

Sử dụng đối số ItemEvent trong phương thức itemStateChange để biết được chỉ số của

phần tử đang thay đổi trạng thái.

Page 120: Bai giang JAVA

120

Để xử lý được tình huống nhấp đôi chuột, ta cài đặt giao tiếp ActionListener và gắn nó

vào danh sách.

Phương thức getActionCommand() trong ActionEvent sẽ trả về tên của phần tử bị nhấp.

// Java core packages

import java.awt.*;

// Java extension packages

import javax.swing.*;

import javax.swing.event.*;

public class ListTest extends JFrame {

private JList colorList;

private Container container;

private String colorNames[] = { "Black", "Blue", "Cyan", "Dark Gray", "Gray", "Green",

"Light Gray", "Magenta", "Orange", "Pink", "Red", "White", "Yellow" };

private Color colors[] = { Color.black, Color.blue, Color.cyan, Color.darkGray,

Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red,

Color.white, Color.yellow };

// Thiết lập GUI

public ListTest()

{

super( "List Test" );

// lấy layout

container = getContentPane();

container.setLayout( new FlowLayout() );

// Tạo danh sách

colorList = new JList( colorNames );

colorList.setVisibleRowCount( 5 );

// Không cho chọn nhiều

colorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION );

// thêm một JScrollPane chứa danh sách

container.add( new JScrollPane( colorList ) );

// đặt lắng nghe sự kiện

colorList.addListSelectionListener( new ListSelectionListener() {

public void valueChanged( ListSelectionEvent event )

{

container.setBackground( colors[ colorList.getSelectedIndex() ] );

} } );

setSize( 350, 150 );

setVisible( true );

Page 121: Bai giang JAVA

121

}

// hàm main

public static void main( String args[] )

{

ListTest application = new ListTest();

application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

} }

III.7 Ô văn bản (text field) và vùng văn bản (text areas)

Tạo ô văn bản:

Khởi tạo một ô văn bản không xác định kích thước: public TextField();

Tạo một ô văn bản hiển thị tối thiểu numCols ký tự: public TextField(int

numCols);

Tạo một ô văn bản với nội dung là một chuỗi cho trước: public TextFiled(String

initText);

Tạo ô văn bản kết hợp: public TextField(String initText, int numCols);

Tạo vùng văn bản:

Tạo vùng văn bản rỗng, kích thước bất kỳ: public TextArea();

Tạo một vùng văn bản với nội dung cho trước: public TextArea(String initiaText);

Tạo một vùng văn bản với số cột và số dòng định trước: public TextArea(int rows,

int cols);

Tạo một vùng văn bản với số dòng số cột và nội dung cho trước: public

TextArea(String st, int rows, int cols)

Đặc điểm chung của các thành phần văn bản:

Hai lớp này được dẫn xuất từ lớp TextComponent

Muốn đưa nội dung văn bản vào các đối tượng này ta sử dụng phương thức setText:

public void setText(String newText);

Lấy nội dung văn bản trong các đối tượng: public String getText();

Lấy nội dung văn bản được đánh dấu: public String getSelectedText();

Để xác định xem vị trí đánh dấu khối văn bản bắt đầu và kết thúc ở đâu: public int

getSelectionStart(); //đầu

public int getSelectionEnd(); //cuối

Đánh dấu toàn bộ văn bản: public void selectAll();

Cho phép soạn thảo được: public void setEditable(boolean canEdited); canEdited = false:

chỉ đọc.

canEdited = true: thêm, sử được.

Xác định đối tượng đang ở trang thái nào: public boolean isEditable();

Đặc điểm riêng của TextField:

Đặt ký tự hiển thị cho ký tự nhập vào: public void setEchoChar(Char ch); ví dụ:

myTextField.setEchoChar('*'); //mã mKhẩu

Xác định xem ký tự làm ký tự hiển thị: public char getEchoChar();

Xác định chiều dài của ô văn bản theo ký tự: public int getColums();

Đặc điểm riêng của đối tượng TextArea:

Đưa thêm một dòng văn bản vào đối tượng: public void appendText(String newText);

Page 122: Bai giang JAVA

122

Chèn một chuỗi văn bản vào vị trí bất kỳ: public void insertText(String newText, int pos);

Xác định kích thước hiển thị: public int getRows(); public int getColums();

Sử dụng đối tượng TextField và TextArea:

Muốn lấy nội dung văn bản của đối tượng, ta thiết lập ActionListener để gắn đối tượng xử

lý tình huống vào văn bản TextField. Khi người dung nhấn Enter thì tình huống được gọi.

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class TextFieldTest extends JFrame {

private JTextField textField1, textField2, textField3;

private JPasswordField passwordField;

// Thiết lập giao diện GUI

public TextFieldTest()

{

super( "Testing JTextField and JPasswordField" ); // constructor của JFrame

Container container = getContentPane();

container.setLayout( new FlowLayout() );

// ô nhập với kích thước mặc định

textField1 = new JTextField( 10 );

container.add( textField1 );

// ô nhập với văn bản có sẵn

textField2 = new JTextField( "Enter text here" );

container.add( textField2 );

// ô nhập không cho phép nhập, chỉ hiên thị thông tin

textField3 = new JTextField( "Uneditable text field", 20 );

textField3.setEditable( false );

container.add( textField3 );

// ô nhập password

passwordField = new JPasswordField( "Hidden text" );

container.add( passwordField );

// Đăng ký bộ lắng nghe sự kiện

TextFieldHandler handler = new TextFieldHandler();

textField1.addActionListener( handler );

textField2.addActionListener( handler );

textField3.addActionListener( handler );

passwordField.addActionListener( handler );

setSize( 325, 100 );

setVisible( true );

}

// hàm main

public static void main( String args[] )

Page 123: Bai giang JAVA

123

{

TextFieldTest application = new TextFieldTest();

application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

}

// Lớp nội cho bộ lắng nghe sự kiện

private class TextFieldHandler implements ActionListener {

// phương thức xử lý sự kiện

public void actionPerformed( ActionEvent event )

{

String string = "";

// khi người dùng ấn enter

if ( event.getSource() == textField1 )

string = "textField1: " + event.getActionCommand();

// user pressed Enter in JTextField textField2

else if ( event.getSource() == textField2 )

string = "textField2: " + event.getActionCommand();

// user pressed Enter in JTextField textField3

else if ( event.getSource() == textField3 )

string = "textField3: " + event.getActionCommand();

// user pressed Enter in JTextField passwordField

else if ( event.getSource() == passwordField ) {

JPasswordField pwd = ( JPasswordField ) event.getSource();

string = "passwordField: " + new String( passwordField.getPassword() );

}

JOptionPane.showMessageDialog( null, string ); // Hiên thị cửa sổ thông báo

}

}

}

III.8 Thanh trượt (Scrollbar)

Ta có thể đặt thanh trượt các giá trị giới hạn tối thiểu (min) và tối đa (max) cùng với vị trí

hiện tại trên thanh trượt.

Khi người dùng kích chuột vào mũi tên ở hai đầu thì tình huống line nảy sinh, thanh trượt

sẽ tự động cộng thêm hay trừ đi một đơn vị.

Tình huống page nảy sinh khi người dùng kích chuột vào khoảng giữa thanh trượt, vị trí

hiện hành sẽ thay đổi.

Tình huống absolute nảy sinh khi người dùng nắm vào vị trí hiện hành của thanh trượt và

kéo nó đi.

Đối tượng Scrollbar chỉ chịu trách nhiệm di chuyển và cung cấp cho ta giá trị thay đổi.

Tạo thanh trượt:

Phương thức khởi tạo: public Scrollbar();

Page 124: Bai giang JAVA

124

Tạo thanh trượt đứng hay ngang ta dùng: public Scrollbar(int orienttation); orienttation

nhận giá trị Scrollbat.VERTICAL - cho đứng, Scrollbar.HORIZONTAL cho nằm ngang.

Tạo thanh trượt có đầy đủ thông số ban đầu:

public Scrollbar(int orienttation,

int pos, //vị trí khởi đầu

int pageUnit, //bước nhảy

int minValue, //giá trị min

int maxValue); //giá trị max

Một số phương thức hay dùng:

Thay đổi giá trị tăng giảm (mặc định là 1): public void setUnitIncrement(int increment);

Muốn biết hiện thời tăng giảm bao nhiêu: public int getUnitIncrement()

Chỉ định con số khi tình huống page xảy ra: pubic void setBlockIncrement(int b);

Muốn biết hiện thời đơn vị thay đổi là bao nhiêu: public int getBlockIncrement();

Lấy giá trị lớn nhất và nhỏ nhất: public int getMaximum(); public int getMinimum();

Đặt lại vị trí hiện hành cho thanh trượt: public void setValue(int newPos);

Cho ta vị trí hiện hành: public int getValue();

Muốn biết thanh trượt đứng hay ngang: public int getOrientation() trả về giá trị là một

trong hai hằng số Scrollbar.VERTICAL và Scrollbar.HORIZONTAL.

Thiết lập lại các thông số cho thanh trượt: public void setValues(int position, int

pageUnit, int minimum, int maximum);

ví dụ: myScrollbar.setValues(75, 10, 0, 500);

Sử dụng thanh trượt:

Ta nhờ đối tượng xử lý tình huống xử lý: public void

adjustmentValueChanged(AdjustmentEvent evt);

Có 3 trạng thái: line, page và absolute. Ta sử dụng hàm getAdjustmentType() để xác định

xem tình huống nào đang xảy ra.

AdjustmentEvent.UNIT_INCREMENT: tình huống line xảy ra, vị trí thanh trượt tăng 1

đơn vị.

AdjustmentEvent.UNIT_DECREMENT: tình huống line xảy ra, vị trí thanh trượt giảm 1

đơn vị.

AdjustmentEvent.BLOCK_INCREMENT: tình huống page xảy ra, vị trí hiện hành tăng 1

đv.

AdjustmentEvent.Track: tình huống absolute xảy ra, ta lấy vị trí thanh trượt bằng hàm

getValue().

IV. Thành phần Menu

Lớp JMenuBar cài đặt thanh thực đơn và trong đó có thể chứa các thực đơn pull-down.

Các JMenuBar được tạo ra để gắn vào một của sổ JFrame bằng một lệnh gọi:

JMenuBar menuBar = new JMenuBar();

JFrame frm = new JFrame(“Day la mot Frame”);

frm.setJMenuBar(menuBar); // MenuBar này chưa có phần tử nào

Sau khi có MenuBar, ta cần thêm vào đó các JMenu là các mục trên thanh Menu, khi

người dùng chọn vào đó sẽ sổ xuống danh sách các mục chọn khác.

JMenu file = new JMenu(“File”);

Ta đặt cho nó một phím tắt, ví dụ là „F‟ để khi ấn Alt + F thì JMenu này được kích hoạt:

file.setMnemonic('F');

Page 125: Bai giang JAVA

125

Sau đó thì thêm nó vào JMenuBar: menuBar.add(file);

Bây gời là lúc ta cài đặt các mục chọn trong một JMenu. Java dùng lớp JMenuItem định

nghĩa từng mục của thực đơn.

JMenuItem open = new JMenuItem(“Open”,‟O‟);

Ở đây ta đã gọi một constructor với một tham số là nhãn của mục chọn, một tham số là ký

tự phím tắt. Sau đó ta add vào JMenu:

file.add(open);

Nếu ta cần biểu diễn các dòng kẻ ngang để phân tách các mục chọn thì ta có thể gọi

phương thức addSeparator() của một đối tượng JMenu:

file.addSeparator();

Lớp JPopUpMenu biểu diễn cho thực đơn pop-up. Những thực đơn này có thể xuất hiện

bất cứ vị trí nào trong cửa sổ hiện tại.

Lớp JCheckBoxMenuItem chứa các mục được chọn để kiểm tra trong các mục thực đơn.

Tạo thanh trình đơn: JMenuBar myMenubar = new JMenuBar();

Đặt trạng thái cho mỗi mục chọn sử dụng enable() hoặc disable():

Vi dụ: openItem.enable(); //được chọn

openItem.disable(); //mờ mục chọn

Ta có thể dùng đường phân cách để tách các mục chọn:

FileMenu.addSeparator();

Tạo mục chọn có chứa menu con khác, ta tạo một menu bình thường rồi đưa vào

menu đã có.

Ví dụ:

//tạo mục chọn có menu con

JMenu printItem = new JMenu("Print");

//tạo các mục chọn cho menu con

printItem.add("Print preview");

printItem.add("to preview");

//đưa mục chọn có menu con vào menu chính

FileMenu.add(printItem);

Tạo một mục chọn có khả năng đánh dấu (check Item), một dấu kiểm tra (check mark) sẽ

hiện bên trái mục chọn:

Mục đánh dấu: CheckboxMenuItem Autosave = new CheckboxMenuItem("Auto save");

FileMenu.add(Autosave);

Xác định xem mục chọn Autosave đang ở trạng thái nào, ta dùng: Autosave.getState();

Khi sử dụng, để mục chọn tương tác và nhận được sự kiện ta cần cài đặt giao diện

ActionListener và gắn vào từng mục chọn.

Sau đây là một ví dụ xây dựng một JFrame với thanh menu và các mục chọn trong đó có

cài đặt xử lý các sự kiện.

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

class MenuBarSample extends JFrame {

//Khai bao mot hop thoai

JOptionPane op = new JOptionPane();

// Khai bao mot thuc don pop-up

JPopupMenu jp;

public MenuBarSample()

Page 126: Bai giang JAVA

126

{

// Lay ve doi tuong chua cua Frame hien tai

Container pane = this.getContentPane();

// Dat kieu trinh bay

pane.setLayout(new FlowLayout(FlowLayout.LEADING));

// Khai bao mot thanh menu

JMenuBar menuBar= new JMenuBar();

// Khai bao muc File trong thanh menu

JMenu menuFile= new JMenu("File");menuBar.add(menuFile);

// Dat ky tu kich hoat tat cung Alt

menuFile.setMnemonic('F');

// Khai bao mot muc chon voi phim tat O

JMenuItem fileOpen = new JMenuItem("Open",'O');

// Them muc chon vao muc File

menuFile.add(fileOpen);

// Them mot muc chon khac voi phim tat N

menuFile.add(new JMenuItem("New",'N'));

// Them dong ngan cach

menuFile.addSeparator();

// Them mot muc chon co ten Save

menuFile.add("Save");

// Xu ly su kien chon muc Open

fileOpen.addActionListener( new ActionListener()

{

public void actionPerformed(ActionEvent event)

{

// Hien thi thong bao, getContentPane() de lay Container cua Frame

op.showMessageDialog(getContentPane(),"Ban vua chon Open");

}

} );

// Xu ly su kien chon New

menuFile.getItem(1).addActionListener(new ActionListener()

{

public void actionPerformed(ActionEvent event)

{

op.showMessageDialog(getContentPane(),"Ban vua chon New");

}

} );

// Xu ly su kien chon Save

menuFile.getItem(3).addActionListener(new ActionListener()

{

public void actionPerformed(ActionEvent event)

{

op.showMessageDialog(getContentPane(),"Ban vua chon Save");

}

} );

// Khai bao mot muc chon kieu checkbox

Page 127: Bai giang JAVA

127

JCheckBoxMenuItem chk = new JCheckBoxMenuItem("is editting");

// Them phan xu ly su kien chon hay khong chon cho no

chk.addActionListener( new ActionListener()

{

public void actionPerformed(ActionEvent e)

{

// Lay ve doi tuong nguon su kien va ep kieu

JCheckBoxMenuItem ck = (JCheckBoxMenuItem)e.getSource();

if (ck.isSelected())

//Neu duoc chon

op.showMessageDialog(getContentPane(),"Ban vua chon is editting");

else

// Neu khong duoc chon

op.showMessageDialog(getContentPane(),"Ban vua bo chon is editting");

}

} );

// Them muc chon checkbox vao menu File

menuFile.add(chk);

// Dat thanh Menu cho Frame la doi tuong menuBar

this.setJMenuBar(menuBar);

// Cap phat bo nho cho popup menu

jp = new JPopupMenu("Popup");

jp.add("Create");

jp.addSeparator();

jp.add("New Document");

this.addMouseListener( new MouseAdapter()

{

public void mouseClicked(MouseEvent e)

{

if( (e.getModifiers() & InputEvent.BUTTON3_MASK)== InputEvent.BUTTON3_MASK)

jp.show(getContentPane(),e.getX(),e.getY());

}

}

);

}

public static void main(String[] argvs)

{

MenuBarSample m = new MenuBarSample();

m.setSize(300,400);

m.setVisible(true);

}

}

V. Bộ quản lý cách trình bày (Layout Manager)

Dùng để sắp xếp chỗ và định vị cho các đối tượng GUI.

Page 128: Bai giang JAVA

128

Có 5 cách trình bày:

FlowLayout: sắp xếp các đối tượng từ trái qua phải và từ trên xuống dưới. Các đối

tượng giữ nguyên kích thước.

GridLayout: tạo một khung lưới vô hình với các ô bằng nhau, các đối tượng sẽ đặt

vừa kích thước với các ô đó.

BorderLayout: Các đối tượng được đặt theo đường viền của khung chứa theo các

cạnh West, East, South, Nort và Center.

CardLayout: Các đối tượng được đặt vừa vặn với khung chứa và nằm chồng lên

nhau như các lá bài.

GridBadLayout: các đối tượng trong khung chứa cũng được đưa vào các ô của

một khung lưới vô hình, kích thước các đối tượng không nhất thiết phải vừa một

ô.

Muốn áp dụng ta tạo ra đối tượng trên rồi chuyển nó cho khung chứa.

Ví du: FlowLayout objectsLayout = new FlowLayout();

myWindow.setLayout(objectsLayout);

hay có thể viết gọn hơn:

myWindow.setLayout(new FlowLayout());

V.1 Cách trình bày FlowLayout:

Tạo đối tượng FlowLayout, ta sử dụng phương thức: public FlowLayout();

hoặc chỉ định luôn cách căn lề bằng phương thức khởi tạo: public FlowLayout(int align);

align là FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER hoặc chỉ ra khoảng các

giữa các đối tượng trên cùng một hàng: public FlowLayout(int align, int hgap, int vgap);

V.2 Cách trình bày GridLayout:

Phương thức khởi tạo: public GridLayout(int Rows, int Cols);

Ví dụ: GridLayout layout = new GridLayout(3, 2);

Xác định khoảng cách giữa các đối tượng quản lý:

public GridLayout(int Rows, int Cols, int hgap, int vgap);

V.3 Cách trình bày BorderLayout

Đối tượng được đặt theo đường viền khung chứa, theo các cạnh của khung.

Tạo bộ quản lý kiểu BorderLayout: public BorderLayout();

Ví dụ: myWindow.setLayout(new BorderLayout());

Khi đưa đối tượng vào khung chứa, ta phải định hình trước đối tượng đó đặt ở đâu:

myWindow.add("North", new Button("on Top"));

có 5 kiểu: "North", "South", "West", "East", "Center".

VI. Các hộp thoại

VI.1 Hộp thoại thông báo

Khi cần đưa ra thông báo hay hỏi người dùng một vấn đề gì đó và nhận về câu trả lời, ta

dùng hộp thoại thông báo. Java hỗ trợ lớp JOptionPane để ta thực hiện công việc này.

Lớp JOptionPane có 4 phương thức tĩnh sau:

Tên phương thức Giá trị trả về Ý nghĩa

Page 129: Bai giang JAVA

129

showMessageDialog Không có Hiển thị một thông báo và đợi ấn OK

showConfirmDialog Số int Hiển thị thông báo và đợi xác nhận Ok hay Cancel

showOptionDialog Số int Hiển thị thông báo và nhận về trả lời từ một danh sách chọn

showInputDialog Chuỗi Hiển thị thông báo và nhận về một dòng do user nhập vào

icon hiển thị phụ thuộc vào loại thông báo:

ERROR_MESSAGE : Thông báo lỗi

INFORMATION_MESSAGE : Thông tin

WARNING_MESSAGE :Cảnh báo

QUESTION_MESSAGE: Hỏi

PLAIN_MESSAGE: Giải thích

Các hằng số này được truy cập qua JOptionPane.

Ví dụ:

int selection = JOptionPane.showConfirmDialog(parent, "Message", "Title",

JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);

if (selection == JOptionPane.OK_OPTION) . . .

VI.2 Hộp thoại chọn File

Khi viết ứng dụng ta gặp các tình huống mở file để đọc hoặc ghi. Swing hỗ trợ một lớp

JFileChooser để ta thực hiện công việc này. Hai phương thức quan trọng là:

- showOpenDialog: Để hiện thị hộp thoại chọn mở file

- showSaveDialog: Để hiện thị hộp thoại chọn ghi file

Sau đây là các bước để làm việc với hộp thoại chọn file:

1- Tạo một đối tượng JFileChooser: JFileChooser chooser = new JFileChooser();

2- Đặt thư mục cho hộp thoại: chooser.setCurrentDirectory(new File("."));

3- Nếu định chọn trước một file, có thể đặt: chooser.setSelectedFile(new File(filename));

4- Để cho phép chọn nhiều file: chooser.setMultiSelectionEnabled(true);

5- Nếu muốn giới hạn kiểu file, dùng bộ lọc file. Để dùng được bộ lọc file ta phải thiết kế

một lớp kế thừa từ lớp javax.swing.filechooser.FileFilter. Ví dụ bộ lọc file Gif:

public class GifFilter extends FileFilter

{

public boolean accept(File f)

{

return f.getName().toLowerCase().endsWith(".gif") || f.isDirectory();

}

public String getDescription()

{

Page 130: Bai giang JAVA

130

return "GIF Image";

}

}

Sau đó gán cho hộp thoại: chooser.setFileFilter(new GifFilter());

6- Mặc định thì chỉ cho phép chọn file, nếu muốn cho phép chọn thư mục dùng phương

thức: setFileSelectionMode() với các tham số: JFileChooser.DIRECTORIES_ONLY hoặc

JFileChooser.FILES_AND_DIRECTORIES.

7- Hiển thị hộp thoại bằng lệnh gọi:

int result = chooser.showOpenDialog(parent);

hoặc

int result = chooser.showSaveDialog(parent);

Các giá trị trả về là JFileChooser.APPROVE_OPTION,

JFileChooser.CANCEL_OPTION, or JFileChooser.ERROR_OPTION

8- Lấy vè file hoặc các file được chọn dùng: getSelectedFile() hoặc getSelectedFiles().

Neus chỉ muốn lấy tên file thì ta dùng phương thức getPath().

String filename = chooser.getSelectedFile().getPath();

VI.3 Hộp thoại chọn màu

Swing hỗ trợ lớp JColorChooser để người dùng chọn màu. Cú pháp sử dụng như sau:

Color selectedColor = JColorChooser.showDialog(parent,title, initialColor);

Khi làm việc với hộp thoại chọn màu ta cần cung câp:

- parent: một companent cha;

- title: Tiêu đề hộp thoại;

- chế độ hộp thoại modal hay modeless;

- một đối tượng chọn màu

- bộ lắng nghe cho nút bấm Ok và Cancel.

chooser = new JColorChooser();

dialog = JColorChooser.createDialog(parent,"Background Color", false /* not modal */, chooser,

new ActionListener() // Lắng nghe cho OK

{

public void actionPerformed(ActionEvent event)

{

setBackground(chooser.getColor());

}

},

null /* Không có lắng nghe cho Cancel */);

Bài tập

1. Hãy thiết kế một giao diện có nội dung như sau:

Page 131: Bai giang JAVA

131

2. Hãy lập trình để xử lý sự kiện click chuột phải lên nền của sổ sẽ hiện một menu Popup.

3. Viết chương trình giải phương trình bậc 2 với giao diện GUI. Yêu cầu chương trình có các ô

nhập các hệ số a, b, c và cho phép xem kết quả. Trường hợp không có nghiệm sẽ hiển thị một hộp

thoại thông báo “chương trình vô nghiệm”.

Page 132: Bai giang JAVA

132

Đề tài 11. Threading

Java là ngôn ngữ thông dụng duy nhất hỗ trợ cho lập trình viên các giải pháp lập trình

song song. Lập trình viên xác định số lượng các thread được chạy trong chương trình và chúng

được thực hiện song song với nhau ở những giai đoạn nào. Khả năng này của Java gọi là tính đa

luồng.

I. Khái niệm thread

I.1 Khái niệm:

Thread – luồng chỉ một đơn vị chương trình có thể tách khỏi các phần khác của chương

trình để thực hiện song song với các phần khác ở từng khoảng thời gian hoặc trong toàn bộ quá

trình nó thực hiện.

Trong mỗi chương trình Java, có một luồng chính được bắt đầu bằng việc gọi hàm main(),

các luồng khác có thể phát sinh từ luồng chính này. Các câu lệnh trong hàm main() nếu không

được đưa vào một luồng riêng thì sẽ được thực hiện tuần tự.

I.2. Lớp Thread

Lớp Thread trong gói java.lang có một số constructor:

Public Thread (<tên thread>)

Public thread(): Khi này thread sẽ có tên là Thread_1, Thread_2,….

Các công việc của một thread được đặt trong phương thức run(). Phương thức này có thể

được khai báo chồng trong lớp khai báo kế thừa Thread hoặc khai báo cài đặt giao diện Runable.

Người lập trình bắt đầu một thread bằng các gọi phương thức start(), phương thức start()

sau đó sẽ gọi run(). Sau khi start() thực hiện xong, nó trả về điều khiển cho chương trình gọi nó.

Do đó, chương trình gọi nó và thread được thực hiện một cách đồng thời.

Phương thức start() sẽ ném ra một ng oại lệ IllegalThreadStateException nếu

thread cần bắt đầu đã bắt đầu rồi.

Phương thức tĩnh sleep của Thread được gọi với một tham số xác định rằng một

thread đang chạy sẽ dừng lại trong bao lâu theo đơn vị phần nghìn giây. Trong khi

một thread “sleep”, nó sẽ không tiêu tốn tài nguyên CPU và thread khác có thể

chạy.

Phương thức interrupt() được gọi để để ngắt một thread. Phương thức này trả về

true nếu ngắt thành công. Phương thức isInterrupted() dùng để kiểm tra xem

thread có bị ngắt hay không.

Phương thức isAlive() trả về true nếu start() đã được gọi và phương thức run() vẫn

đang thực hiện.

Phương thức setName() đặt tên cho một thread, getName() lấy tên một thread.

Phương thức toString() trả về tên phương thức, độ ưu tiên và nhóm của thread.

Phương thức static currentThread() trả về tham chiếu tới thread hiện hành đang

thực hiện.

Phương thức joint đợi (wait) một phản hổi của một thông điệp được gửi đi trước

khi thực hiện thread.

I.3 Các bước để tạo một thread

Sau đây là các bước đơn giản để thực hiện một nhiệm vụ trong một thread riêng:

Page 133: Bai giang JAVA

133

1. Khai báo một lớp có cài đặt giao diện Runable với phương thức run() được định nghĩa:

class MyRunnable implements Runnable

{

public void run()

{

// code thực hiện

}

}

2. Tạo một đối tượng của lớp

Runnable r = new MyRunnable();

3. Tạo một đối tượng Thread từ đối tượng Runable trên:

Thread t = new Thread(r);

4. Gọi phương thức start()

t.start();

Một thread cũng có thể được tạo ra bằng cách xây dựng một lớp con của lớp Thread:

class MyThread extends Thread

{

public void run()

{

// code của thread

}

}

Sau đó ta cũng làm theo các bước 2,3 và 4 để thực hiện thread.

II. Các trạng thái của thread.

Trạng thái born: Khi thread chưa gọi start().

Trạng thái ready: Khi phương thức start() được gọi.

Trạng thái running: Một Thread ở trạng thái ready có quyền ưu tiên cao nhất sẽ

được chuyển sang trạng thái này.

Trạng thái dead: Khi một Thread ngưng hoặc hoàn thành nhiệm vụ của nó.

Ngoài ra, một thread running cũng có thể bị chặn (blocked) trong các thao tác vào ra. Lúc

này nó cũng không sử dụng tài nguyên CPU.

Trạng thái sleep: Khi Thread gọi phương thức sleep. Nếu đang ở trạng thái sleep

mà gọi phương thức interrupt(), tread sẽ thoát khỏi trạng thái sleep và chuyển sang

trạng thái ready.

Sau đây là sơ đồ trạng thái của một thread.

Page 134: Bai giang JAVA

134

Khi một thread đang chạy gọi phương thức wait(), thread sẽ rơi vào một trạng thái wait để

đợi một đối tượng mà nó đã gọi.

III. Các thuộc tính của thread

III.1 Độ ưu tiên của thread

Mỗi Thread có một độ ưu tiên. Mặc định thì thread thừa kế độ ưu tiên từ thread cha của

nó- là thread đã gọi nó. Ta có thể tăng hoặc giảm độ ưu tiên của bất kỳ thread nào với phương

thức setPriority() bằng một giá trị nằm giữa MIN_PRIORITY(1) và MAX_PRIORITY (10).

Trình từ thực hiện của các thread theo độ ưu tiên của nó được minh họa như sau:

Page 135: Bai giang JAVA

135

Các thread có độ ưu tiên càng cao thì khả năng thực hiện càng cao.

III.2 Nhóm thread

Các thread có thể được đưa vào cùng một nhóm để có thể đồng thời làm việc với cả nhóm

thread này.

Khai báo một nhóm Thread:

String groupName = . . .;

ThreadGroup g = new ThreadGroup(groupName)

Sau đó, với mỗi thread được tạo ra ta dùng constructor có khai báo nhóm thread:

Thread t = new Thread(g, threadName);

Để kiểm tra xem có thread nào trong nhóm g còn hoạt động không, ta dùng phương thức:

g. activeCount();

Để ngắt tất cả các thread trong nhóm g ta gọi:

g.interrupt();

III.3 Quản lý các ngoại lệ của thread

Phương thức run() không thể ném ra một ngoại lệ được kiểm soát mà bị kết thúc bởi một

ngoại lệ không kiểm soát được mỗi khi có lỗi. Không có mệnh đề catch nào được thực hiện mà

thay vào đó, trước khi thread bị dead, ngoại lệ này sẽ được gửi cho một bộ xử lý ngoại lệ không

được kiểm soát.

Page 136: Bai giang JAVA

136

Bộ xử lý này phải thuộc một lớp có cài đặt giao diện Thread.UncaughtExceptionHandler

chỉ với 1 phương thức:

void uncaughtException(Thread t, Throwable e);

Từ phiên bản Java 1.5, ta có thể cài bộ xử lý ngoại lệ cho bất cứ thread nào bằng phương

thức: setUncaughtExceptionHandler(). Mgoaif ra ta có thể cài bộ xử lý ngoại lệ mặc định cho tất

cả các thread bằng cách gọi phương thức setDefaultUncaughtExceptionHandler của lớp Thread.

Nếu không cài bộ xử lý ngoại lệ cho một thread thì mặc định là null. Tuy nhiên, các

thread riêng lại phụ thuộc vào bộ xử lý của nhóm thread chứa nó. Khi này, phương thức

uncaughtException sẽ làm các việc sau:

1- Nếu nhóm thread có cài đặt uncaughtException thì phương thức đó được gọi.

2- Ngược lại, nếu phương thức Thread.getDefaultExceptionHandler trả về một bộ xử lý

không phải là null thì bộ xử lý này được gọi.

3- Nếu là null, nếu Throwable là một đối tượng của TheadDead, không có gì xảy ra.

4- Nếu không, tên của thread và stack trace được gửi tới System.err và đưa ra màn hình.

IV. Điều khiển các thread

Sau khi đã khởi động được một thread rồi, vấn đề tiếp theo sẽ là điều khiển thread.

IV.1 Interrupt một thread

Khi sử dụng phương thức Thread.sleep(int) thì chương trình thường phải bắt các ngoại lệ

để xử lý. Lý do là thread bị dừng lại trong một khoảng thời gian lâu và trong khoảng thời gian đó

nó không thể tự đánh thức nó được. Tuy nhiên, nếu một thread cần phải được đánh thức sớm hơn,

ta có thể ngắt nó dùng phương thức interrupt().

public class SleepyHead extends Thread

{

// Phương thức được chạy khi thread khởi động lần đầu

public void run()

{

System.out.println ("Thread đang ngủ. Hãy đánh thức nó");

try

{

// Ngủ trong 8 tiếng

Thread.sleep( 1000 * 60 * 60 * 8 );

System.out.println ("Đó là một giấc ngủ trưa");

}

catch (InterruptedException ie)

{

System.err.println ("Chỉ mới được hơn 5 phút thôi....");

}

}

// Phương thức main tạo và bắt đầu thread

public static void main(String args[]) throws

java.io.IOException

{

// Tạo một thread

Thread sleepy = new SleepyHead();

Page 137: Bai giang JAVA

137

// bắt đầu thread

sleepy.start();

// Nhắc người dùng để dừng thread

System.out.println ("Nhấn Enter để ngưng thread");

System.in.read();

// Ngắt thread

sleepy.interrupt();

}}

Cách thực hiện ở đây là gửi một thông điệp từ một thread khác để đánh thức một thread

đang ngủ. Ở đây, thread chính- hàm main- sẽ đợi cho người dùng ấn enter, sau đó gửi một thông

điệp ngắt tới thread đang ngủ.

IV.2 Dừng một thread

Đôi khi ta muốn một thread dừng lại trước khi nhiệm vụ của nó hoàn thành. Một thread

(gọi là thread điều khiển) có thể gửi một thông điệp dừng tới một thread khác bằng việc gọi

phương thức Thread.stop(). Điều này yêu cầu thread điều khiển phải giữ một tham chiếu tới

thread muốn dừng.

public class StopMe extends Thread

{

// Phương thức được thực hiện khi thread khởi động lần đầu

public void run()

{

int count = 1;

System.out.println ("Thread đếm!");

for (;;)

{

// In ra biến count và tăng giá trị cho nó

System.out.print (count++ + " ");

// Ngủ nửa giây

try { Thread.sleep(500); } catch

(InterruptedException ie) {}

}}

// phương thức main

public static void main(String args[]) throws java.io.IOException

{

// Tạo và bắt đầu thread

Thread counter = new StopMe();

counter.start();

// Nhắc người dùng

System.out.println ("Nhấn Enter để dừng đếm");

System.in.read();

// Dừng thread

counter.stop();

}}

Page 138: Bai giang JAVA

138

IV.3 Tạm dừng và phục hồi một thread

Các phương thức suspend() dùng để tạm dừng một thread trong khi resume() dùng để tiếp

tục một thread đã bị suspend. Tuy nhiên sử dụng các thread này rất hay gây ra tình trạng

deadlock do thread bị suspend đang chiếm giữ một tài nguyên và không giải phóng trong khi

nhiều thread khác có thể đang đợi sử dụng tài nguyên đó.

IV.4 Giải phóng thời gian cho CPU

Khi một thread rơi vào trạng thái đợi một sự kiện xảy ra hoặc đi vào một vùng mã lệnh

mà nếu giải phóng thời gian cho CPU sẽ nâng cao hiệu quả của hệ thống. Trong trường hợp này,

thread nên giải phóng thời gian hệ thống hơn là dùng sleep() để nghỉ trong thời gian dài. Để làm

điều này ta dùng phương thức static yield() của Thread để giải phóng thời gian CPU cho thread

hiện thời. Ta không thể giải phóng thời gian CPU của bất kỳ thread nào mà chỉ đối với thread

hiện thời.

IV.5 Đợi một thread kết thúc công việc

Đôi khi ta cần đợi cho một thread kết thúc một công việc nào đó như gọi một phương

thức hay đọc một thuộc tính thành phần,…Ta dùng phương thức isAlive() để xác định thread còn

chạy không. Tuy nhiên, nếu thường xuyên dùng phương thức này để kiểm tra sau đó dùng sleep()

hoặc yield() thì hiệu quả sử dụng CPU sẽ rất thấp. Một cách hiệu quả là gọi phương thức joint()

để đợi một thread kết thúc công việc.

public class WaitForDeath extends Thread

{

// Phương thức run()

public void run()

{

System.out.println ("thread chuẩn bị nghỉ....");

// Nghỉ trong 5 giây

try

{

Thread.sleep(5000);

}

catch (InterruptedException ie) {}

}

// phương thức main

public static void main(String args[]) throws

java.lang.InterruptedException

{

// Tạo thread

Thread dying = new WaitForDeath();

dying.start();

// Nhắc user

System.out.println ("Đợi cho thread kết thúc");

dying.join();

System.out.println ("Thread đã dừng");}}

Page 139: Bai giang JAVA

139

V. Đồng bộ thread

Trong hầu hết các chương trình đa luồng, các thread có thể cần phải truy cập đến cùng

một đối tượng. Điều gì xảy ra nếu cả hai thread cùng truy cập đến đối tượng và làm thay đổi

thuộc tính đối tượng. Kết quả có thể là các thread bị ảnh hưởng lẫn nhau và không đạt được kết

quả mong muốn. Tình trạng này gọi là “đua tranh”.

V.1 Tình trạng “đua tranh”

Trong phần tiếp theo, chúng ta mô phỏng một ngân hàng có rất nhiều tài khoản khách

hàng. Chúng ta thử thiết kế một chương trình để chuyển tiền ngẫu nhiên giữa các tài khoản. Mỗi

tài khoản có một thread riêng. Mỗi giao dịch thực hiện việc chuyển tiền từ account sang một

account ngẫu nhiên khác.

Ta có một class Bank với phương thức transfer để chuyển tiền. Nếu account chuyển

không đủ tiền, giao dịch kết thúc ngay.

public void transfer(int from, int to, double amount)

{

System.out.print(Thread.currentThread());

accounts[from] -= amount;

System.out.printf(" %10.2f from %d to %d", amount, from, to);

accounts[to] += amount;

System.out.printf(" Số dư: %10.2f%n", getTotalBalance());

}

Sau đây là đoạn code cho class transferRunnable:

class TransferRunnable implements Runnable

{

. . .

public void run()

{

try

{

int toAccount = (int) (bank.size() * Math.random());

double amount = maxAmount * Math.random();

bank.transfer(fromAccount, toAccount, amount);

Thread.sleep((int) (DELAY * Math.random()));

}

catch(InterruptedException e) {}

}

}

Khi chương trình chạy, ta không biết được trong mỗi tài khoản còn bao nhiêu tiền nhưng

tổng số tiền của tất cả các tài khoản là không đổi. Chương trình trên chạy và không bao giờ dừng

lại, ta phải ấn Ctrl + C để dừng nó.

Tuy nhiên, trong một số tình huống chương trình trên có thể gây lỗi và in ra tổng số tiền

khác nhau, đó là khi có nhiều hơn một tài khoản cùng chuyển tiền đến một tài khoản khác, tức là

cùng thực hiện câu lệnh:

account[to] += amount;

Page 140: Bai giang JAVA

140

Giả sử đây là một hành vi đơn vị (atomic- hành vi chỉ chiếm một chu kỳ thực hiện lệnh

của CPU), khi đó mỗi thread sẽ thực hiện phép tính này một cách tuần tự mà không gây ảnh

hưởng vì trong một thời điểm, CPU cũng chỉ phục vụ được cho một thread.

Tuy nhiên, phép tính này lại không phải là atomic, công việc có thể phải làm là:

1- Load giá trị account[to] vào thanh ghi

2- Cộng với account

3- Load kết quả ngược trả lại cho account[to]

Giả sử có 2 thread là thread_1 và thread_2 cùng thực hiện đến dòng lệnh này. Thread_1

thực hiện xong bước 1 và 2 thì bị ngắt, sau đó thread_2 sẽ thực hiện câu lệnh trên với đầy đủ 3

bước tức là account[to] đã bị thay đổi giá trị. Tiếp theo, thread_1 thức dậy và làm tiếp bước 3,

account[to] lúc này đã ghi đè giá trị do thread_2 cập nhật. Điều này dẫn tới việc tổng số tiền bị

thay đổi, phần tiền do thread_2 chuyển cho account[to] đã bị mất.

V.2 Khóa đối tượng

Trong ví dụ trên, nếu ta đảm bảo rằng phương thức transfer() được thực hiện thành công

trước khi thread bị ngắt thì sẽ không có vấn đề gì xảy ra. Có nghĩa là, trong một thời điểm sẽ chỉ

có một thread được truy cập vào một đoạn mã lệnh nào đó.

Từ phiên bản Java 5.0 có hỗ trợ hai cơ chế để bảo vệ một khối lệnh khỏi sự truy cập đồng

thời. Các phiên bản trước của Java sử dụng từ khóa synchronized, Java 5.0 giới thiệu thêm lớp

ReentrantLock cho mục đích này.

Cấu trúc đoạn lệnh căn bản để sử dụng cơ chế này là:

myLock.lock(); // đối tượng ReentrantLock

try

{

//Đoạn lệnh cần bảo vệ

}

finally

{

myLock.unlock(); // đảm bảo khóa được mở kể cả khi exception xảy ra

}

Đoạn lệnh này đảm bảo rằng chỉ có một thread tại một thời điểm có thể đi vào vùng được

bảo vệ. Khi một thread đầu tiên đã gọi lock thì không một thread nào sau đó có thể vượt qua lệnh

lock().

Bây giờ chúng ta sẽ khóa phương thức transfer() trong lớp Bank:

public class Bank

{

public void transfer(int from, int to, int amount)

{

bankLock.lock();

try

{

if (accounts[from] < amount) return;

System.out.print(Thread.currentThread());

accounts[from] -= amount;

System.out.printf(" %10.2f from %d to %d", amount, from, to);

accounts[to] += amount;

System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());

Page 141: Bai giang JAVA

141

}

finally

{

bankLock.unlock();

}

}

. . .

private Lock bankLock = new ReentrantLock(); // ReentrantLock là một lớp cài đặt giao

diện lock.

}

V.3 Đối tượng điều kiện

Trong trường hợp thread đi vào vùng bảo vệ, nó cần hoàn thành công việc để có thể mở

khóa cho các thread khác đi vào. Tuy nhiên, nếu trong đó công việc chính cần thực hiện bị giới

hạn bởi một điều kiện nào đó, chẳng hạn ở đây, việc gọi transfer() để chuyển tiền chỉ được thực

hiện khi số tiền của account gửi lớn hơn số tiền được gửi:

if (bank.getBalance(from) >= amount)

bank.transfer(from, to, amount);

Khi có điều kiện này, một thread có thể không thỏa mãn và nó không thực hiện việc

chuyển tiền, tức là công việc của nó là không hữu ích. Đến đây, ta có thể nghĩ ra một giải pháp là

để thread đợi cho đến khi nó có đủ tiền để chuyển:

public void transfer(int from, int to, int amount)

{

bankLock.lock();

try

{

while (accounts[from] < amount) // Đợi cho đến khi tài khoản của nó có đủ tiền

{

// đợi

. . .

}

// Chuyển tiền

. . .

}

finally

{

bankLock.unlock();

}

}

Việc đợi ở đây sẽ kết thúc khi một thread khác chuyển tiền vào cho nó. Tuy nhiên ta thấy

rằng vùng chứa lệnh chuyển tiền lại đang bị khóa bởi chính thread này nên các thread khác không

thể chuyển tiền được. Kết quả là thread này không bao giờ thoát khỏi tình trạng đợi, chương trình

rơi vào deadlock.

Đây là tình huống mà ta phải sử dụng đối tượng điều kiện:

class Bank

{

public Bank()

Page 142: Bai giang JAVA

142

{

. . .

sufficientFunds = bankLock.newCondition();

}

. . .

private Condition sufficientFunds;

}

Nếu phương thức transfer() kiểm tra và thấy rằng nó chưa đủ tiền để chuyển thì nó sẽ gọi:

sufficientFunds.await();Lúc này nó sẽ nằm chờ thread khác chuyển tiền.

Có một sự khác nhau căn bản giữa một thread đang đợi để khóa (gọi phương thức lock()

để đi vào vùng bảo vệ) và thread gọi phương thức await(). Nó sẽ không thể mở khóa khi đang

nằm trong vùng khóa cho đến khi một thread khác gọi signalAll(). Một thread thực hiện xong

việc chuyển tiền, nó nên gọi: sufficientFunds.signalAll() để mở khóa cho các thread đang nằm

đợi thỏa mãn điều kiện đủ tiền. Một khi thread đã thoát khỏi tình trạng đợi do await() gây ra, nó

sẽ được chạy tiếp và cố gắng đi vào vùng khóa và bắt đầu từ vị trí mà nó chờ đợi trước đó - vị trí

gọi phương thức await() và kiểm tra lại điều kiện.

Một phương thức await() nên được gọi trong một vòng lặp đợi:

while (!(đủ tiền))

condition.await();

Nếu không có thread nào gửi signalAll() thì thread đang đợi không có cách nào chạy tiếp

được. Nếu tất cả các thread khác đều đang bị chặn, thread gọi await() không giả phóng tình trạng

này cho một thread nào đó thì bản thân nó cũng bị chặn, chương trình sẽ bị treo.

Vấn đề là khi nào thì gọi signalAll()? Nguyên tắc chung là khi một thread hoàn thành việc

thay đổi trạng thái đối tượng thì nó nên gọi signalAll(). Ở đây, sau khi cộng tiền vào cho tài

khoản nhận và thì signalAll() sẽ được gọi. Việc gọi này sẽ giúp các thread cũng đang trong tình

trạng chờ đợi này không bị chặn nữa và tiếp tục công việc với một giá trị tài khoản có thể đã bị

thay đổi.

public void transfer(int from, int to, int amount)

{

bankLock.lock();

try

{

while (accounts[from] < amount)

sufficientFunds.await();

// Chuyển tiền

. . .

sufficientFunds.signalAll();

}

finally

{

bankLock.unlock();

}

}

Chú ý là việc gọi signalAll() không phải là kích hoạt thread bị chặn ngay lập tức. Nó chỉ

giải phóng tình trạng bị chặn của các thread khác cho đến khi nó kết thúc đoạn chương trình được

bảo vệ. Một phương thức khác là sign() chỉ trao khóa cho một thread xác định thay vì tất cả. Một

thread chỉ có thể gọi các phương thức signalAll(), sign() và await() trong vùng được bảo vệ.

Page 143: Bai giang JAVA

143

Chúng ta có thể kết thúc phần này bằng một câu chuyện minh họa: Có 10 người cùng đến

ngân hàng để chuyển tiền cho nhau, mỗi người chuyển cho một người khác trong số 9 người còn

lại. Mỗi thời điểm ngân hàng chỉ chuyển tiền cho một người, người được gửi tiền sẽ được vào

trong ngân hàng và giữ khóa cổng, 9 người khác phải chờ ngoài cổng. Nếu chẳng may người

đang thực hiện chuyển số tiền lớn hơn anh ta có, anh ta sẽ đợi ở trong ngân hàng (gọi await()) và

ném khóa ra ngoài cổng cho tất cả 9 người kia. Một trong số 9 người ngoài cổng sẽ được đi vào

trong ngân hàng, thực hiện việc chuyển tiền. Sau khi chuyển xong, anh ta thông báo cho tất cả

các anh khác đang phải đợi trong ngân hàng là mình vừa chuyển tiền (gọi signalAll()) rồi đi ra

ngoài, sau đó những người đang đợi cũng quay ra cổng để đợi đến lượt vào.

Bài tập

1. Viết một chương trình tạo một thread thực hiện việc giải một phương trình bậc 2 với

các hệ số cho trước.

2. Viết chương trình song song với 10 thread để cộng 10000 số tự nhiên liên tiếp từ 1 đến

10000.

Page 144: Bai giang JAVA

144

Phụ lục A. Các từ khóa của Java

Từ khóa Ý nghĩa

abstract Một lớp hoặc phương thức trừu tượng

assert Được sử dụng để định vị lỗi nội bộ chương trình

boolean Kiểu boolean

break Thoát khỏi lệnh switch hoặc các vòng lặp

byte Số nguyên 1 byte

case Một lựa chon của switch

catch Một mệnh đề của khối Try để bắt một ngoại lệ

char Kiểu ký tự Unicode

class Định nghĩa một class

const Không được sử dụng

continue Tiếp tục tại vị trí cuối vòng lặp hiện thời

default Mệnh đề mặc định của switch

do Phần trên của vòng lặp do/while

double Kiểu số thực floating-number 8 byte

else Mệnh đề else của một lệnh if

extends Xác định lớp cha của một lớp

final Một hằng số, hoặc một lớp hay phương thức không thể bị khai báo chống.

finally Một phần của khối try mà luôn được thực hiện

float Số thực 4 byte

for Một kiểu vòng lặp

goto Không sử dụng

if Một lệnh điều khiển rẽ nhánh

implements Chỉ ra các interfaces mà lớp sẽ cài đặt.

import Nhập một package

instanceof Kiểm tra xem đối tượng có phải là biểu hiện của một lớp

int Số nguyên 4 byte

interface Một kiểu trừu tượng với các phương thức được cài đặt tại các class

Page 145: Bai giang JAVA

145

Từ khóa Ý nghĩa

long Sô nguyên 8 byte

Native a method implemented by the host system

new Cấp phát vùng nhớ cho một đối tượng hoặc mảng mới

null Một tham chiếu null

package Một gói các lớp

private a feature that is accessible only by methods of this class

protected a feature that is accessible only by methods of this class, its children, and other

classes in the same package

public a feature that is accessible by methods of all classes

return returns from a method

short the 16-bit integer type

static a feature that is unique to its class, not to objects of its class

strictfp Use strict rules for floating-point computations

super the superclass object or constructor

switch a selection statement

synchronized a method or code block that is atomic to a thread

this the implicit argument of a method, or a constructor of this class

throw throws an exception

tHRows the exceptions that a method can throw

transient marks data that should not be persistent

try a block of code that traps exceptions

void denotes a method that returns no value

volatile ensures that a field is coherently accessed by multiple threads

while a loop

Phụ lục B Một số hàm hay sử dụng

a) Hàm toán học, lớp java.lang.Math; {java.math.*;}

1. abs(number x): lấy |x|, x có thể là các kiểu long, int, float, double.

2. acos(double x) = arccos(x). x từ 0.0 ... PI

3. asin(double x) = arcsin(x). x từ -PI/2 ... PI/2

4. atan(double x) = arctag(x).

5. ceil(double x): làm cận trên hoặc cận dưới của số x.

6. cos(double x) = cos(x). x là radian.

Page 146: Bai giang JAVA

146

7. exp(double x) = ex.

8. log(double x) = Ln(x).

9. max(number x, number y) = max{x, y}, trong đó x, y có thể là kiểu int, float,

double, long.

10. min(number x, number y) = min{x, y}, trong đó x, y có thể là kiểu int, float,

double, long.

11. pow(double x, double y) = xy.

12. random(): cho một số ngẫu nhiên trong [0.0, 1.0].

13. round(number x): làm tròn số x, nếu x là kiểu double thì thành kiểu long, nếu x là

kiểu float thì thành kiểu int.

14. sin(double x) = sin(x).

15. sqrt(double x) =

16. tan(double x) = tg(x).

Khi sử dụng ta phải dùng Math.tên_hàm.

b) Lớp String, khai báo java.lang.String;

1. String() : Khởi động một đối tượng chuỗi.

2. String(String s) : Khởi động một chuỗi bằng chuỗi s.

3. length() : trả về giá trị int là độ dài một chuỗi.

4. charAt(int i): trả về một ký tự thứ sau i.

5. indexOf(int ch): trả về vị trí trước của ký tự ch đầu tiên tìm thấy.

6. concat(String str): nối thêm chuỗi str vào sau.

7. toLowerCase(): thay đổi chuỗi thành chữ thường.

8. toUpperCase(): chuyển đổi chuỗi thành chữ HOA.

Lớp Date khai báo java.util.Date;

1. Date(): cho thứ, tháng, ngày, giờ, năm.

2. getDate(): trả về giá trị của ngày trong tháng.

3. getDay(): trả về giá trị int là thứ trong tuần, 0 = CN, 1 = mon, ..., 6 = Sat.

4. getMonth(): trả về giá trị int là tháng trong năm (0..11).

5. getYear(): trả về giá trị int là năm. Lấy mốc là 1900, năm thực =

date.getYear()+1900.

6. getTime(): trả về là một số được tính theo giây đồng hồ.

7. getHours(): trả về giá trị int chỉ giờ trong ngày.

8. getMinutes(): trả về giá trị int chỉ phút trong giờ.

9. getSeconds(): trả về giá trị int chỉ giây đồng hồ trong phút.

10. setDate(int date) đặt lại ngày trong biến. date lấy giá trị từ 1..31

11. setMonth(int month): thay đổi giá trị tháng trong biến date. month có giá trị 0..11.

12. setYear(int year): thay đổi giá trị năm trong biến date. (year + 1900).

13. setHours(int hour): thay đổi giá trị giờ trong biến date.

14. setMinutes(int i): thay đổi giá trị phút trong biến date.

15. setSeconds(int i): thay đổi giá trị giây trong biến date.

Tài liệu tham khảo

[1] Deitel & Associates (2001), “Java, How to program”, fourth edition.

[2] Cay S. Horstmann, Gary Cornell (2004), “Core Java™ 2”, volume 1,2, Prentice Hall PTR

[3] David Reilly, Michael Reilly (2002), “Network Programming and Distributed Computing”,

Addison Wesley