oop in java - ver1.1
DESCRIPTION
Lập trình Hướng đối tượng Java (Object-Oriented Programming in Java) Biên soạn bởi: Vũ Duy LinhTRANSCRIPT
Giảng viên: Vũ Duy Linh Email: [email protected]
LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG JAVA Object-Oriented Programming in Java
Version 1.1
3
© Vũ Duy Linh Java – Giới thiệu
Là ngôn ngữ lập trình mới, được phát triển bởi Sun
Microsystems vào năm 1991.
Phiên bản đầu tiên gọi là Oak do James Gosling phát triển.
Năm 1995 tên chính thức được gọi là Java
Một số Nhà phát triển Java: James Gosling, Arthur Van, Karl
Jacob và một số nhân vật nổi bật khác
4
© Vũ Duy Linh Tổng quan về Java SE 7
Java SE Development Kit (JDK) 7 và Java SE Runtime Environment (JRE) 7:
5
© Vũ Duy Linh Môi trường JRE
JRE: là môi trường đòi hỏi cần có để chạy các ứng dụng (Applet, stand alone) được viết bằng ngôn ngữ Java: Giao diện lập trình ứng dụng
Java API (Application Programming Interface)
Máy tính ảo Java (Java Virtual Machine): Sẽ tạo ra một môi trường để thực thi các lệnh bằng cách nạp các file.class, quản lý bộ nhớ và dọn rác,…
Mã nguồn
6
© Vũ Duy Linh Sơ đồ thực thi chương trình
Với Java, mọi hệ điều hành là một!
Tập tin mã nguồn .java Mã trung gian - Byte code Mã máy - Machine code Mã nhị phân -Binary code
7
© Vũ Duy Linh Cấu trúc thư mục chương trình
Byte code files
Source code files
8
© Vũ Duy Linh Sự khác biệt giữa 2 loại kiến trúc mã
Kiến trúc phụ thuộc (Architecture dependent): SưCSử dụng
kiến trúc mã không trung gian. Các ngôn ngữ như: C/C++, Pascal.
9
© Vũ Duy Linh Sự khác biệt giữa 2 loại kiến trúc mã
Kiến trúc độc lập (Architecture independent): Sử dụng kiến trúc mã
trung gian mà ngôn ngữ Java đã tạo nên một cuộc cách mạng mới: Write
once, run anywhere.
/* Giống nhau với mọi platform */
/* Khác nhau trên mỗi flatform */
10
© Vũ Duy Linh Các đặc tính Java (1)
Thân thiện, đơn giản và nhỏ gọn (Familiar, simple, small)
Được biên dịch (Compiled) và được thông dịch (Interpreted)
An toàn, bảo mật (Secure): Kiểm tra an toàn trước từng bước (ngôn ngữ biên dịch thực thi: tính đóng gói .java .class class loader machine code) Từ bên ngoài không thể xâm nhập vào chương trình được.
Kiến trúc mã trung gian (Architecture neutral ): Sinh mã bytecode -
Độc lập với hệ điều hành và có thể chạy ở mọi hệ điều hành
(platform).
Khả chuyển (Portable): JVM dựa trên nền tảng chính POSIX
(Portable Operating System Interface [for Unix]) – Giao diện hệ điều
hành linh động: cung cấp mã nguồn di động cho các thiết bị đầu cuối,
ngoại vi.
11
© Vũ Duy Linh Các đặc tính Java (2)
Hướng đối tượng (Object-oriented)
Hiệu suất cao (High performance): Có cơ chế hỗ trợ trình thông dịch
chạy ở tốc độ tối đa, cơ chế dọn rác (garbage) tự động,…
Mạnh mẽ (Robust): Định kiểu mạnh, tường minh
Phân tán (Distribution): Hỗ trợ TCP, UDP, Socket và Network
communication: Applets, servlets, aglets – hệ thống mobile agents,
remote method invocation (RMI), Common Object Request Broker
Architecture (CORBA) .
Đa tuyến đoạn (Multithreads)
Tính động (Dynamic): Ở thời điểm run-time, các file.class được liên
kết khi cần.
12
© Vũ Duy Linh Một số khác biệt với C++
Không có Typedefs, Defines, hoặc Preprocessor
Không có biến toàn cục: "Global variables are bad"
Không hỗ trợ lệnh Goto
Không có con trỏ số học (pointer arithmetic): Trong Java, hầu hết sự phức tạp và rắc rối cố hữu liên quan đến con trỏ đều được bỏ đi nhằm tạo ra một ngôn ngữ trong sáng, giản đơn.
Không hỗ trợ các cấu trúc không an toàn: Java không có kiểu struct.
Không có đa thừa kế (Multiple inheritance)
Không có nạp chồng toán tử (Operator overloading)
Không có ép kiểu tự động (Automatic coercions)
13
© Vũ Duy Linh Phạm vi ứng dụng Java
JAVA
Mobile
Console GUI
Network
Web Database
RMI
Applet
Cloud
14
© Vũ Duy Linh Các loại chương trình của Java
Có thể phát triển 2 loại chương trình Java: Các chương trình chạy độc lập (Stand-alone
applications): Có chứa phương thức “main” và có thể chạy từ dòng lệnh thông qua trình thông dịch Java.
Các chương trình Web (Web applications/ applets): Không chứa phương thức “main” và là chương trình được nhúng vào trang web và được chạy khi trang web được duyệt.
15
© Vũ Duy Linh Java Development Kit
javac: Trình biên dịch java
java: Trình thông dịch java: Chạy ứng dụng độc lập
jdb : Gỡ rối (Java Debugger)
appletviewer : Chạy ứng dụng applets
javap - to print the Java bytecodes
javaprof - Java profiler
javadoc - documentation generator
javah - creates C header files
16
© Vũ Duy Linh Ứng dụng Standalone
Java source: Hello_StandAloneApp.java
public class Hello_StandAloneApp { public static void main(String args[]) {
System.out.println("Hello! Stand alone application.");
}
}
Biên dịch và thực thi: javac Hello_StandAloneApp.java ↲
(Tạo file: Hello_StandAloneApp.class)
java Hello_StandAloneApp ↲ (Kết quả: Hello! Stand alone application.)
17
© Vũ Duy Linh Ứng dụng applet
Java source: Hello_AppletApp.java
import java.applet.Applet;
import java.awt.*;
public class Hello_AppletApp extends Applet {
public void paint(Graphics g) {
g.drawString ("Hello! Applet application.", 25, 25);
}
} Tạo trang web: Hello_AppletApp.html <HTML>
<TITLE> JAVA APPLET APPLICATION</TITLE>
<APPLET CODE="Hello_AppletApp.class” width=250 height=100>
</APPLET>
</HTML>
18
© Vũ Duy Linh Duyệt trang web
Duyệt trang web bằng trình duyệt FireFox, IE,… Address: [path] Hello_AppletApp.html
19
© Vũ Duy Linh Cài đặt môi trường phát triển ứng dụng Java
Gồm 2 bước:
1. Cài bộ JDK (Java Development Kit): Bộ công
cụ phát triển Java, bao gồm cả môi trường JRE
(Java Runtime Environment) vào hệ thống máy
tính để chạy Java applications và Applets.
2. Các phần mềm hỗ trợ source code:
a. Đơn giản: NotePad, WordPad, EditPlus,…
b. Chuyên nghiệp: NetBeans IDE, Eclipse IDE,
JDeveloper IDE, JCreator IDE.
20
© Vũ Duy Linh Số liệu thống kê
Lịch sử 2004-2013:
21
© Vũ Duy Linh Số liệu thống kê (3)
Hiện tại năm 2014:
22
© Vũ Duy Linh Số liệu thống kê (2)
Ngôn ngữ kịch bản (Client-side scripting):
24
Cấu trúc chương trình Java đơn giản
1 //ProgramName.java
2 //Phần document
3 package packagename;
4 import packagename.ClassName;
5 public class ProgramName{
6 // Khai báo các biến
7 . . .
8 // Định nghĩa các phương thức
9 . . .
10 //Định nghĩa phương thức main.
11 public static main(String args[]){
12 // Phần thân phương thức main
13 } // Kết thúc main method.
14 } // Kết thúc lớp ProgramName
Phần mô tả chương trình
Câu lệnh package
Các câu lệnh import
Định nghĩa các Interface
Định nghĩa các class
Phương thức main của class{
}
Ở phần cơ bản này, chúng ta sử dụng phương pháp lập trình dựa
trên đối tượng Object-Based Programming (OBP) để minh hoạ:
25
© Vũ Duy Linh Chương trình Java cơ bản
1. /* Author: Vũ Duy Linh
2. Topic: A very simple stand-alone application in java
3. File name: HelloWorld.java
4. */
5. import java.lang.*;
6. public class HelloWorld {
7. public static void main( String args[ ] ) {
8. System.out.println( “Hello world!..." );
9. }
10. }
import: Từ khóa khai báo sử dụng gói (package) cần có trong chương trình
class: Từ khóa khai báo lớp
public, static: Access modifiers – các bổ từ truy cập
void: Kiểu giá trị trả về của phương thức
args[ ]: Các đối số nhập từ dòng lệnh
26
© Vũ Duy Linh Biên dịch và thực thi
Biên dịch
javac HelloWorld.java
Out file: HelloWorld.class
Thực thi
java HelloWorld
Kết quả: Hello world!...
27
© Vũ Duy Linh Một số lưu ý thêm (1)
Gói java.lang.* được import một cách mặc định nên lệnh
System.out.println(); chính là java.lang. System.out.println();
Tên đầy đủ - Fully qualified name
28
© Vũ Duy Linh Một số lưu ý thêm (2)
Cách sử dụng đối số từ dòng lệnh:
Gõ lệnh: java FullName_App Vu Duy Thuc
Các đối số: args[0] = Vu, args[1] = Duy, args[2] = Thuc
Từ khoá public: Phạm vi truy cập mọi nơi.
Phương thức static: là phương thức chỉ được phép truy cập tới các
biến static của lớp (do đã được fix sẵn bộ nhớ) và có thể gọi mà
không cần khởi tạo đối tượng của lớp chứa nó.
Từ khoá void: Phương thức không trả về (return;) giá trị nào cả.
29
© Vũ Duy Linh Tính căn bậc 2
// CanBac2.java
import java.lang.Math;
public class CanBac2 {
public static void main(String args []) {
double x = 4; //Giả sử x > 0
double y;
y = Math.sqrt(x);
System.out.println(“Can bac 2 cua " + x + "= " + y);
}
}
30
© Vũ Duy Linh Kiểu dữ liệu nguyên thủy
Kiểu Kích
thước
Khoảng giá trị
boolean 8 bit true hoặc false
byte 8 bit -128 đến 127
short 16 bit -32,768 đến 32,767
int 32 bit -2,147,483,648 đến +2,147,483,647
long 64 bit -9,223,372,036,854,775,808 đến
+9,223,372,036,854,775,807
char 16 bit \u0000 đến \uFFFF (chuẩn unicode)
float 32 bit -3.40292347E+38 đến +3.40292347E+38
double 64 bit -1.79769313486231570E+308 đến
+1.79769313486231570E+308
Kiểu nguyên thuỷ (Primitive data type): là
kiểu mà các phép toán được dịch trực tiếp
sang các lệnh của máy (operational data).
31
© Vũ Duy Linh Biến
Biến (Variable): Theo định nghĩa của Khoa học máy tính, biến gồm một số ô nhớ được định danh (duy nhất) bởi một định danh, đó chính là tên biến. Đây là cách thức thường xuyên được dùng trong lập trình, dùng để chứa một giá trị nào đó có thể thay đổi trong quá trình thực thi chương trình.
Quy tắc đặt tên biến
Bắt đầu bằng chữ cái, dấu gạch dưới (_) hoặc dấu dollard ($), không
có khoảng trắng giữa tên, không trùng với các từ khoá,… Lưu ý:
Java phân biệt chữ hoa chữ thường.
Ví dụ:
• Tên biến đúng: myList1, double_X1, luongCoBan,…
• Tên biến sai: my List1, 2nghiem, luong-Co-Ban,…
Cách khai báo và khởi tạo:
Cách 1: kiểu_nguyên_thuỷ tên_Biến;
tên_Biến = giá_trị;
Cách 2: kiểu_nguyên_thuỷ tên_Biến = giá_trị;
32
© Vũ Duy Linh Kiểu dữ liệu nguyên thủy (2)
Mỗi biến được khai báo chỉ tồn tại trong phạm vi (scope) của nó – tương tự
như ngôn ngữ C đã học.
Các ví dụ: Khai báo (tên) biến a kiểu (nguyên thuỷ) int, gán giá trị của biến a bằng 40
int a; a = 40;
a: tên biến, kiểu là int, và giá trị của a là 40.
double diemThi =9.5; //biến số thực diemThi bằng 9.5
int octVal = 032; int hexVal = 0x1a; char characterC = 'C';
unicodeC='\u1EE9'; (Java sử dụng UTF-16)
String hoTen = "Ch\u00e0o b\u00e9: V\u0169\u0020Duy\u0020Th\u1EE9c!"
0
a
40
a
33
© Vũ Duy Linh Cấp phát trên bộ nhớ
Cho đoạn lệnh Java:
int a = 10; int b;
b = a; a += 10;
34
© Vũ Duy Linh Hằng
Hằng (Constant): cũng tương tự như biến ngoại trừ nó giữ một giá trị cố định (hay được gọi là các biến chỉ đọc)
Chúng được khai báo bởi từ khóa final
final int SI_SO = 100;
final double PI = 3.1428;
Kiểu chữ in hoa thường được dùng để đặt tên cho các hằng.
35
© Vũ Duy Linh Hằng (2)
Ví dụ hằng:
public class DienTichHinhTron {
public static void main(String args[]) {
final double PI = 3.1428;
double bk = 5.5; // ban kinh
double dt; // dien tich
dt = PI * bk * bk
System.out.println("Ban kinh= "+ bk + ", dien tich= " + dt);
}
}
36
© Vũ Duy Linh Lệnh rẽ nhánh - if
Có 3 dạng: if (boolean_expression) { statement(s); }
if (boolean_expression) { statement(s); } else { statement(s); }
if (boolean_expression_1) { statement(s); } else if (boolean_expression_2){ statement(s); } else { statement(s); }
Kết quả: 7 <= 8
Ví dụ:
Với: boolean_expression: Là biểu thức lô-git đúng/sai,
statement: Biểu thức tính/câu lệnh
37
© Vũ Duy Linh Lệnh rẽ nhánh - switch
Cú pháp Swich:
switch (evaluated_expression) { case constant_expression_1: statements_1; … case constant_expression_n: statements_n; default: default_statements;
}
Biểu thức phân nhánh (evaluated_expression): có kiểu rời rạc như
int, char, hoặc enum.
Có kết hợp với các lệnh continue; hoặc break;
38
© Vũ Duy Linh switch (2)
Kết quả: Gia tri bien c KHONG la 'a' hoac 'b' ma la 'V'
Ví dụ:
39
© Vũ Duy Linh Lệnh lặp For và For-each
Cú pháp For:
for (initialization; boolean-expression; step){ statement(s);
}
Với Initialization: Khởi tạo biến chạy, boolean-expression: điều kiện dừng, step: bước nhảy tăng hoặc giảm
Ví dụ:
Kết quả: 1 3 5 7 9
Cú pháp For-each: for (type vaiable : collection){
statement(s);
}
hoặc for (type vaiable: array) {
statement(s);
}
40
© Vũ Duy Linh
Cú pháp:
while (boolean_expression) {
statement(s)
}
Sẽ lặp cho đến khi điều kiện trở thành false
Lệnh lặp While
Kết quả: 1 3 5 7 9
41
© Vũ Duy Linh Lệnh lặp Do while
Cú pháp:
do {
statement(s)
} while (boolean_expression);
Kết quả: 1 3 5 7 9
42
© Vũ Duy Linh
Cú pháp:
Access_modifiers return_type tênPhươngThức( [Các_tham_số]){ [Local_declaration(s);]
Statement(s);
}
Local declaration(s): Biến/hằng được khai báo bên trong phương thức là cục bộ và chỉ được hiểu trong phương thức chứa nó.
Access_modifiers: Các bổ từ truy cập
Return_type: Kiểu dữ liệu của kết quả trả về.
• void: Không trả về giá trị nào cả (return; )
• Chỉ có thể trả về tối đa giá trị của một kiểu dữ liệu.
Ví dụ: phương thức tính diện tích hình tròn có 1 tham số hình thức.
protected double tinhDienTich(double r){
return (Math.PI*Math.pow(r,2);
}
Phương thức
43
© Vũ Duy Linh Ví dụ
Giải phương trình bậc 2 theo OBP, gồm 2 lớp: PTB2 và LopChinh
44
© Vũ Duy Linh Ví dụ (2)
46
© Vũ Duy Linh Các mẫu hình lập trình
Mẫu hình lập trình tuần tự (Imperative paradigm)
Mẫu hình lập trình mô tả (Declarative paradigm)
Lập trình hàm (Functional programming)
Lập trình logic (Logic programming )
Mẫu hình lập trình hướng đối tượng (Object-oriented paradigm)
Mẫu hình lập trình hướng định dạng/khía cạnh (Aspect-oriented
paradigm)
47
© Vũ Duy Linh Mô hình lập trình tuần tự
Phục vụ cho thời kỳ đầu máy tính và ngôn ngữ asembler
Cách làm tuần tự từng bước (step-by-step) để cụ thể hóa bài toán được làm như thế nào (how to get sth)
Các biến được đại diện trong bộ nhớ
Sử dụng lệnh gán để thay đổi trị biến
Các ngôn ngữ tiêu biểu: Algol, Pascal, C, Ada
procedure Fibo(n: integer);
var a, b, kq: integer;
begin
a := 0; b:=1;kq:=0;
while (kq < n) do
begin
kq := q + b; write(kq:4);
a = b; b = kq;
end;
end;
48
© Vũ Duy Linh
Declarative programming: Để miêu tả bài toán cần giải quyết được định nghĩa như thế nào.
Nó dựa trên cách lập trình định nghĩa hàm (definition-based functional programming): Lập trình hàm (Functional programing)
Lập trình logic (Logic programing)
Lập trình hàm: Ước lượng các hàm toán học
Không làm thay đổi dữ liệu
Chương trình chính là một tập các hàm
Các ngôn ngữ tiêu biểu: Lisp, Refal, Perl, Planer,…
Lập trình logic: Xác định kết suy diễn của bài toán là thành công hay thất bại
Dựa vào một tập các phép logic được định nghĩa: các sự kiện/tiên đề, các luật logic
Các nguyên lý hợp nhất (Unification), nguyên lý giải (Resolution)
Ngôn ngữ tiêu biểu: Prolog
(+ x y) x + y
Mô hình lập trình mô tả
49
© Vũ Duy Linh Mô hình lập trình mô tả (2)
Ngôn ngữ LISP
(max 3 10 -10 15 7) 15
(defun factorial (N)
"Compute the factorial of N."
(if (<= N 1)
1
(* N (factorial (- N 1)))))
Bài toán n! được định nghĩa là:
“bằng 1 nếu n <=1 ngược lại bằng n*(n-1)!
Bài toán n! được định nghĩa theo cú pháp Prolog.
Ngôn ngữ Prolog
mortal(X) :- human(X).
human(socrate).
?- mortal(socrate).
Yes, Sorate is mortal.
fac(0,1).
fac(N,F) :- N>0,
M is N-1,
fac(M, Fm),
F is N * Fm.
50
© Vũ Duy Linh Mô hình lập trình hướng đối tượng
Dựa trên nền tảng đối tượng (Object)
Chương trình bao gồm nhiều tập quần thể đối tượng khác nhau, mỗi quần thể đối tượng thuộc vào một loài/ loại/ lớp (Class) riêng biệt.
Sự thực thi chương trình là sự trao đổi thông điệp (messages) giữa các đối tượng với nhau.
thuần OOP: Mọi thứ là đối tượng ngay cả các kiểu nguyên thủy (primitives)
Ngôn ngữ thuần OOP: Smalltalk, Eiffel.
1 lớp Xe
4 chiếc xe
4 đối tượng
thuộc lớp Xe
51
© Vũ Duy Linh Kết hợp các mô hình
Ngôn ngữ lập trình hiện đại thường có sự kết
hợp giữa các mô hình:
Imperative + OO Paradigms: C++, Java, Object
Pascal, Ada
Fuctional + OO Paradigms: Clos (Common Lisp
Object System)
Logic + OO Paradigms: Object Prolog
52
© Vũ Duy Linh Quá trình phát triển chương trình HĐT
1. Đặc tả bài toán 2. Phân rã bài
toán 3. Phân tích các thực thể tồn
tại trong bài toán (Trừu tượng hoá)
4. Viết mã lệnh Java 5. Kiểm thử
6. Chỉnh sửa lại.
1
2
3
4
5
6
53
© Vũ Duy Linh Sự ánh xạ thế giới thực vào OOP
- Được hực hiện thông qua
sự trừu tượng hóa.
- Sự trừu tượng hóa: là
quá trình xác định các thuộc
tính và các hành động liên
quan đến mỗi thực thể trong
môi trường ứng dụng đang
được phát triển (có nhiều
đối tượng thuộc các loại
khác nhau).
54
© Vũ Duy Linh Sự trừu tượng hóa - Abstraction
Trừu tượng dữ liệu ( Data abstraction): là các đặc tính (properties) của kiểu dữ liệu
và sự cài đặt cụ thể nó Định nghĩa kiểu dữ liệu (thực thể) ở mức trừu tượng interface
và cài đặt nó ở mức cụ thể.
Phép tính a = (1+2) * 5 được
thức hiện như thế nào trên
máy tính, dễ hay khó?
Abstract
properties
Sự trừu tượng hoá điều khiển ( Control abstraction): Là sự trừu tượng các thao tác/
phép toán ở mức thấp. Các ngôn ngữ lập trình đã làm sẵn việc này, giúp giảm bớt công
sức của lập trình viên.
Rất đơn giản nếu sử dụng NNLT
bậc cao, “mệt” nếu sử dụng ngôn
ngữ máy (Machine language)
Tính toán, xử lý ntn để
có kết quả a = 15?
55
© Vũ Duy Linh Sự trừu tượng hóa - Abstraction
Class (kiểu dữ liệu thực thể): Là sự kết hợp của data abstraction + Control abstraction
56
© Vũ Duy Linh Các đặc tính Java hướng đối tượng
Java OOP Paradigm
Encapsulation
Multiple Inheritance
Delegation
Concurrency
Polymorphism
Single Inheritance
Abstraction
Persistence
Genericity
57
© Vũ Duy Linh Sự đóng gói - Encapsulation
Sự đóng gói: Là việc cài đặt mã lệnh cho các phương thức nội tại và cách
thức truy xuất các thuộc tính của lớp thành một đơn vị duy nhất Cung cấp
một cơ chế bảo vệ dữ liệu (đối tượng): che dấu và bảo vệ dữ liệu khỏi người
dùng (can thiệp hoặc thao tác sai mục đích).
Outside code: Phần nhìn
thấy cho người dùng
Inside code: Phần che
khuất khỏi người dùng
58
© Vũ Duy Linh Sự trừu tượng - Abstraction
OOP sử dụng cả data và control abstraction.
Abstraction Class: tập các thuộc tính và thao tác (phương thức).
Lớp GiangVien: có 3 thuộc tính và 2 phương thức.
3 Attributes
2 Operations
V V
59
© Vũ Duy Linh Thừa kế- Inheritance
Thừa kế (Inheritance): Là một cơ chế cho phép lập trình viên định nghĩa một lớp con mới (Child/ sub/ derived class) bằng cách mở rộng từ (các) lớp cha (Parent/ super/ base class) đã tồn tại. Đây là đặc tính nổ bật nhất của OOP và là một cuộc cách mạng của lĩnh vực công nghệ phần mềm.
Lớp con thừa hưởng các đặc điểm (properties = attribute + operations) từ lớp cha trong phạm vi truy xuất được phép.
Quá trình phân tích tìm các lớp con dẫn xuất từ lớp cha được gọi là chuyên biệt hoá (Specialization).
Parent
Child
Phần chung: - Được kế thừa - Có thể reused vì không cài đặt lại
60
© Vũ Duy Linh Thừa kế
Chuyên biệt hoá là quá trình phân lớp quần thể các đối tượng chung của lớp cha ra thành những lớp quần thể con nhỏ hơn (có chung đặc tính) của các lớp con khác nhau phương pháp lập trình top-down.
Mối liên kết giữa lớp con và lớp cha là mối liên kết Là-Một (Is-A) của lớp cha.
c
à
n
g
tổng quát (trừu tượng)
chuyên biệt (cụ thể)
Ex: Nguoi Is-A DongVatCoVu: “Người là một loài động vật có vú”,…
61
© Vũ Duy Linh Các loại thừa kế lớp trong Java
Các dạng thừa kế trong lập trình hướng đối tượng Java là:
Thừa kế đơn (Single inheritance): Một con một cha
Thừa kế phân cấp (Hierarchical inheritance): Nhiều con một cha
Thừa kế đa cấp (Multi-level inheritance): Là dạng Thừa kế Hierarchical nhưng cho phép nhiều cấp (như: chắtkj cháuji coni cha)
Hierarchical
inheritance
Single
inheritance Multi-level
inheritance
62
© Vũ Duy Linh Các loại thừa kế lớp ngoài Java
Thừa kế bội (Multiple inheritance): Một con thừa kế từ nhiều cha. VD: C++
Thừa kế lai (Hybrid inheritance): Là sự kết hợp 2 trong 4 cách trên
Thừa kế đa lối (Multi-path inheritance): Giống như dạng Hybird nhưng được dẫn xuất cùng một lớp cha (base class).
Q & A
63
© Vũ Duy Linh Tính đa hình
Đa hình (Polymorphism): Là khả năng đảm nhận nhiều dạng - Một hoạt động (thông
qua phương thức) được đối tượng thực hiện bằng nhiều cách khác nhau, và các đối
tượng khác loại cùng thực hiện chung một ứng xử theo cách riêng của mình.
Giúp cho chương trình trở nên tổng quát hơn chứ không đơn điệu cá biệt
Có 2 hình thức đa hình:
1. Đa hình tĩnh (Static polymorphism):
được thực hiện thông qua phương pháp
nạp chồng (overloading) ở thời điểm
biên dịch chương trình (early binding)
Đa hình phương thức.
Biên dịch thành byte-code vì biết rõ
phương thức nào sẽ được thực thi
2. Đa hình động (Dynamic polymorphism):
được thực hiện thông qua phương pháp
ghi chồng (overriding) ở thời điểm thực
thi chương trình (late binding) Đa
hình đối tượng.
Chỉ xác định được phương thức
nào được thực hiện ở thời điểm
thực thi
64
© Vũ Duy Linh Tính bền vững
Tính bền vững (Persistence): Mục đích lưu giữ sự tồn tại của đối tượng lâu hơn sự thực thi của chương trình.
Với Native Java persistence bằng tuần tự hoá:
Bằng cách ghi đối tượng vào nơi an toàn (không bị xung đột) rồi sau đó đọc ra để sử dụng lại các thư viện hỗ trợ: java.io.FileInputStream; java.io.FileOutputStream; java.io.ObjectInputStream; java.io.ObjectOutputStream; Cơ chế để đảm bảo sự bền vững là sự tuần tự hóa (serialization) - java.io.Serializable;: Nó chuyển đổi dữ liệu (đối tượng) vào luồng (byte stream) và ghi nó vào tập tin (CSDL, bộ nhớ) để lưu trữ - sử dụng phương thức writeObject(). Chương trình sẽ được java bean khôi phục lại bằng cơ chế deserialization để có được trạng thái ban đầu của đối tượng - sử dụng phương thức readObject().
65
© Vũ Duy Linh Tính bền vững CSDL trong Java - Persistence database
Với các framework hỗ trợ persistence: JPO/OpenJPA, TopLink, EclipseLink, Hibernate,…
và với JPA trong Java EE, và Java Data Objects (JDO API) của Cộng đồng Java (Java Community Process):
66
© Vũ Duy Linh Đồng bộ hóa, sự ủy quyền
Đồng bộ hóa (Concurrency): Là cơ chế cho phép thực hiện
nhiều chức năng/công việc tại một thời điểm. VD như hệ điều
hành đa nhiệm - Java thực hiện thông qua cơ chế tiến trình
(processes) và tuyến đoạn (threads) và tuần tự hoá
(synchronization). Java API là gói java.util.concurrent;
Sự ủy quyền (Delegation): Cho phép một phương thức
method_A của lớp A thực hiện một nhiệm vụ thông qua một
phương thức method_B ở lớp B.
Point
xCoord yCoord
getXCoord() getYCoord()
Circle
centre
getCentreX() getCentreY()
Phương thức getCenterX()
của đối tượng lớp Circle
thực hiện tính xCord của
tâm hình tròn thông qua
phương thức getXCoord
thuộc đối tượng lớp Point
67
© Vũ Duy Linh Kỹ thuật tổng quát
Kỹ thuật Generic: Cho phép sự trừu tượng hóa các phần tử dữ liệu
mà không cụ thể chính xác kiểu của chúng. Các kiểu tổng quát
(chưa biết) này chỉ được xác định ở thời điểm sử dụng chúng.
E là tham số hình thức có kiểu tổng
quát ở thời điểm định nghĩa.
Khi sử dụng List<Integer> thì E được
thay thế bằng kiểu của đối số thực (là
Integer)
68
© Vũ Duy Linh Lợi ích của OOP
Sự tin cậy cao hơn: Phân các dự án phần mềm phức tạp
thành các mô đun các đối tượng nhỏ hơn (Package)
Khả năng bảo trì phần mềm: Với các gói nhỏ (mô-đun) sẽ
giúp dễ phát hiện lỗi và sửa lỗi hơn
Năng suất cao hơn thông qua tính sử dụng lại (Reused)
Inheritance: Làm giảm bớt sự dư thừa mã lệnh, mở rộng việc
sử dụng các class đang tồn tại
Encapsulation: Giúp cho xây dựng chương trình an toàn
hơn.
OOP dễ dàng ánh xạ các đối tượng trong miền xác định của
bài toán tới các đối tượng trong chương trình
Những hệ thống hướng đối tượng có thể được nâng cấp từ
hệ thống nhỏ sang lớn dễ dàng.
Chương 4. Lớp, đối tượng và gói
Class, Object, Package
Giảng viên: Vũ Duy Linh Email: [email protected]
70
© Vũ Duy Linh Khái niệm
Lớp (Class): đại diện cho một mẫu các đối tượng có chung những đặc điểm giống nhau, bao gồm các thuộc tính (attributes) và các hành vi (operations) của nó.
Trên sơ đồ, lớp có 03 phần: ClassName, Field(s), Method(s) như sau:
Ví dụ: Lớp Sinh viên, lớp Giảng viên, lớp Động vật có vú,…
Lớp Giảng viên, ta quan tâm đến 03 đặc điểm là: Mã số, họ tên, chuyên ngành, và 02 hoạt động là: dạy học và nghiên cứu khoa học.
Dữ liệu thành viên (trường và phương thức) được phân ra 2 nhóm: Thành viên thể hiện (Instance members): Là các biến thể hiện và các phương
thức thể hiện. Đây là phần dữ liệu dành riêng cho mỗi đối tượng được tạo ra Với cách này, địa chỉ của mỗi đối tượng được lưu trong vùng nhớ là khác nhau.
Thành viên lớp (Class/static members): Là các biến lớp (static variables) và phương thức lớp (static methods). Đây là phần dữ liệu dành riêng cho lớp và được truy xuất trực tiếp bởi tên lớp Với cách này, các đối tượng được tạo ra từ lớp này sẽ có chung địa chỉ của biến lớp biến chung cho các đối tượng.
Tên lớp
Các trường
Các phương thức
4 biến thể hiện
(instance variables)
1 biến lớp (static variable)
2 phương thức thể hiện
(instance methods)
71
© Vũ Duy Linh Khái niệm (2)
Đối tượng (Object): Là một thể hiện, instance, của một lớp là một biến thuộc kiểu dữ liệu lớp.
Đối tượng thì có trạng thái (states), còn lớp thì không. Trạng thái chính là giá trị riêng của mỗi đối tượng và được lưu vào trong các biến thể hiện.
Hệ thống hướng đối tượng là một tập các đối tượng tương tác với nhau.
Các phương thức là tập các lệnh tuần tự dùng để thao tác trên các trường.
Lớp GiangVien Hai đối tượng: gv1, gv2 thuộc lớp GiangVien
72
© Vũ Duy Linh Các loại lớp
Lớp chuẩn Java (Standard class): Là các lớp đã được xây dựng sẵn (thư viện Java - Java API). Lớp tổ tiên trong Java là:
java.lang.Object;
Lớp tự định nghĩa (Programmer-define class): Là các lớp được lập trình viên tự định nghĩa ra thông qua việc trừu hóa các lớp đối tượng trong môi trường bài toán.
Các lớp này được gọi chung là kiểu dữ liệu tham chiếu/ đối tượng (Reference/ Object data types)
73
© Vũ Duy Linh Lớp chuẩn
Các thư viện chuẩn: java.lang.*, java.awt.*, java.util.*
Ví dụ: Lấy căn hai của 25 ta sử dụng lệnh
Nạp thư viện vào: import java.lang.*
Gọi phương thức: double ketQua = Math.sqrt(25);
74
© Vũ Duy Linh Lớp tự định nghĩa
Cú pháp tổng quát:
Khai báo biến trường trong lớp (member variables):
[Modifier] data-type fieldName;
Khai báo phương thức trong lớp (member methods):
// hoặc Members
75
© Vũ Duy Linh Lớp tự định nghĩa (2)
[Modifier] class TênLớp { //Modifier ở mức lớp
[Modifier] data_type tênTrường_1; //Modifier ở thành viên
...
[Modifier] data_type tênTrường_n;
[Modifier] return_type tênPhươngThức_1([Các_Tham_số]) {
//…
return (giá trị trả về);
}
...
[Modifier] return_type tênPhươngThức_m([Các_Tham_số]) {
//…
return (giá trị trả về);
}
}
* Chú ý: Các thành phần tùy chọn (trong cặp [ ]) sẽ được đề cập sau.
Cú pháp chi tiết:
76
© Vũ Duy Linh Lớp tự định nghĩa (3)
Có 02 mức khác nhau của bổ từ truy cập (modifier): Mức lớp (Class level):
public: Lớp sẽ được truy cập ở mọi nơi trong dự án – anywhere.
Không có modifier: Lớp chỉ được truy cập trong phạm vi cùng gói (package).
Các bổ từ astract, final sẽ được học ở các chương sau.
Mức các thành viên của lớp (Member level: fields và Methods): private: Các thành viên chỉ có thể được truy xuất trong phạm vi bên
trong lớp chứa nó, ngay cả các thành viên ở lớp con cũng không thể truy xuất tới (không được thừa kế).
public: Các thành viên của lớp sẽ được truy cập ở mọi nơi
Không có modifier (friendly/ package access): Trong cùng gói là public còn khác gói là private.
protected: Các thành viên được truy xuất bởi các phương thức ở cùng lớp, các phương thức ở trong các lớp con (được thừa kế) và các phương thức ở khác lớp nhưng phải cùng gói
Các bổ từ final, synchronized, transient, native,… sẽ được học sau.
77
© Vũ Duy Linh Lớp tự định nghĩa (4)
Ví dụ 1: Định nghĩa kiểu dữ liệu lớp HinhTron mà các thành viên
chỉ gồm các biến và các phương thức thể hiện:
public class HinhTron { //Mức lớp: truy cập được mọi nơi
private int x, y; // Mức thành viên: riêng của lớp
private double banKinh; // 3 biến thể hiện
public double tinhChuVi() { // Mức thành viên: truy cập được mọi nơi
return 2 * Math.PI * banKinh; // 2 phương thức thể hiện
}
public double tinhDienTich() {
return Math.PI * banKinh * banKinh;
}
}
Phạm vi truy nhập ở mức lớp HinhTron là public, mức của 3 biến
thể hiện là private, và mức 2 phương thức thể hiện là public.
78
© Vũ Duy Linh Lớp tự định nghĩa (5)
Bảng phạm vi truy cập ở mức thành viên
Quyền truy xuất
Phạm vi
public protected default private
Ở cùng lớp Yes Yes Yes Yes
Ở khác lớp và cùng gói Yes Yes Yes No
Ở lớp con và cùng gói Yes Yes Yes No
Ở lớp con và khác gói Yes Yes No No
Ở khác lớp vàkhác gói Yes No No No
79
© Vũ Duy Linh Lớp tự định nghĩa (6)
Lớp hằng/tận cùng (Final class): được khai báo với bổ từ modifier là final, nghĩa là không cho phép mở rộng hoặc thừa kế cho lớp con nữa.
Phương thức hằng (Final method): có modifier là final và không cho phép ghi chồng lên nó.
Biến hằng (Final variable): sử dụng từ khóa final.
80
© Vũ Duy Linh Đối tượng
Đối tượng (Object): Là một thể hiện của lớp, do vậy nó được
khai báo, khởi tạo thông qua một lớp đã được định nghĩa.
Cách 1: Khai báo và khởi tạo riêng biệt
Khai báo: TênLớp tênBiếnĐốiTượng;
Ví dụ: HinhTron ht1;
(Đọc là: biến ht1 (có kiểu HinhTron và được) tham chiếu tới null)
Khởi tạo: tênBiếnĐốiTượng = new TênLớp([Các_đối_số]);
Ví dụ: ht1 = new HinhTron();
(Đọc là: biến tham chiếu đối tượng hình tròn ht1
biến ht1 tham chiếu tới đối tượng hình tròn
giá trị của ht1 là một tham chiếu tới đối tượng hình tròn
địa chỉ của đối tượng hình tròn được trỏ bởi biến ht1)
Cách 2: Khai báo và khởi tạo một lần
Cú pháp: Tên_Lớp tênBiếnĐốiTượng = new TênLớp([Các_đối_số]);
Ví dụ: HinhTron ht2 = new HinhTron();
ht1 null
HinhTron
ht1
ht2
HinhTron
81
© Vũ Duy Linh Đối tượng (2)
Sự cấp và quản lý biến trong Java: Java có kiểu nguyên thủy và kiểu đối tượng,
chúng được cấp phát và tham chiếu như hình sau.
82
© Vũ Duy Linh Đối tượng (3)
Ví dụ 2: Viết chương trình (theo OBP) để tạo một hình tròn có toạ độ tâm
O(50,100), bán kính bằng 30 và hiển thị thông tin và diện tích của nó.
Source code: OBP_HinhTron.java
class HinhTron{
int x=50; int y=100; double banKinh=30;
double tinhDienTich(){
return Math.PI*Math.pow(banKinh, 2);
}
}
public class OBP_HinhTron {
public static void main(String[] args) {
HinhTron ht= new HinhTron();
System.out.printf("Hinh tron vua tao co tam O(%d,%d)"
+ " va dien tich= %.4f\n",ht.x,ht.y,ht.tinhDienTich());
}
}
83
© Vũ Duy Linh Đối tượng (4)
Phương thức dựng (Constructors) : Dùng để tạo một đối tượng, khởi tạo giá trị ban đầu cho thuộc tính của đối
tượng được tạo ra (nếu có).
Tên phương thức cùng tên với tên lớp
Không có kiểu trả về (kiểu void: không có giá trị trả về)
Có thể có nhiều phương thức dựng: Sử dụng phương thức nạp chồng (Overloading) của tính đa hình để viết
Sử dụng từ khóa this để tham chiếu đến chính đối tượng được tạo. Nó được dùng để phân biệt giữa biến thể hiện (instance variables) và các tham số hình thức khi chúng giống tên nhau
Sử dụng từ khóa supper để tham chiếu tới đối tượng thuộc lớp cha. Nó được dùng để gọi các phương thức, các biến thể hiện từ lớp cha
Java có sẵn một phương thức dựng mặc định (không có tham số) để gán tất cả các biến thể hiện bằng zero. Chúng ta có thể ghi chồng (Overriding ) phương thức mặc định này.
Phương thức hủy (Destructors ): Khác với C and C++, sự thu hồi bộ nhớ được Java tự động thực hiện
Java cung cấp một phương thức được gọi bởi Garbage collector, giúp cho ta thực hiện các yêu cầu trước khi đối tượng bị hủy, đó phương thức finalize()
Ta có thể ghi chồng lại phương thức finalize() này để quản lý các đối tượng trong chương trình.
84
© Vũ Duy Linh Đối tượng (5)
Phương thức thiết lập (Setters):
Dùng để gán giá trị (set) các biến thể hiện (private) của mỗi lớp.
Được gọi là phương thức thay đổi (mutator methods)
Có sự kiểm tra sự hợp lệ dữ liệu trước khi thiết lập giá trị trong setters để trở nên an toàn hơn.
Phương thức đọc (Getters):
Dùng để lấy (get) giá trị các biến thành viên của mỗi lớp.
Được gọi là phương thức truy xuất (accessor methods)
Các phương thức setters/getters là một cách bao đóng dữ liệu – chúng thường là các phương thức public để tạo ra một “kênh” giao tiếp với người dùng bên ngoài, nhằm truy xuất các dữ liệu riêng (private) của đối tượng thuộc lớp vừa định nghĩa được an toàn, bảo mật.
Thông thường, mỗi một biến thành viên sẽ có một cặp phương thức getter, setter.
85
© Vũ Duy Linh Đối tượng (6)
Lớp Circle
Circle
get
x, y, radius
set
Ví dụ 3: Viết chương trình định nghĩa một lớp có tên Circle có chứa các phương thức: dựng, set, get và tính diện tích của nó.
class Circle{ private int x, y, radius; // 3 biến thể hiện //Các phương thức dựng public Circle() { // ghi chồng pthức dựng mặc định x = y = 10; radius = 1; } public Circle(int radius) { // có 1 tham số hình thức this.radius = radius; } public Circle(int x, int y, int radius) { // các tham số cùng tên this.x = x; // với biến thể hiện this.y = y; this.radius = radius; } //Các phương thức setters/getters public int getRadius() { return radius; }
86
© Vũ Duy Linh Đối tượng (7)
public void setRadius(int radius) {
if (radius > 0){ // kiểm tra tính hợp lệ dữ liệu
this.radius = radius;
} else{
System.err.println(“Ban kinh hinh tron phai lon hon khong. ");
}
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
//Phương thức thể hiện
public double computeArea(){
return Math.PI*Math.pow(radius, 2);
}
} // Kết thúc định nghĩa lớp Circle
87
© Vũ Duy Linh Đối tượng (8)
public class Main { // lớp chính
public static void main(String[] args) {
Circle c1 = new Circle(20,20,10); // ban đầu bán kính là 10
System.out.printf("Dien tich voi ban kinh= %d la: .2f\n",c1.getRadius(), c1. computeArea ());
c1.setX(40); // dời toạ độ x = 40,
c1.setRadius(5); // đổi bán kính = 5
System.out.printf("Dien tich voi ban kinh= %d la: %.2f\n",c1.getRadius(), c1. computeArea ());
}
} (0,0) x
y
88
© Vũ Duy Linh Đối tượng (9)
Ví dụ 4: Tính n giai thừa theo OBP:
import java.util.Scanner;
public class GiaiThua {
int n;
public GiaiThua() { //Nhập n thông qua phương thức dựng
/*super(); */ Scanner in = new Scanner(System.in);
System.out.print("Nhap so nguyen n="); n= in.nextInt(); in.close();
}
public void tinhGiaiThua(){
long gt=1;
if(n<0) System.out.println("n= "+n+": Khong tinh giai thua.");
else{ for(int i=1; i<=n; i++) gt = gt*i;
System.out.println(n+"!= " + gt); }
}
public static void main(String[] args) {
GiaiThua gt = new GiaiThua(); gt.tinhGiaiThua(); }
}
89
© Vũ Duy Linh Đối tượng (10)
Biến và phương thức lớp - Static members:
Java cung cấp cách định nghĩa phương thức và biến “toàn cục” của lớp để mà các đối tượng thuộc lớp này sẽ có “điểm chung” kết dính cho nhau. Các phương thức và biến đảm nhận được nhiệm vụ như thế được gọi là biến và phương thức lớp.
Biến lớp (Class variables)và Phương thức lớp (Static methods):
Được khai báo với từ khóa static
Được tham chiếu thông qua tên lớp (không cần tạo đối tượng của lớp)
Biến lớp là phần dữ liệu dành riêng cho lớp và là biến chung cho tất cả các đối tượng được tạo ra từ lớp.
Phương thức lớp chỉ tham chiếu đến các biến lớp và các phương thức lớp (khác) và không sử dụng từ khóa this và sufer
Là phương thức được sử dụng để thiết kế các lớp mà các phương thức trong lớp không phụ thuộc vào các biến thể hiện của chúng. Chẳng hạn như thư viện chuẩn java.lang.Math
90
© Vũ Duy Linh Đối tượng (11)
Ví dụ 5: Viết chương trình để định nghĩa kiểu lớp Circle, sau đó
đếm số đối tượng được tạo ra/ được huỷ khi chạy chương trình?
91
© Vũ Duy Linh Đối tượng (12)
92
© Vũ Duy Linh Đối tượng (13)
Run
93
© Vũ Duy Linh Truyền tham số
Khi gọi phương thức có chứa tham số, ta cần phải truyền đối số
cho nó. Trong Java, vì không có khái niệm con trỏ, nên tất cả các
kiểu dữ liệu đều được truyền bằng tham trị (Pass by value).
Đối với biến kiểu nguyên thủy (Primitive type variable): Khi ta
ra lời gọi phương thức thì Java sẽ tạo một bản sao của biến tham
số thực (tst) và bản sao này sẽ truyền cho tham số hình thức (tsht)
giá trị của biến bản sao tst này sẽ bằng với giá trị của biến tsht
nhưng KHÔNG ảnh hưởng đến giá trị của tst ban đầu.
Đối với biến kiểu tham chiếu/ đối tượng (Reference/ Object
type variable): Java cũng truyền đối số bằng trị, nghĩa là giá trị
(của) biến tham chiếu của tst sẽ được truyền cho biến tham chiếu
của tsht. Như vậy, biến tst và tsht đều tham chiếu đến cùng một đối
tượng giá trị của chúng sẽ ẢNH HƯỞNG đến nhau.
94
© Vũ Duy Linh Truyền tham số (2)
Ví dụ 6 - Dự án gồm 3 lớp: HinhTron, TruyenThamSo, LopChinh
/**
* @author Vu Duy Linh
* Object-Based Programming, Truyen tham so...
*/
class HinhTron{
private int bk;
private String trThai;
public void setBk(int bk) {this.bk = bk;}
public void setTrThai(String trThai) {
this.trThai = trThai;
}
@Override
public String toString() {
return "\n\t>>> Trang thai: \""+ trThai+
"\" va ban kinh= "+ bk ;
}
}
95
© Vũ Duy Linh Truyền tham số (3)
public class PassParametters {
static void testPassObj(HinhTron ht2){
ht2.setTrThai("Da cap nhat"); // thay doi tsht
ht2.setBk(400);
}
static void testPassPri(int a){
a = 200; // thay doi tsht
}
public static void main(String[] args) {
int x = 100; //tst
System.out.println("Gia tri x TRUOC khi goi testPassPri= "+x);
testPassPri(x);
System.out.println("Gia tri x SAU khi goi testPassPri= "+x);
96
© Vũ Duy Linh Truyền tham số (4)
HinhTron ht1 = new HinhTron(); //tst
ht1.setTrThai("Ban dau");
ht1.setBk(300);
System.out.println("Thong tin hinh tron TRUOC khi goi testPassObj:"+ht1.toString());
testPassObj(ht1);
System.out.println("Thong tin hinh tron SAU khi goi testPassObj"+ht1.toString());
}
}
Kết quả:
Gia tri x TRUOC khi goi testPassPri= 100
Gia tri x SAU khi goi testPassPri= 100
Thong tin hinh tron TRUOC khi goi testPassObj:
>>> Trang thai: "Ban dau" va ban kinh= 300
Thong tin hinh tron SAU khi goi testPassObj
>>> Trang thai: "Da cap nhat" va ban kinh= 400
97
© Vũ Duy Linh Truyền tham số (5)
Ban đầu ht1
* Biến kiểu nguyên thủy:
Tham số thực Phương thức được gọi đang hoạt động
100 x-copy
100 a 200
Phương thức được gọi kết thúc
100 x
a
N/A
giải phóng
biến bởi GC
Phương thức được gọi đang hoạt động Tham số thực
Ban đầu ht1
ht2
Đã
cập nhật ht1
ht2
Đã
cập nhật ht1
ht2
null
giải phóng biến
Phương thức được gọi kết thúc
* Biển kiểu tham chiếu:
100 x
Thay đổi
Thay đổi
Sơ đồ minh hoạ:
x-copy
98
© Vũ Duy Linh Gói
Gói (Package): Là một cách để gom chung các kiểu dữ liệu (lớp, giao
diện,…) có liên hệ với nhau thành một nhóm với phạm vi quyền truy xuất
nhất định - việc quan trọng đối với những dự án phát triển theo phương
pháp lập trình HĐT.
Cú pháp:
package tên_gói[.tên_gói_con];
Ví dụ: package mycalculator;
package mycalculator.display;
package mycalculator.processing;
Quyền truy xuất
Phạm vi
public protected default private
Ở cùng lớp Yes Yes Yes Yes
Ở khác lớp và cùng gói Yes Yes Yes No
Bảng phạm vi truy cập ở mức thành viên
99
© Vũ Duy Linh Gói (2)
Ví dụ 7: Phương trình bậc hai có 2 lớp khác nhau và chung gói
100
© Vũ Duy Linh Gói (3)
101
© Vũ Duy Linh Gói (4)
Error
Successful
102
© Vũ Duy Linh Gói (5)
Ví dụ: Tạo một dự án (Project) có 02 gói
Gói 1 - package1: gồm (các) lớp chứa các phương thức để tính
cộng, và trừ hai số nguyên: x+y, x-y
Gói 2 - package2: gồm (các) lớp có chứa phương thức sau:
• phép nhân a * b = a + a + … +a (b lần): thông qua lời gọi phương
thức cộng ở package1
• Sử dụng hai phương thức cộng ở package1 và nhân ở cùng gói
(package2) để tính biểu thức S= 1*2 + 2*3 +…+n*(n+1)
• V.v…
Hướng dẫn: trên lớp
Chương 5. Kiểu dữ liệu mảng - Array
Giảng viên: Vũ Duy Linh Email: [email protected]
104
© Vũ Duy Linh Giới thiệu
Mảng (Array): Là một kiểu dữ liệu có cấu trúc, gồm một dãy liên tục
các phần tử cùng kiểu và được đại diện chung một tên biến.
Vì Java xem mảng là dữ liệu tham chiếu/ đối tượng, nên nó phải
được khai báo và khởi tạo trước khi sử dụng
Giá trị (value) mỗi phần tử được lưu trữ ở một chỉ số index (vị trí)
cụ thể, chỉ số đầu tiên bắt đầu từ 0.
105
© Vũ Duy Linh Mảng 1 chiều
Mảng 1 chiều myList đã được khai báo, khởi tạo và gán giá
trị vào 10 phần tử.
106
© Vũ Duy Linh
Khai báo: Cú pháp 1: kiểu_dữ_liệu[] tênBiến; // phổ biến
Vd: double[] myList;
Cú pháp 2: kiểu_dữ_liệu tênBiến[];
Vd: double myList[];
Chú ý: Kích thước của mảng sẽ được xác định khi khởi tạo.
Khởi tạo: Cách 1: Sử dụng toán tử new để tạo giá trị mặc định
Vd: double[] myList = new double[10]; // tạo mảng 10 phần tử
GiangVien[] bmTHUD = new GiangVien[15]; //15 giảng viên
Cách 2: Vừa khai báo vừa tạo giá trị cụ thể (không cần sử dụng new):
Vd: double[] myList = {5.6, 4.5, 3.3, 13.2, 4.0, 34.33, 34.0, 45.45, 99.993, 11123};
Mảng 1 chiều (2)
107
© Vũ Duy Linh Mảng 1 chiều (3)
Ví dụ 1: Viết chương trình (OBP) để in mảng một chiều lên màn hình, tính
tổng và tìm phần tử lớn nhất
108
© Vũ Duy Linh Mảng 1 chiều (4)
Kết quả: In mang - su dung lenh for:
2.0 1.5 3.5 -3.0
In mang - su dung lenh foreach:
2.0 1.5 3.5 -3.0
Tong la 4.0, va gia tri lon nhat la 3.5
109
© Vũ Duy Linh Mảng 1 chiều (5)
Java API có xây dựng sẵn các thư viện xử lý liên quan
đến kiểu mảng:
java.util.Arrays;
java.util.ArrayList;
Đề nghị sinh viên trang bị thêm kiến thức này.
110
© Vũ Duy Linh
Mảng 2 (nhiều) chiều được xem như là mảng của (các) mảng.
Khai báo:
Cú pháp: Kiểu_dữ_liệu[][] tênBiến;
Vd: int[][] mang2Chieu;
Khởi tạo: tương tự như 1 chiều Ví dụ:
double[][] a = new double[2][3];
double b[][] = new double[2][3];
double[][] c = new double[2][];
double[][] u; u = new double[2][3];
int[][] mang2D = { {12, 08, 67}, {78,10, 100}}
Mảng 2 chiều
111
© Vũ Duy Linh Mảng 2 chiều (2)
Minh họa khai báo, khởi tạo, gán trị và truy xuất biến mảng a:
Copyright © by Robert Sedgewick, Kevin Wayne
112
© Vũ Duy Linh
Ví dụ 2: Viết chương trình tạo ra một mảng 2
chiều có số lượng phần tử trên mỗi hàng khác
nhau (xem hình bên), giá trị của chúng được
nhập từ bàn phím.
Mảng 2 chiều (3)
113
© Vũ Duy Linh Mảng 2 chiều (4)
Kết quả:
Nhập các giá trị: 3, 5, 9, 7, -10, 15, 77, 25, 40, 12
In mang 2 chieu:
3 5 9
7 -10
15 77 25 40 12
114
© Vũ Duy Linh Truyền đối số bằng mảng
Ví dụ: Thay đổi nội dung của mảng bằng lời gọi phương thức
115
© Vũ Duy Linh Truyền đối số mảng (2)
116
© Vũ Duy Linh Truyền đối số mảng (3)
Chương 6.
Lớp bao kiểu nguyên thủy (Wrapper class),
lớp String, StringBuffer, StringTokenizer
Giảng viên: Vũ Duy Linh Email: [email protected]
118
© Vũ Duy Linh Lớp bao kiểu nguyên thủy
Ý nghĩa: Khi lập trình, nếu chúng ta cần biến kiểu tham chiếu/đối tượng thuộc vào một lớp chứa kiểu nguyên thủy (Primitive types) thì sử dụng lớp bao kiểu nguyên thủy (Wrapper class). Nói cách khác: Để sử dụng các biến trường và các phương thức được xây dựng sẵn của lớp chứa kiểu nguyên thủy, ta sử dụng wrapper class.
Ví dụ: double diemTrBinh = 8.5; //biến kiểu nguyên thủy double
Double diemTrB = new Double(8.5); //biến kiểu đối tượng của lớp Double
119
© Vũ Duy Linh Các lớp bao kiểu nguyên thủy
Các lớp bao kiểu nguyên thủy (Wrapper classes):
Đề nghị: Sinh viên tự nghiên cứu phần căn bản này từ:
Giáo trình: Lập trình Java căn bản,…
Ebook: Laura Lemay, Charles L. Perkins, Teach your self Java in 21days,…
Internet:
• http://www.syntax-example.com/Code/wrapper-classes-1357.aspx
• http://download.oracle.com/javase/tutorial/java/data/numberclasses.html
• …
120
© Vũ Duy Linh Lớp String
Khai báo
Cú pháp: String tênBiếnChuỗi;
Ví dụ: String hoTen;
Khởi tạo: Có 2 cách
Cú pháp 1 – String literals: tênBiếnChuỗi = "Chuỗi cần tạo"; • Ý nghĩa: Sử dụng 1 địa chỉ vùng nhớ chung cho các biến
chuỗi có giá trị chuỗi giống nhau.
• Ví dụ: hoTen1 = "Nguyễn Huệ";
Cú pháp 2 – String class: tênBiếnChuỗi = new String ("Chuỗi cần tạo"); • Ý nghĩa: Sử dụng địa chỉ vùng nhớ riêng cho mỗi biến chuỗi.
• Ví dụ: hoTen2 = new String("Lý Thường Kiệt");
121
© Vũ Duy Linh Lớp String (2)
Khai báo và khởi tạo:
Cú pháp: • String tênBiếnChuỗi = "Chuỗi cần tạo";
• String tênBiếnChuỗi = new String ("Chuỗi cần tạo");
Ví dụ: • String monHoc = "Lập trình hướng đối tượng Java";
• String chuyenNganh = new String("Tin học ứng dụng");
Chú ý: Đối tượng chuỗi có tính bất biến (Immutable) và không thể thay đổi nội dung khi chúng đã được tạo ra.
122
© Vũ Duy Linh Lớp String (3)
Một số phương thức quan tâm: String() chuỗi rỗng (null string) ;
String(String value) Tạo chuỗi value.
length(str) độ dài chuỗi str
charAt(int index) ký tự ở chỉ số index
trim(str) cắt bỏ khoảng trắng thừa bên trái và phải của str
compareTo(String anotherStr) <0: nhỏ hơn, 0: bằng nhau, >0: lớn hơn
compareToIgnoreCase( String anotherStr); // không phân biệt hoa thường
toLowerCase(str) chuyển thành chữ thường của str
toUpperCase(str) chuyển thành chữ in hoa cho chuỗi str
substring(int beginIndex) Tạo chuỗi con mới bắt đầu ở chỉ số beginIndex
substring(int beginIndex, int endIndex) chuỗi con từ beginIndex đến endIndex
equals(Object anObject) So sánh giá trị của đối tượng: true nếu bằng và ngược lại.
toán tử firstObjectString == secondObjectString So sánh địa chỉ đối tượng (địa chỉ reference chứa chuỗi): true nếu hai đối tượng bằng nhau và ngược lại.
Read more… http://docs.oracle.com/javase/7/docs/api/java/lang/String.html
123
© Vũ Duy Linh Lớp String (4)
Ví dụ : Tạo, so sánh giá trị và địa chỉ của chuỗi
124
© Vũ Duy Linh Lớp String (5)
/**
* @author Vu Duy Linh
* Pass parameter with String type
*/
public class PassStr {
static void kiemTra_Str(String tsht) {
tsht = “Chuoi da cap nhat!";
}
public static void main(String[] args) {
String tst = new String("Chuoi ban dau!");
System.out.println("Gia tri cua tham so thuc, tst: ");
System.out.println("\t>> TRUOC khi ra loi goi kiemTra_Str: "+tst);
kiemTra_Str(tst);
System.out.println("\t>>SAU khi kiemTra_Str hoan thanh: " + tst);
}
}
Giá trị của
tst có
thay đổi?
Truyền tham số bằng chuỗi String
? o
125
© Vũ Duy Linh Lớp String (6)
Vậy: Trước và sau khi gọi phương thức kiemTraStr(…) thì tst KHÔNG có bất kỳ
sự tác động nào từ tsht.
Hình minh họa truyền tham số bằng chuỗi - String
126
© Vũ Duy Linh Lớp String (7)
Ví dụ 2: Kiểm tra một từ có phải là Palindrome không?
127
© Vũ Duy Linh Lớp String (8)
128
© Vũ Duy Linh Lớp StringBuffer
Đối tượng String khi tạo ra thì nội dung cố định
Đối tượng StringBuffer khi tạo ra thì có thể thay đổi được Linh hoạt hơn String.
Sử dụng toán tử new để khởi tạo đối tượng
Khi đối tượng StringBuffer chứa chuỗi ký tự: Độ dài của chuỗi, String.length(), có thể khác với độ dài/khả năng chứa (capacity) của StringBuffer và ta có thể thay đổi độ dài của nó bằng setLength(int newLength)
Có thể cập nhật thêm append(…) , chèn insert(…), xóa delele(…)
Các phương thức dựng thường dùng: new StringBuffer() khởi tạo đối tượng StringBuffer có độ dài mặc
định là16 và không chứa ký tự nào cả.
new StringBuffer(int length) tương tự nhưng có độ dài length
new StringBuffer(String s) chứa chuỗi s và có độ dài = 16 + s.length()
Sử dụng phương thức toString() để đổi StringBuffer sang String.
129
© Vũ Duy Linh Lớp StringBuffer (2)
/**
* @author Vu Duy Linh
* Pass by StringBuffer
*/
public class PassStrBuffer {
static void kiemTra_Str(StringBuffer tsht) {
System.out.println("\t\tTruoc khi cap nhat, tsht= "+ tsht);
tsht.delete(0,tsht.length()).append("Chuoi ban dau da thay doi!");
System.out.println("\t\tSau khi da cap nhat, tsht= "+ tsht);
}
public static void main(String[] args) {
StringBuffer tst = new StringBuffer("Chuoi ban dau!...");
System.out.println("Gia tri cua tham so thuc, tst: ");
System.out.println("\t>>TRUOC khi ra loi goi kiemTra_Str: "+tst);
kiemTra_Str(tst);
System.out.println("\t>>SAU khi kiemTra_Str hoan thanh: "+tst);
}
}
130
© Vũ Duy Linh
Ứng dụng: Tách từng nhóm ký tự (token) dựa vào (các) ký tự phân tách – delimiters
Ví dụ: Tách các token của một chuỗi
Lớp StringTokenizer
131
© Vũ Duy Linh Lớp StringTokenizer (2)
}
132
© Vũ Duy Linh
Ví dụ: Kiểm tra một chuỗi (nhiều từ) có phải là Palindrome không?
Lớp StringTokenizer (3)
133
© Vũ Duy Linh Lớp StringTokenizer (4)
135
© Vũ Duy Linh Sự đóng gói
Đây là một trong những đặc điểm quan trọng của OOP.
Phương pháp để thực hiện việc đóng gói là sử dụng:
Phương thức setters, getters: để thiết lập một cơ chế truy xuất
đến các thuộc tính riêng của lớp
Các phương thức nội tại chi tiết bên trong
Lợi ích: Việc các đặt, sửa chữa nội dung bên trong lớp không ảnh
hưởng đến các lớp khác liên quan
Ví dụ:
1. Khi uống thuốc Aspirin, người dùng có cần biết
công thức hóa, cách trị bệnh của nó không?
2. Duyệt web, người dùng có cần biết mã lệnh HTML, CSS, framework,
thuật toán,… của chúng là gì không?
3. Xem các ví dụ trong phần thừa kế và đa hình (phía dưới).
136
© Vũ Duy Linh Thừa kế
Thừa kế là một cơ chế cho phép lập trình viên mở rộng một lớp cha cho một lớp con. Trong Java, thừa kế được sử dụng bởi 02 phương cách:
Thừa kế lớp (Class inheritance): Tạo một con lớp mới như là
một sự mở rộng (extends) của lớp khác (giúp cho việc tái sử dụng mã lệnh - code) - Java hỗ trợ thừa kế lớp đơn (single class inheritance )
Thừa kế giao diện (Interface inheritance): Tạo một lớp mới để cài đặt (implements) các phương thức đã được định nghĩa trong giao diện. Java hỗ trợ thừa kế bội giao diện - multiple interface inheritance (sẽ được trình bày ở chương Interface).
137
© Vũ Duy Linh Thừa kế lớp (2)
Phương pháp thiết kế:
Tạo mới/sử dụng một lớp cha (tổng quát) không phải là lớp final để định nghĩa những đặc điểm chung của các lớp con (nếu có) Xác định các thành viên (inherited members) của lớp cha có thể được thừa kế cho (các) lớp con.
Tạo (các) lớp con để mở rộng các thuộc tính và phương thức của lớp cha bằng cách thêm vào: Các thuộc tính, phương thức đặc trưng của lớp con
phương thức trùng tên được gọi là overriding methods, các biến trùng tên được gọi là biến phủ lấp (shadowing variables)
Các private members ở lớp cha không thừa kế cho lớp con, tuy nhiên ta có thể sử dụng phương thức setters/getters để truy xuất các biến riêng ở lớp cha.
Quyền truy xuất ở mức thành viên của các lớp, các lớp con thừa kế ở chung gói, khác gói được thể hiện ở bảng “phạm vi truy cập ở mức thành viên” (slide phía dưới)
Truy xuất các phương thức ở lớp cha thông qua từ khóa super, hoặc phương thức super()
138
© Vũ Duy Linh Thừa kế lớp (3)
Cú pháp định nghĩa lớp con thừa kế:
[modifier] class Subclass extends Superclass {
//Class body;
}
Từ khóa extends: là lớp con được mở rộng (dẫn xuất) từ lớp cha nó.
class HinhTron { private int x, y; private double bk; public HinhTron{…} public setBK(doble bk){…} protected double dienTich(){…} } class HinhTru extends HinhTron { private double chieuCao; public HinhTru(double chieuCao){ //… } // v.v… }
139
© Vũ Duy Linh Thừa kế lớp (4)
Bảng phạm vi truy cập ở mức thành viên
Quyền truy xuất
Phạm vi
public protected default private
Ở cùng lớp Yes Yes Yes Yes
Ở khác lớp và cùng gói Yes Yes Yes No
Ở lớp con và cùng gói Yes Yes Yes No
Ở lớp con và khác gói Yes Yes No No
Ở khác lớp và khác gói Yes No No No
Yêu cầu: Sinh viên viết chương trình hoàn
chỉnh để tính thể tích hình trụ theo:
a. Sơ đồ lớp đã thiết kế sẵn
b. Nếu đổi từ protected của dienTich()
thành private thì tính được không?
c. Sau khi xong câu a, chương trình có thể
coding lại để thay đổi tọa độ và/hoặc kích
thước của hình trụ không?
d. v.v…
140
© Vũ Duy Linh Thừa kế lớp (5)
Ví dụ: Giải OOP-PTB2, các lớp chung gói.
141
© Vũ Duy Linh Thừa kế lớp (6)
142
© Vũ Duy Linh Thừa kế lớp (7)
143
© Vũ Duy Linh Mối liên kết - Relationships
Đối tượng kiểu A có một (Has-A) biến thể hiện thuộc kiểu B
Kết tập chặt (Composition): Vòng đời (lifecycle) của đối tượng kiểu B
phụ thuộc nội tại vào vòng đời của A A được tạo thì B được tạo (sử
dụng final), A hủy thì B bị hủy theo. VD: “Mỗi người có một ngày sinh”,
“Mỗi xe có một động cơ”,…
Kết tập lỏng (Aggregation): Vòng đời của đối tượng kiểu B không phụ
thuộc vào vòng đời của A A hủy thì B có thể không bị hủy theo. VD:
“Mỗi TV có một Remote”, “Mỗi laptop có 1 ổ đĩa CD”
[public] class TV{
private Remote itsRmt;
}
[public] class Nguoi{
private final Ngay ngSinh;
public Nguoi(){
ngSinh=new Ngay();
}
}
144
© Vũ Duy Linh Mối liên kết (2)
Đối tượng kiểu A có nhiều (* Has-Many) biến thể hiện kiểu B
Liên kết (Association): Vòng đời của đối tượng kiểu B không phụ
thuộc vào vòng đời của A. VD: “Mỗi niên giám điện thoại có nhiều số
điện thoại”, “Mỗi GV có đăng hoặc không nhiều bài báo khoa học”.
Hỏi: “Mỗi người có tứ chi” hoặc “Mỗi căn nhà có từ một đến 10
phòng”, “Mỗi sinh viên học nhiều GV, mỗi GV dạy nhiều SV”,… thì
mối liên kết sẽ ntn?
[public] class BoMon{
private GiangVien soGV[15];
//private Vector<T> soGV; // nếu *
}
Theo nguyên lý SOLID, nên ưu tiên xét HAS-A trước khi IS-A
145
© Vũ Duy Linh Mối liên kết (3)
Ví dụ: Demo trên lớp
146
© Vũ Duy Linh Mối liên kết (4)
147
© Vũ Duy Linh Đa hình
Có 3 dạng đa hình (Polymorphism) phân biệt trong
ngôn lập trình Java 7:
Nạp chồng phương thức
Ghi chồng phương thức của thừa kế lớp
• Lớp thường (Class)
• Lớp trừu tượng (Abstract class )
• Lớp tổng quát (Generic class)
Ghi chồng phương thức của thừa kế giao diện
(Interface)
148
© Vũ Duy Linh Đa hình (2)
Dạng 1 – Nạp chồng (Overloading): Có nhiều phương thức cùng tên ở trong cùng một lớp với số lượng và kiểu tham số khác nhau
Giả sử trong lớp ViDu_Overloading có 04 phương thức:
• Phương thức 1: cong()
• Phương thức 2: cong(int a, int b)
• Phương thức 3: cong(int a, double b)
• Phương thức 4: cong(String a, String b)
Trong phương thức main của lớp ViDu_Overloading, các phương thức được gọi dựa vào đối số nhập vào như sau:
• cong() // phương thức 1 được gọi 0
• cong(2, 4) // phương thức 2 được gọi 6
• cong(5, 6.5) // phthức 3 được gọi 11.5
• cong("OOP" ,“in Java") // phthức 4 được gọi "OOP in Java"
Dạng 2- Ghi chồng (Overriding): Phương thức ở lớp con ghi đè lên
phương thức cùng tên ở lớp cha. Nó cho phép một phương thức có nhiều dạng tác động khác nhau trên các loại đối tượng khác nhau.
149
© Vũ Duy Linh Đa hình (3)
Ví dụ 1 - Ghi chồng, nhiều lớp nhiều gói khác nhau.
150
© Vũ Duy Linh Đa hình (4)
151
© Vũ Duy Linh Đa hình (5)
152
© Vũ Duy Linh Đa hình (6)
* Kết quả: Toi la doi tuong hinh tron, co dien tich= 7853.98
Toi la doi tuong hinh cau, co dien tich= 31415.93
153
© Vũ Duy Linh Đa hình (7)
c
a
s
t
i
n
g
Up
Down Ví dụ:
DongVat dv = new BoSat(); // Upcasting: OK
BoSat bs = (BoSat) dv; // Downcasting: OK (tường minh)
DongVatCoVu dvcv = dv; // Downcasting Error: type mismatch
DongVatCoVu dvcv2 = new DongVatCoVu();
Nguoi nguoi = new Nguoi();
nguoi = (Nguoi) dvcv2; /* Downcasting:
Biên dịch : OK; chạy: ErrorRuntime exception ClassCastException */
Ép (chuyển) kiểu Ép kiểu lên (Upcasting): đối tượng
kiểu lớp con được gán cho đối tượng
kiểu lớp cha/tổ tiên đối tượng của
lớp con được tham chiếu bởi biến
thuộc lớp cha của nó (theo thừa kế
phân cấp).
Chuyển kiểu xuống (Downcasting):
Theo thứ tự ngược lại của upcasting
và có thể thực hiện bằng ép kiểu
tường minh.
154
© Vũ Duy Linh Đa hình (8)
Ví dụ 2: Đa hình thông qua nạp chồng và ghi chồng ở cùng gói
155
© Vũ Duy Linh Đa hình (9)
/**
* @author Vu Duy Linh
* Polymorphism by overriding, overloading
*/
class LopCha{
protected int x = 10; //not private
void hienThi(){
System.out.println("Toi la phuong thuc trong LopCha."); }
int cong(int a, int b){ return a + b; }
private double cong(int a, double b){ return a + b; }
public Double cong(double a, Double b){ return a + b; }
String cong(String a, String b){ return a + " " + b; }
}
156
© Vũ Duy Linh Đa hình (10)
class LopConA extends LopCha{
//shadow variable – biến bóng: bị che phủ bởi biến cùng tên ở lớp cha
int x = 50;
void cong(LopConA lConA1, LopCha lCha ) {//overloading methods
}
void cong(LopConA lConA1, LopConA lConA2 ) { }
@Override
void hienThi(){ //over-riding method
System.out.println("Toi la phuong thuc trong LopConA."); }
}
class LopConB extends LopCha{
int x = 150;
void cong(LopConB lConB, LopConA lConA ) {
}
@Override
void hienThi(){ //over-riding method
System.out.println("Toi la phuong thuc trong LopConB."); }
}
157
© Vũ Duy Linh Đa hình (11)
public class DaHinh {
public static void main(String[] args) {
LopCha lCha = new LopCha();
lCha.hienThi();
System.out.printf("lCha1.x = %d\n\n",lCha.x);
LopCha lCha2 = new LopConA(); //upcasting
lCha2.hienThi(); //Không bị override bởi shadow var
System.out.printf("lCha2.x = %d\n\n",lCha2.x);
LopConA lCon = new LopConA();
lCon.hienThi();
System.out.printf("lCon.x = %d\n\n", lCon.x);
/* Error: LopCha khong the convert sang LopCon
LopCon lcon2 = new LopCha(); */
158
© Vũ Duy Linh Đa hình (12)
LopCha[] a= new LopCha[3]; a[0]=new LopCha();
a[1]=new LopConA(); a[2]=new LopConB(); //upcasting
int so_dtLopCha=0, so_dtLopConA = 0;
for (LopCha lopCha : a) {
lopCha.hienThi(); //run-time <=> late binding
if (lopCha instanceof LopCha) so_dtLopCha++;
if (lopCha instanceof LopConA) so_dtLopConA++;
}
System.out.println("So doi tuong \"Is-A\" cua LopCha=" +so_dtLopCha);
System.out.println("So doi tuong \"Is-A\" cua LopConA=" +so_dtLopConA);
}
}
Run
Toi la phuong thuc trong LopCha.
lCha1.x = 10
Toi la phuong thuc trong LopConA.
lCha2.x = 10
Toi la phuong thuc trong LopConA.
lCon.x = 50
Toi la phuong thuc trong LopCha.
Toi la phuong thuc trong LopConA.
Toi la phuong thuc trong LopConB.
So doi tuong "Is-A" cua LopCha= 3
So doi tuong "Is-A" cua LopConA= 1
Chương 8. Lớp trừu tượng và giao diện Abstract class và Interface
Giảng viên: Vũ Duy Linh Email: [email protected]
160
© Vũ Duy Linh Lớp trừu tượng
Trong quá trình thiết kế chương trình, chúng ta thường đi
theo quy trình: Từ tổng quát đến cụ thể.
Tổng quát (General):
• Là trường hợp chung chung, ở mức khái niệm
• Sự chung chung đó được xem như là sự trừu tượng
• Lớp mà có tính tổng quát như thế được gọi là lớp trừu tượng
(Abstract class): không thể cài đặt các hành vi (phương thức) một
cách chi tiết/cụ thể được.
Cụ thể (Specific):
• Là trường hợp riêng biệt, một cách rõ ràng: có thể cài đặt các hành
vi (phương thức) một cách chi tiết.
• Lớp có tính riêng biệt được gọi là lớp cụ thể (concrete class): cài
đặt hoàn chỉnh tất cả các hành vi (phương thức).
• Từ lớp tổng quát cho đến lớp cụ thể có thể có nhiều cấp độ trừu
tượng giảm dần khác nhau (cụ thể dần mức độ trừu tượng).
161
© Vũ Duy Linh Lớp trừu tượng (2)
Lớp cụ thể là: Không có từ khóa abstract
Chỉ chứa các phương thức cụ thể (concrete methods)
Phương thưc cụ thể không có từ khóa abstract và được cài đặt hoàn chỉnh
Cần được sử dụng từ khóa new để tạo đối tượng (instances/objects)
Có thể làm lớp cha, lớp con (superclass, subclass): nhưng tất cả các phương thức ở cha con đều được cài đặt hoàn chỉnh
Ví dụ: Tất cả các ví dụ đã học ở phần trên
Lớp trừu tượng là: Được định nghĩa bởi từ khóa abstract
Tồn tại một hoặc tất cả các phương thức trừu tượng (abstract method)
Phương thức trừu tượng được khai báo với từ khóa abstract và chỉ có phần tên phương thức (prototype): Phần thân chưa cài được đặt
Lớp trừu tượng đóng vai trò làm lớp cha. Lớp con thừa kế từ lớp trừu tượng cha có thể là lớp trừu tượng con hoặc là lớp cụ thể
Là thực thể trừu tượng Không được sử dụng từ khóa new để tạo đối tượng
Lớp trừu tượng thường được dùng để gắn kết các lớp cụ thể - cài đặt đầy đủ các phương thức ở superclass.
Bổ từ của lớp là khác private và không chứa abstract static methods.
162
© Vũ Duy Linh Lớp trừu tượng (3)
[Modifier] abstract class TênLớpTrừuTượng {
[Modifier] data_type tênTrường_1;
[Modifier] data_type tênTrường_m;
// Khai báo các phần tên phương thức trừu tượng
[Modifier] abstract return_type tênPhươngThức_1([Các_Tham_số]);
[Modifier] abstract return_type tênPhươngThức_i([Các_Tham_số]);
// Định nghĩa các phương thức cụ thể
[Modifier] return_type tênPhươngThức_j([Các_Tham_số]){
//…
return (giá trị trả về);
}
[Modifier] return_type tênPhươngThức_n([Các_Tham_số]){
//…
return (giá trị trả về);
}
}
Cú pháp khai báo
163
© Vũ Duy Linh Lớp trừu tượng (4)
Ví dụ 1
164
© Vũ Duy Linh Lớp trừu tượng (5)
Mã lệnh:
165
© Vũ Duy Linh Lớp trừu tượng (6)
166
© Vũ Duy Linh Lớp trừu tượng (7)
167
© Vũ Duy Linh Lớp trừu tượng (8)
168
© Vũ Duy Linh Lớp trừu tượng (9)
Ví dụ: Cho các loại động vật. Hãy viết chương trình hiển thị lên tiếng kêu của
từng loài (vd: gâu gâu, meo meo, cạp cạp,…) bằng 02 cách:
1. Sử dụng ép kiểu (Downcasting)
2. Sử dụng đa hình (Polymorphism) //sử dụng lớp trừu tượng
• Source code DongVat.java
169
© Vũ Duy Linh Lớp trừu tượng (10)
• Source code DongVat.java
170
© Vũ Duy Linh Lớp trừu tượng (11)
171
© Vũ Duy Linh Giao diện
Giao diện (Interface): Là một thực thể trừu tượng ở mức cao hơn cả lớp trừu tượng
Lớp là mẫu (template) cho việc hình thành đối tượng, còn interface là mẫu để hình thành lớp.
Một interface cụ thể hóa một loạt các chức năng mà một lớp được cài đặt từ nó cần làm những gì (what) chứ không cần phải biết làm như thể nào (how)
Sử dụng từ khóa interface, nó chỉ chứa các biến hằng và các phương thức trừu tượng
Khác với lớp, Java hỗ trợ thừa kế bội giao diện thông qua từ khóa extends
Không thể new đối tượng
172
© Vũ Duy Linh Giao diện (2)
[public] interface TênGiaoDiện {
//Khai báo các hằng, ngầm định là: public static final
data_type tênTrường_1 = value_1;
data_type tênTrường_m = value_m;
// Khai báo các tên phương thức trừu tượng, ngầm định: public abstract
return-type tênPhươngThức_1([Các_Tham_số]);
return-type tênPhươngThức_n([Các_Tham_số]);
}
* Ví dụ:
interface GiaoDienDongVat {
String TEN_GIAO_DIEN = "giao dien dong vat";
void tuGioiThieu();
}
GiaoDienDongVat
Cú pháp khai báo
173
© Vũ Duy Linh Giao diện (3)
Sự cài đặt giao diện (Implementing Interfaces): Interface được xem như là một mẫu (template) để hình thành lớp. Do đó cần có một lớp làm nhiệm vụ cài đặt cụ thể, bằng từ khóa implements, các phương thức (ảo) trong interface để các chức năng này trở nên hiệu lực và được gọi là lớp cài đặt giao diện (implementation class).
Cú pháp:
[Modifiers] [abstract] class TênLớp implements TênGiaoDiện [, TênGiaoDiện2,…]{
// cài đặt cụ thể các phương thức ảo
}
Ví dụ:
class Meo implements GiaoDienDongVat{
public void tuGioiThieu(){
System.out.println("Xin chào! Tôi là Doremon thuộc họ nhà mèo.");
}
}
174
© Vũ Duy Linh Giao diện (4)
Ví dụ 1: Interface đơn giản
175
© Vũ Duy Linh Giao diện (5)
Sự thừa kế lớp và cài đặt giao diện: Việc định nghĩa lớp con thừa kế đơn từ lớp cha và được cài đặt từ (nhiều) giao diện có dạng tổng quát sau.
Cú pháp:
[Modifiers] class TênLớpCon extends TênLớpCha implements TênGiaoDiện [,TênGiaoDiện 2,…] {
//cài đặt cụ thể các phương thức ảo
}
Ví dụ:
public class PhepTinh1Ngoi extends PhepTinh implements ICong, ITru, INhan, IChia{
private final Screen s;
public void cong(){
s.setKetQua(String.format("%.2f", s.getA() + s.getB()));
}
//...
}
176
© Vũ Duy Linh Giao diện (6)
* Ví dụ 2: Sự cài đặt từ nhiều giao diện
177
© Vũ Duy Linh Giao diện (7)
Screen.java
package vdlinh.package1;
public class Screen {
private double a, b;
private String ketQua;
public Screen(double a, double b){
this.a = a; this.b = b;}
public double getA() {
return a;}
public double getB() {
return b;}
public String getKetQua() {
return ketQua; }
public void setKetQua(String ketQua){
this.ketQua = ketQua;}
}
178
© Vũ Duy Linh Giao diện (8)
PhepTinh.java
package vdlinh.package2;
import vdlinh.package1.Screen;
interface ICong{ void cong(); } interface ITru{ void tru(); }
interface INhan{ void nhan(); } interface IChia{ void chia(); }
public class PhepTinh implements ICong, ITru, INhan, IChia{
private final Screen s;
public PhepTinh(Screen s) { this.s = s; }
public Screen getS() { return s; }
public void cong(){
s.setKetQua(String.format("%.2f", s.getA() + s.getB())); }
public void tru(){
s.setKetQua(String.format("%.2f", s.getA() - s.getB())); }
public void nhan(){
s.setKetQua(String.format("%.2f", s.getA() * s.getB())); }
public void chia(){
if (s.getB() == 0) {s.setKetQua(“Loi: Chia cho khong!");}
else s.setKetQua(String.format("%.2f", s.getA() / s.getB()));}
}
179
© Vũ Duy Linh Giao diện (9)
OOP_SimpleCalc.java
package vdlinh.package3; import java.util.Scanner;
import vdlinh.package1.Screen; import vdlinh.package2.PhepTinh;
public class OOP_SimpleCalc {
public static void main(String[] args) {
double th1,th2; char c;
Scanner in=new Scanner(System.in);
do {
out.print("Nhap toan hang 1= "); th1 = in.nextDouble();
out.print("Nhap toan hang 2= "); th2 = in.nextDouble();
PhepTinh pt = new PhepTinh(new Screen(th1,th2));
out.print(“Chon phep tinh (+, -,* , /), T de thoat? ");
String s = in.next(); c = s.charAt(0);
switch (c) {
case '+':
pt.cong();
out.println("Tong= "+ pt.getS().getKetQua());
break;
180
© Vũ Duy Linh Giao diện (10)
case '-':
pt.tru();
out.println("Hieu= "+ pt.getS().getKetQua());
break;
case '*':
pt.nhan();
out.println("Tich= "+ pt.getS().getKetQua());
break;
case '/':
pt.chia();
out.println("Thuong= "+ pt.getS().getKetQua());
break;
}
} while (Character.toUpperCase(c) != 'T');
System.out.println("Chuong trinh ket thuc...");
in.close();}
} //end main class
181
© Vũ Duy Linh Giao diện (11)
Thừa kế bội bằng
giao diện
Java cho phép định
nghĩa một giao diện
con được thừa kế từ
nhiều giao diện cha.
Điều này giúp cho
việc trừu tượng hóa
trong những dự án
lớn được dễ dàng
hơn.
Ví dụ: Minh họa dự án
có 4 interface
182
© Vũ Duy Linh Giao diện (12)
/** @author Vu Duy Linh */
interface IOne{
String TITLE ="Interface one";
void doSomeThing(); }
interface ITwo{
String TITLE ="Interface two";
void doSomeThing(); }
interface IThree extends IOne, ITwo {
String TITLE ="Interface three";
void doSomeThing3(); }
interface IFour {
String TITLE ="Interface four";
void doSomeThing4(); }
class ConcreteClassImp implements IThree, IFour{
@Override
public void doSomeThing() {
System.out.println("Cai dat doSomeThing()"); }
Ví dụ
183
© Vũ Duy Linh Giao diện (13)
public void doSomeThing3() {
System.out.println("Cai dat doSomeThing3()"); }
public void doSomeThing4() {
System.out.println("Cai dat doSomeThing4()"); }
}
public class MIITest {
public static void main(String[] args) {
ConcreteClassImp cci = new ConcreteClassImp();
cci.doSomeThing();cci.doSomeThing3();
cci.doSomeThing4();
out.println("Title of IOne= "+IOne.TITLE);
out.println("Title of ITwo= "+ITwo.TITLE);
out.println("Title of IThree= "+IThree.TITLE);
out.println("Title of IFour= "+IFour.TITLE);
//out.println("Title of cii= "+cci.TITLE); // ambiguous
}
}
184
© Vũ Duy Linh Giao diện (14)
Đa hình bằng giao diện
Ví dụ: Trên lớp
185
© Vũ Duy Linh Giao diện (15)
Chương 9. Ngoại lệ và xử lý ngoại lệ Exceptions và Exception handle
Giảng viên: Vũ Duy Linh Email: [email protected]
187
© Vũ Duy Linh Giới thiệu
Một chương trình được viết ra thường gặp các lỗi sau: Lỗi cú pháp (Syntax errors): Do LTV không tuân theo đúng cú pháp
của ngôn ngữ lập trình và được trình biên dịch hỗ trợ sửa lỗi.
VD: int a = (5 +7; boolean kt := true;
Lỗi ngữ nghĩa (Semantic errors): Sử dụng câu lệnh không đúng cách. Nó được phân ra 2 loại: Lỗi ngữ nghĩa tĩnh (static semantic errors) ở thời điểm biên dịch và lỗi ngữ nghĩa động (dynamic semantic errors) ở thời điểm runtime.
. VD: char c = “A”; // type mismatch/incompatibility;
int[] a = new int [3];
a[3]=5; // java.lang.ArrayIndexOutOfBoundsException
Lỗi logic (Logical errors): Chương trình cho ra những kết quả sai hoặc không mong muốn.
VD: int cong(int a, int b) { return a*b; }
Để giúp cho người viết chương trình có thể kiểm soát và quản lý được các lỗi compiler/runtime, Java cung cấp một cơ chế "Ngoại lệ" và "Xử lý ngoại lệ"
188
© Vũ Duy Linh Ngoại lệ
Ngoại lệ (Exception): Là một cơ chế để thông báo và xử lý các lỗi trong chương trình gặp phải. Khi chương trình phát hiện ra lỗi thì một ngoại lệ tương ứng với lỗi sẽ được thẩy ra. Có 2 loại ngoại lệ:
Ngoại lệ được kiểm tra (Checked exception): Bao gồm tất cả các lỗi
cú pháp và một số lỗi ngữ nghĩa tĩnh. Chúng sẽ được phát hiện bởi trình biên dịch Java
Ví dụ:
Biên dịch: lỗi.
Chạy: lỗi. ☻
189
© Vũ Duy Linh Ngoại lệ (2)
Chạy: lỗi.
Biên dịch:
thành công.
Ngoại lệ không được kiểm tra (Unchecked exception): Là lỗi không được phát hiện trong quá trình biên dịch mà chúng chỉ được phát hiện khi chạy chương trình (Runtime). Chúng bao gồm các lỗi ngữ nghĩa động và các lỗi logic.
Ví dụ:
190
© Vũ Duy Linh Ngoại lệ (3)
some bugs: có lỗi runtime
Bắt đầu kết thúc cách
bình thường
No bug: không có lỗi runtime
kết thúc
đột ngột
Bắt đầu kết thúc cách
bình thường
Không lỗi
Gặp lỗi
* Chương trinh không có và có bugs:
ngoại lệ được ném ra
191
© Vũ Duy Linh Ngoại lệ (4)
Các loại ngoại lệ được thẩy/tung/ném lên thông qua lớp Throwable
lớp Object
lớp Throwable
lớp Error lớp Exception
lớp RuntimeException Các lớp con Exception
khác RuntimeException
Thuộc loại:
Unchecked exceptions
Thuộc loại:
Checked exceptions
Các phương thức thường
được sử dụng:
1. getCause()
2. getMessage()
3. getStackTrace()
4. toString()
192
© Vũ Duy Linh Ngoại lệ (5)
* Lớp chuẩn Error: Là các lỗi nghiêm trọng gây nguy hiểm (fatal) cho sự thực thi chương trình và KHÔNG được Java phát hiện trong quá trình biên dịch và thuộc loại unchecked exception.
AssertionError
193
© Vũ Duy Linh Ngoại lệ (6)
Các lớp
chuẩn Exception Standard Java exception classes
o Lớp Exception: Bao gồm lớp RuntimeException cùng với các lớp con của nó (Unchecked exception) và các lớp con khác (Checked exception)
…
194
© Vũ Duy Linh Ngoại lệ (7)
Link: http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Exception.html
o Các lớp con của Exception trong JDK 1.5
195
© Vũ Duy Linh Ngoại lệ (8)
Một số minh họa phát sinh lỗi ngoại lệ RuntimeException: Trong gói java.util:
1. EmptyStackException: Lỗi khi ngăn xếp rỗng (empty stack) Stack stack = new Stack();
stack.pop(); // java.util.EmptyStackException
2. NoSuchElementException: Không có phần tử cần tìm trong kiểu liệt kê (enum) ArrayList al = new ArrayList();
al.add(new String("Hi!"));
Iterator iterator = al.iterator();
iterator.next(); // ok
iterator.next(); // hết còn phần tử: java.util.NoSuchElementException
Trong gói: java.lang:
1. ArithmaticException: khi tính toán số học sai, như chia cho 0 int a = 10/0; // java.lang.ArithmeticException: / by zero.
2. ArrayStoreException: khi lưu đối tượng khác kiểu vào mảng kiểu đối tượng Object[] x = new Integer[5];
x[0] = new String("Java"); // java.lang.ArrayStoreException: java.lang.String
3. ClassCastException: khi ép kiểu cho một đối tượng chưa được khởi tạo Object y = new Integer(10); /* y = new Double(y.toString()); // ok */
y = (Double) y; /*java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double */
196
© Vũ Duy Linh Ngoại lệ (9)
Trong gói: java.lang:
4. IllegalArgumentException: Lỗi truyền đối số sai.
IllegalThreadStateException: phát sinh một ngoại lệ nếu gọi phương thức start() mà Thread này đã được bắt đầu chạy (start) khởi hoạt (được học ở chương sau)
NumberFormatException: Lỗi chuyển đổi một chuỗi số không hợp lệ sang số.
Integer.parseInt("Java2010"); //java.lang.NumberFormatException: For input string: "Java2010"
5. IllegalMonitorStateException: thực hiện các phương thức của đối tượng monitor (đối tượng giám sát tuyến đoạn) không hợp lệ (học ở chương sau)
6. IndexOutOfBoundsException: Chỉ số vượt ra ngoài phạm vi của đối tượng
ArrayIndexOutOfBoundsException: Lỗi sai chỉ số của mảng
int[] a = {5, 10, 15};
int v = a[3]; // java.lang.ArrayIndexOutOfBoundsException: 3
StringIndexOutOfBoundsException: Lỗi sai chỉ số của chuỗi
7. NegativeArraySizeException: lỗi do kích thước mảng âm.
double[] mang = new double[-10]; //java.lang.NegativeArraySizeException
8. NullPointerException: lỗi truy xuất đối tượng chưa được khởi tạo
double[][] array2D = new double[5][];
array2D[0][0]=8.0; //java.lang.NullPointerException
9. SecurityException: Lỗi không được quyền truy cập
197
© Vũ Duy Linh Xử lý ngoại lệ
Xử lý ngoại lệ (Exception Handling):
Khi một ngoại lệ xảy ra, một đối tượng thuộc lớp ngoại lệ cụ thể liên quan đến lỗi đó được tạo ra. Nhờ đó người lập trình có thể bắt được đối tượng này để xử lý lỗi, giúp cho chương trình không bị ngắt ngang một cách đột ngột.
Java cung cấp rất đa dạng các lớp ngoại lệ giúp hiệu quả trong việc bắt lỗi ngoại lệ
Ví dụ: Lớp ArithmaticException để quản lý lỗi ngoại lệ của phép toán chia 0, lớp NullPointerException để xử lý lỗi truy xuất đối tượng chưa được khởi tạo
198
© Vũ Duy Linh Xử lý ngoại lệ (2)
some bugs: có lỗi runtime
phát sinh ngoại lệ
kết thúc cách
bất thường
Bắt đầu kết thúc cách
bình thường
Bad
program
Xử lý ngoại lệ
thẩy lỗi
(throw)
Bắt đầu kết thúc cách
bình thường
Good
program
bắt lỗi
(catch)
* Là một dạng như cấu trúc điều khiển:
Khi gặp phải một lỗi, luồng chương
trình đang chạy sẽ bị dừng, ngoại lệ
sẽ được xử lý sao cho nó được kết
thúc một cách bình thường (theo kịch
bản sẵn có của người lập trình)
throw(s) và catch
199
© Vũ Duy Linh Xử lý ngoại lệ (3)
1. Từ khóa throw: để thẩy/ném ra một ngoại lệ (do JVM hoặc LTV)
* Cú pháp: throw throwableObject;
Với throwableObject: là một đối tương thuộc lớp Throwable hoặc lớp con nó
* Ví dụ: throw new ArrayIndexOutOfBoundsException("Lỗi chỉ số mảng");
2. Từ khóa throws: để thẩy ra một hoặc nhiều ngoại lệ của phương thức
* Cú pháp: [modifiers] returntype methodName(params) throws
class_Exception1,... , class_Exception_n {
// thân phương thức
}
Với class_Exception_i: là lớp Throwable hoặc lớp con của nó
* Ví dụ:
void tinhMang(int[] a) throws NullPointerException,
ArithmeticException{
// có thể mảng chưa được khởi tạo
// có thể lỗi chia cho zero
}
200
© Vũ Duy Linh Xử lý ngoại lệ (4)
Câu lệnh try .. catch.. Finally
try {
// Câu lệnh thực hiện. Nếu không có lỗi thì chạy bình thường, ngược lại sẽ
// thẩy lên một ngoại lệ để bắt (catch ) nó …
} catch (Loại Exception 1 e1) {
// … và khối lệnh để xử lý với ngoại lệ loại e1
} catch (Loại Exception 2 e2) {
// … và xử lý với loại e2
} catch (Loại Exception 3 e3) {
// … và xử lý với loại e3
} catch (Exception e) { // Loại Exception thứ n
// … và xử lý với mọi ngoại lệ e
} finally { // luôn được thi hành
// Khối lệnh thích hợp sau khi đã bắt mọi lỗi ngoại lệ
} * Chú ý: lệnh try có thể
- có một hoặc nhiều catch và/hoặc một finally
- nếu có finally thì có thể không cần catch
201
© Vũ Duy Linh Xử lý ngoại lệ (5)
Ví dụ: JVM sẽ tự động thẩy ra ngoại lệ
202
© Vũ Duy Linh Xử lý ngoại lệ (6)
Ví dụ: LTV quản lý thẩy và bắt ngoại lệ - throw
203
© Vũ Duy Linh Xử lý ngoại lệ (7)
Ví dụ: LTV quản lý thẩy và bắt ngoại lệ bằng throw và throws
204
© Vũ Duy Linh Xử lý ngoại lệ (8)
Ví dụ về throws, throw, try..catch..finally
205
© Vũ Duy Linh Xử lý ngoại lệ (9)
run:
3. Loi duoc thay ra: java.lang.NullPointerException - (Phan tu) mang chua duoc 'new'.
Lenh sau cung duoc thuc hien trong khoi Try..catch..finally.
206
© Vũ Duy Linh Xử lý ngoại lệ (10) Phép chia zero:
double a = 1/0; java.lang.ArithmeticException: / by zero
double a = 1/0.0; Infinity (vô cực)
Lan truyền ngược (exception propogation)
Lan truyền ngược
207
© Vũ Duy Linh Xử lý ngoại lệ (11)
Từ khóa assert (khẳng định)
Cú pháp: assert biểuThứcLogic [: “Chuỗi thông báo lỗi”];
Sẽ kiểm tra biểu thức logic xem có phải là khẳng định đúng (true)
không, nếu sai thì sinh ra lỗi java.lang.AssertionError, ngược lại thì chương trình
tiếp tục. Nếu có thêm phần tùy chọn, LTV tự đưa ra thông báo lỗi bằng “Chuỗi
thông báo lỗi” thay vì thông báo lỗi mặc định của JVM.
Lớp AssertionError:
Khi gặp một khẳng định sai thì JVM sẽ thẩy ra lỗi java.lang.AssertionError
Chú ý: Để chương trình không bị ngắt ngang, LTV cần sử dụng câu lệnh
try..catch..finally để bắt lỗi ngoại lệ phát sinh (nếu có)
Ví dụ: Xem slides sau…
208
© Vũ Duy Linh Xử lý ngoại lệ (12)
209
© Vũ Duy Linh Xử lý ngoại lệ (13)
// 1a. Ket qua chia so nguyen= 5.0
// 1b. Loi ngoai le la: java.lang.ArithmeticException: / by zero
// 2a. Ket qua chia so thuc= 5.0
// 2a. Ket qua chia so thuc= Infinity
// 3a. Ket qua chia so thuc =5.0
// 3b. Bat ngoai le sinh ra: java.lang.AssertionError
// java.lang.AssertionError: 4a. Loi chia 0 va bi ngat ngang
210
© Vũ Duy Linh Kết chương
Ở ví dụ và bài tập ở các chương trước, Sinh
viên hãy viết lại chương trình mà có phần bắt
lỗi ngoại lệ phát sinh (nếu có) chương
trình sẽ an toàn và professional hơn.
Đề nghị:
Chương 10. Kỹ thuật tổng quát Generics
Giảng viên: Vũ Duy Linh Email: [email protected]
212
© Vũ Duy Linh Generics
Tóm ý:
Kiến thức lập trình Java quan trọng
Phần bắt buộc trong học phần TN196
Sẽ được trình bày sau
Chương 11. Tập các cấu trúc dữ liệu Java Collection Framework
Giảng viên: Vũ Duy Linh Email: [email protected]
214
© Vũ Duy Linh Collections
Tóm ý:
Kiến thức lập trình Java quan trọng
Phần tùy chọn trong học phần TN196
Chương 12. Tuyến và đa tuyến đoạn Thread and Multi-threads
Giảng viên: Vũ Duy Linh Email: [email protected]
216
© Vũ Duy Linh Thread and Multi-threads
Tóm ý:
Kiến thức lập trình Java quan trọng
Phần tùy chọn trong học phần TN196
Sẽ được biên soạn sau
Chương 13. Luồng và tập tin Streams and files
Giảng viên: Vũ Duy Linh Email: [email protected]
218
© Vũ Duy Linh Luồng và tập tin
Luồng (Stream):
Nền tảng nhất của lập trình I/O trong Java dựa tên luồng (Stream).
Một luồng đại diện cho luồng / dòng chảy của dữ liệu. Nó là một dãy
tuần tự các byte với chiều dài không xác định
về mặt lý thuyết, được gắn với một đầu ghi là writer và đầu khác để
đọc là reader.
Đọc và ghi nguồn dữ liệu từ chương trinh bằng luồng
Source: Claudius Gros
219
© Vũ Duy Linh Luồng và tập tin (2)
220
© Vũ Duy Linh Luồng và tập tin (3)
221
© Vũ Duy Linh Luồng và tập tin (4)
Link: http://docs.oracle.com/javase/7/docs/api/java/io/package-tree.html
Hierarchy For Package java.io
222
© Vũ Duy Linh Luồng và tập tin (5)
InputStream và OutputStream (abstract class): định nghĩa các chức chính để
đọc/ghi dãy các byte không có cấu trúc (unstructured sequence of bytes).
Tất cả các luồng byte khác trong Java được xây dựng trên nền tảng cơ bản
của hai lớp này.
Reader, Writer (abstract class): định nghĩa các chức chính để đọc/ghi dãy
các dữ liệu ký tự (character data) với cả sự hỗ trợ unicode.
DataInputStream, DataOutputStream: luồng lọc (filter streams) được chuyên
biệt để có thể đọc và ghi các kiểu dữ liệu nhiều byte (multibyte) như short,
long, VARCHAR(100 BYTE) trong DB.
ObjectInputStream, ObjectOutputStream: là các luồng filter chuyên biệt để
ghi một toàn bộ nhóm các đối tượng java tuần tự (serialization) và tái tạo
(xây dựng) lại chúng.
BufferedInputStream, BufferedOutputStream, BufferedReader,
BufferedWriter: Là các luồng filter chuyên biệt để đọc ghi các dữ liệu I/O ở
thế giới thực như các bộ nhớ ngoài – giúp tăng hiệu quả đọc ghi dữ liệu.
PrintStream, PrintWriter: Luồng để in văn bản
FileInputStream, FileOutputStream, FileReader, FileWriter: đọc và ghi tập tin
223
© Vũ Duy Linh Luồng và tập tin (6)
Basic I/O:
InputStream stdin = System.in;
OutputStream stdout = System.out;
OutputStream stderr = System.err;
Đoạn lệnh định nghĩa mảng buff kiểu byte và phương thức read() để
điền dữ liệu vào mảng với khả năng chứa nhiều nhất có thể và trả về
số bytes đọc được:
và tạo ra một mảng data với đúng kích thước của nó:
224
© Vũ Duy Linh Luồng và tập tin (7)
Character Streams
225
© Vũ Duy Linh Luồng và tập tin (8)
Stream Wrappers: I/O streams thường được xếp lớp/kết nối (Layered/
Chained streams) lại với nhau để thực hiện cho coongnhững mục đích
khác nhau mà các stream khác nhau (có nhiều đặc tính khác nhau) mang
lại, ví dụ như: tạo vùng đệm (buffering), lọc (filtering) hoặc chuyển đổi các
định dạng dữ liệu (data-format conversion) và được gọi chung là các luồng
lọc (filter streams).
VD:
Source: Claudius Gros
BufferedInputStream in in = new BufferedInputStream(
new FileInputStream(fileName));
226
© Vũ Duy Linh Luồng và tập tin (9)
Data streams:
VD: DataInputStream dis = new DataInputStream( System.in );
double d = dis.readDouble();
Buffered streams:
BufferedInputStream bis = new
BufferedInputStream(myInputStream, 32768);
bis.read();
PrintWriter and PrintStream:
227
© Vũ Duy Linh Luồng và tập tin (10)
Pipes: Những ứng dụng cần hai phía của luồng ví dụ như sự trao đổi giữa
các tuyến đoạn.
Java cung cấp gói: import java.nio.channels.Pipe;
Piped streams:
Hoặc:
Lựa chọn một luồng làm phía thứ nhất, sau đó dựng luồng phía còn
lại bằng cách sử dụng luồng thứ nhất làm đối số cho nó.
228
© Vũ Duy Linh Luồng và tập tin (11)
Ví dụ: PrintStream
229
© Vũ Duy Linh Luồng và tập tin (12)
Ví dụ: PrintWriter
230
© Vũ Duy Linh Luồng và tập tin (13)
Ví dụ về BufferInputStream
Kết quả: ABCDE A: 65| B: 66| C: 67| D: 68| E: 69|
231
© Vũ Duy Linh Luồng và tập tin (14)
Tập tin (File I/O):
Lớp java.IO.File,
java.nio.file.Files: Tạo file và
kiểm tra sự tồn tại, thư mục
đường dẫn thư mục, quyền
tập tin,…
FileStream: FileInputStream
và FileOutputStream
RandomAccessFile
232
© Vũ Duy Linh Luồng và tập tin (15)
Ví dụ: chép file bằng BufferedInputStream
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File; import java.io.IOException;
//Source: http://www.ntu.edu.sg/
public class FileCopyBufferedStreamJDK7 {
public static void main(String[] args) {
String inFileStr = "d:/OOPJava/LearningJava.pdf";
String outFileStr = "d:/OOPJava/LearningJava-out.pdf";
long startTime, elapsedTime; // for speed benchmarking
File fileIn = new File(inFileStr);
System.out.println("File size is "+ fileIn.length()+" bytes");
233
© Vũ Duy Linh Luồng và tập tin (16)
try (BufferedInputStream in = new BufferedInputStream(
new FileInputStream(inFileStr)) BufferedOutputStream out= new BufferedOutputStream(
new FileOutputStream(outFileStr))){
startTime = System.nanoTime(); int byteRead;
while ((byteRead = in.read()) != -1) {
out.write(byteRead);}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Elapsed Time is "+ (elapsedTime / 1000000.0) + " msec");
} catch (IOException ex) {
ex.printStackTrace();}
}
} File size is 25743822 bytes
Elapsed Time is 2756.206114 msec
234
© Vũ Duy Linh Luồng và tập tin (17)
Ví dụ chương: Viết chương trình OOP cho việc nhập xuất các đối
tượng sinh viên (cao đẳng, đại học, sau đại học). Mỗi loại sinh viên
có chung các thông tin về: Mã số (String), ngày sinh (Date), số tín
chỉ tích lũy (int).
Lưu ý: Sinh viên tự chuyên biệt hóa cho 3 trường hợp Cao đẳng, Đại
học, Sau đại học
Hãy tạo ra 10 đối tượng thuộc vào 3 loại đối tượng tên và lưu vào tập
tin D:/Danhsach.dat
Đọc từ file Danhsach.dat và phân ra 3 danh sách: Cao đẳng, Đại học,
Sau đại học và cho biết số tin chỉ tích lũy nhiều nhất và nhỏ nhất
Xem mã lệnh OOP_IO.java
Chương 14. Kết nối cơ sở dữ liệu Java Database Connectivity
Giảng viên: Vũ Duy Linh Email: [email protected]
236
© Vũ Duy Linh Database Connectivity
Tóm ý:
Lập trình ứng dụng CSDL
Sẽ được trình bày sau
Phần tùy chọn (option) trong học phần TN196
237
© Vũ Duy Linh Tài liệu tham khảo
1. Anban Pilla, Object Oriented Programming using Java, 2007
2. Buyya, Selvi, Chu (2009), Object Oriented Programming with Java: Essentials and Applications, TATA MC-GRAW HILL PUBLISHING CO.LTD.-NE.
3. Bruce Eckel (1998), Thinking in Java, Prentice Hall PTR.
4. Cay S. Horstmann (2004), Gary Cornell, Core JavaTM 2 Volume I - Fundamentals, Seventh Editition, Prentice Hall PTR.
5. Cay S. Horstmann (2004), Gary Cornell, Core JavaTM 2 Volume II – Advanced Features, Seventh Editition, Prentice Hall PTR.
6. Daniel Liang (2003), Introduction to Java Programming, Fifth Edition.
7. Eric Armstrong, Jennifer Ball, Stephanie Bodoff, Debbie Bode Carson, Ian Evans, Dale Green, Kim Haase, Eric Jendrock, (2006), The J2EETM 1.4 Tutorial: For Sun Java System Application Server Platform Edition 8.2, Sun Microsystems.
8. Joshua Block (2001), Effective Java: Programming Language Guide, Addison Wesley.
9. Paul Deitel, Harvey Deitel, JavaTM How to Program, 9th, 2012
10. Patrick Niemeyer and Daniel Leuck, Learning Java, 4th, 2012, O’REILLY, 2013
11. R. Morelli, R. Walde, Java, Java, Java Object-Oriented Problem Solving, 3rd Edition, 2012.
13. Robert Cecil Martin, UML for Java Programmers, Prentice Hall, 2002
14. Simon Kendal, Object Oriented Programming using Java, 2009
238
© Vũ Duy Linh Tài liệu tham khảo
15. Trần Minh Châu, Nguyễn Việt Hà, Giáo trình: Lập trình hướng đối tượng với Java, NXB ĐHQG 2013 (draft)
16. V.v…
17. Và nhiều links được cập nhật sau