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
Trang 1MỤC LỤC
MỤC LỤC 1
CHƯƠNG 1: CÁC KHÁI NIỆM CƠ BẢN 4
I Lịch sử hình thành và phát triển ngôn ngữ lập trìnhJava 4
A Giới thiệu vềJava 4
B Các đặc trưng của Java 5
C Các loại ứng dụng của Java 7
D Công cụ và môi trường lập trình Java 7
E Cài đặt Java 7
II Nền tảng của Java 10
A Các kiểu dữ liệu trong Java 10
B Khai báo biến và hằng trongJava 11
C Các toán tử và biểu thức 14
CHƯƠNG 2: CẤU TRÚC ĐIỀU KHIỂN 16
I Lệnh if 16
II Lệnh switch …case 16
III Các lệnh lặp 17
A Vòng lặpfor 17
B Vòng lặpwhile 18
C Vòng lặp do while 19
D Phépnhảy 19
IV Vào dữ liệu từ bàn phím và xuất dữ liệu ra mànhình 20
A Lấy giá trị nhập vào từ bànphím 20
CHƯƠNG 3: LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG TRONG JAVA 23
I Khái niệm lập trình hướng đối tượng (Object-Oriented Programming -OOP) 23
A Khái niệm OOP 23
B Cơ sở lý luận củaOOP 23
C Trừu tượnghóa 23
II Tính đóng gói trongJava 25
A Khái niệm tính đónggói 25
B Mối quan hệ giữa cácclass 25
C Một số gợi ý khi thiết kếclass 25
D Sử dụng các Class xây dựng sẵn trong thư viện 26
E Xây dựng Class trong Java 27
III Tính kế thừa trongJava 33
A Sự kế thừa các thuộc tính và phươngthức 33
B Sự kế thừa đối với cácconstructor 36
IV Tính đa hình trongJava 37
A Sự ép kiểu và gán tham chiếu đốitượng 37
B Sự ràng buộc động –DynamicBinding 37
V LớpObject 38
VI Giaodiện 39
A Cấu trúc của giaodiện 39
B Các tính chất của giaodiện 41
Trang 2VII Package 41
A Sử dụng các package trong thư viện Java 41
B Đặt lớp vàopackage 42
CHƯƠNG 4 XỬ LÝ NGOẠI LỆ 43
I Các tình huống sử dụng ngoạilệ 43
II Cơ sở quản lý ngoại lệ trongJava 43
III Cấu trúc cây kế thừa các xử lý ngoạilệ 44
IV Sử dụng ngoại lệ được kiểmsoát 45
V Xây dựng một ngoạilệ 46
CHƯƠNG 5: LẬP TRÌNH GIAO DIỆN ĐỒ HỌA GUI 48
I Giới thiệuAWT 48
II Vật chứa(Container) 49
A JFrame 49
B JPanel 49
C JDialog 50
D JScrollPane 51
III Giới thiệu về các thành phần GUI cơbản 51
A Nútnhấn 51
B Nhãn(Label) 52
C Nút đánh dấu(checkbox) 53
D Nút chọn (radiobutton) 55
E Hộp thoạiCombo 56
F Danh sách(Lists) 57
G Ô văn bản (text field) và vùng văn bản (textareas) 59
H Thanh trượt(Scrollbar) 61
IV Thành phầnMenu 62
V Bộ quản lý cách trình bày (LayoutManager) 65
A Cách trình bày FlowLayout: 66
B Cách trình bàyGridLayout: 66
C Cách trình bàyBorderLayout 66
VI Các hộpthoại 66
A Hộp thoại thôngbáo 66
B Hộp thoại chọnFile 67
C Hộp thoại chọnmàu 68
VII Khái niệm và cơ sở xử lý sựkiện 68
A Truy cập thông tin sự kiện 74
B Xử lý các sự kiện trên window 75
C Các lớp thích nghi 76
D Xử lý các sự kiệnchuột 102
CHƯƠNG 6: LUỒNG VÀ TẬP TIN 103
I Khái niệmthread 103
A Khái niệm: 103
B LớpThread 103
C Các bước để tạo mộtthread 103
D Các trạng thái của thread 104
E Các thuộc tính của thread 105
F Điều khiển các thread 107
Trang 3G Đồng bộ thread 110
II Các luồng vào ra dữ liệu với file 114
A Khái niệm luồng vào ra (I/O stream) 114
B Nhập xuất lọc 117
C Vào/ra có sử dụng bộ đệm 118
D Đối tượng System.in 121
Trang 4CHƯƠNG 1: CÁC KHÁI NIỆM CƠ BẢN
I Lịch sử hình thành và phát triển ngôn ngữ lập trìnhJava
A 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êninternet 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ăngbả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ácchúng ta sẽ xem xét trong phần sau
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êncá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ínhquan 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ườisá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ủaC++ 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 đượcchà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ểnnhanh 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ìnhJava 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.2là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 SoftwareDevelopment 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
Trang 51.3 1840
Hiện tại, Java đã phát triển tới phiên bản 1.6
B Các đặc trưng của Java
Java được biết đến với các đặc trưng sau:
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 TrongJava 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ácInterface
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
Ảnh hưởng tới bộ nhớ nằm ngoài phạm vi được cấpphát
Đọc và ghi file tựdo
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
Trang 6Trìnhbiên dịch
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
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àophầ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ựcthi 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ươngthức
Các toán hạng của mãbytecode
Các tham số truyền cho phươngthức
Các biến cụcbộ
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ủaC++ 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ố bytecodenhư 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ạihoà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
TrìnhthôngdịchJava(Java Interpreter)
Trang 78 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 chotính di động
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 nhanhhơ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àynay, 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ịchtruyề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 trongchương trình, tối ưu chúng để nâng cao tốc độc thựchiện
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
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ácphươ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ệncủa chương trình đang chạy
C Các loại ứng dụng của Java
Ứng dụng console: Không có giao diệnGUI
Ứng dụng đồ hoạ: Có giao diệnGUI
Applet: Nhúng trong các trangWeb
Servlet: Các class thực thi phía webserver
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
D 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ạihttp://www.netbeans.org)
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
Trang 8docs 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:
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
hayjdb -host -password [options] sourcecodename.java
Cài đặt đường dẫn mặc định.
1 Mở ControlPanel
2 ChọnSystem
Trang 10II. Nền tảng của Java
A Các kiểu dữ liệu trong Java
1 Các kiểu dữ liệu số nguyên
Java có 4 kiểu số nguyên:
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,807byte 1 byte Từ –128 đến 127
12 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
Một biến char sẽ có một giá trị là một ký tự Unicode.
14 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.
15 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.
16 Chuyển đổi giữa các kiểu số
Trang 11char long
float
byte
F Khai báo biến và hằng trongJava
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ữatên
Sau ký tự đầu, có thể dùng các ký tự (chữ), ký tự số, dấu dollard, dấu gạchdưới
Không trùng với các từkhoá
17 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 khaibá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ệucủ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 đốitượng
Ví dụ khai báo cho từng kiểu biến toán học:
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:
Trang 12String 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ủagiátrị
III.2 Biến kiểumả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átvù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
Trang 13Ta 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
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ụ: 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ố 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ự:
Trang 14Là 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
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.3 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
{
Block 3
}{ Block 1
}
Trang 15 Biểu thức gán dùng để gán giá trị cho một biến, mộthằng.
Biểu thức logic chỉ cho ra kết quả là các giá trị true hayfalse.
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àmtrònthà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;
Ngày tháng năm 2016
NGƯỜI BIÊN SOẠN
GIÁO VIÊN Trung úy, Kỹ sư Hà Văn Muôn
/= chia kết hợp phép gán x/=y tương đương x=x/y
& phép và trên bit
&& Toán tử logic AND
|| Toán tử logic OR
= = So sánh bằng nhau
Trang 17CHƯƠNG 2: CẤU TRÚC ĐIỀU KHIỂN
I 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ựchiện
public class dkIfThen {
public static void main(String[] args) {int x=1;
int y=x+1;
if (x<y) {System.out.println("x>y");
int y=x-1;
if (x<y) {System.out.println("x>y");
} else { System.out.println("x<y
");
}}}
III 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>{
Trang 18Biểuthức kiểm tra
false
trueThực hiện khốilệnh
Biểu thức biến điều khiển
Biểu thức điều chỉnh theo bước nhảy
Kết thúc vòng for
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ố
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
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
Trang 19public class vdFor {
public static void main(String[] args) {
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:
Trang 20I 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>.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) {
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ạivới lệnh continue
Lệnh break
Trang 21Lệ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
V Vào dữ liệu từ bàn phím và xuất dữ liệu ra mànhình
A Lấy giá trị nhập vào từ bànphí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óijava.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ậpvà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ụ:
Trang 22import 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 hinhSystem.out.println("Hello, " + name + " Next year, you'll be " + (age + 1));}
}
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 ramà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
Trang 23public 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);
Trang 24CHƯƠNG 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)
A 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ácngô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ì takhô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đốitượ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ạnhcủ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 đốitượ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ộcphải sử dụng kỹ thuật OOP để cài đặt thì mới phát huy hiệu quả
K Cơ sở lý luận củaOOP
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áicủ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ậptrì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ữngthự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ẫnlộn thường xảy ra giữa hệ thống và lĩnh vực ứngdụ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 trongngô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ừutượng hóa thế giới thực
L Trừu tượnghó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ậptrì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ậylà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ượnghóa
Trang 25Trừu tượng hóa
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
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ầnquan 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ácthô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 địachỉ 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 địnhcá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óahà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ọcThay đổ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êntrong 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àokhá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 vikhá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 đốitượ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 đốitượng
Trang 26VI.Tính đóng gói trongJava
A Khái niệm tính đónggó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 đượcgắ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 đốitượ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 truycập
Java
Đố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
M Mối quan hệ giữa cácclass
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ươngthứ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ượngcủa class A chứa đối tượng của classB
Thừa kế (inheritance): Class B gọi là thừa kế class A nếu class B có các phươngthứ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êngnó
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
N 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
Trang 27Đặ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ó.
O 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âydự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 theokịch bản của ứngdụ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ủanó
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
javax.sql Cung cấp các hàm API cho việc truy cập dữ liệu phía server
Trang 28javax.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:
P 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
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>]{
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ế.
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
Trang 29<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
IV.1Các thuộc tính thànhphầ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ớpnà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ốntruy cập vào biến, trước hết phải khởi tạo một đối tượng thuộclớ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ượngcủalớ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 đốitượ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 đượcdù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ũngkhô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ênngoà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 trongphạm vi các phương thức củalớp
Ví dụ:
Trang 30public class TestThis
{
private int number = 10; public voidPrintNumber()
{
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
}}
20 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
private: phương thức này chỉ được truy xuất bên trong lớp chứanó
public: có thể truy xuất từ bất kỳ lớp bên ngoàinà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 đượcnó
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ủalớ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ẫnxuấ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áoabstract
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
đặtlại
native: là phương thức được viết bằng ngôn ngữ khácjava
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)
Trang 31return num1;
else
return num2;
}
Về <mệnh đề throws> chúng ta sẽ xem xét kỹ trong phần xử lý ngoại lệ
21 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 thamtrị
Các tham số có kiểu đối tượng được truyền theo kiểu thamchiếu
Các chú ý khi truyền tham số cho phươngthứ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 đốitượ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!");
22 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 Trongtrườ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() {
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
Trang 32Hà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.
23 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ườipublic 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 mainpublic static void main(String[] argvs){
// Truy cập vào biến lớp không cần khởi tạo đối tượngSinhVien.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);
Trang 33class Outer {
int outer_x = 100;
void test() {Inner inner = new Inner(); inner.display_x();
}classInner{// có thể truyxuấttrưcint inner_y =10;
void display_x() {System.out.println(“display : outer_x = “ +outer_x);
Lớ p lồ ng chỉđươ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đoanmã bất kỳ của lớp bên ngoài truy cậptrưctiếp lớp lồng
Môtlớp lồng có quyền truycâpđếncácthànhviêncủalớpbaobênngoài,thâmchí nếu
chúng được khai báo private Tuy nhiên,lớ p bao không thể truyxuấtcác thành phầncủalớplồng
Có hai kiểu lớp lồng : tĩnh và phi tĩnh
Lớp lồng tĩnh (static nested class) đươc bổ sung từ khoá static Nó không thể tham chiếutrư
c tiếpđếnbiếnhayphươngthứcđốitươṇgđươc điṇ hnghia trong lớ p bao, mà chỉ dùngchúngthôngquađốitươṇg.Vìgiớihạnnàynênlớplồngtĩnhítđượcdùng.Hầuhếtcáclớplồnglàlớp
nôị bô.̣
Lớp lồng phi tĩnh (nonstatic nested class ) không bổ sung từ khoá static , còn đươc goị là
lớpnôịbộ(inner class).Nócóthểtruycậptrựctiếpđếncácbiếnvàphươngthứcđốitượng
Trang 34void 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
VII Tính kế thừa trongJava
Để 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
A Sự kế thừa các thuộc tính và phươngthứ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:
// Phương thức khởi tạo
public Employee(String n, double s, int year, int month, int day)
Trang 35// 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)
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ẵntrong 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
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)
{
Trang 36Tấ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ớpEmployee
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ớpEmployee 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ươngthứ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 đó, tacầ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
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()
Đế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;
}
Trang 37Tuy 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úcnà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ớpcha 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 finalkhi khai báo phương thức
Q Sự kế thừa đối với cácconstructor
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 Tuynhiê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)
Đế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)
double LuongCoBan = super.getLuong(); // OK
return LuongCoBan + TienThuong;
}
//Phương thức đặt tiền thưởng
public void setTienThuong(double b)
Trang 38VIII Tính đa hình trongJava
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ảnhlú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
A Sự ép kiểu và gán tham chiếu đốitượ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 chanhư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);
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 đốitượngManager mà không cần chuyểnkiể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ậptrì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()
R Sự ràng buộc động –DynamicBinding
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
Trang 39staff[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ứcgetLuong() của Employee Tuy nhiên đối tượng thứ 0 đã gọi phương thức getLuong() củaManager 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ộnhay 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ượngtrong 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ềuphươ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 publictrong các lớp cha củaC
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ếutrong 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ươngthứ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ảif(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ươngthứ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áolỗ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àngbuộ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ưngsau đó đượ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ứcf(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
IX.LớpObject
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ảikhaibá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 thamchiếu tới bất kỳ đối tượng nào khác
Object obj = new Employee("AAA", 35000);
Employee[] staff = new Employee[10];
Trang 40obj = staff; // OK
obj = new int[10]; // OK
X Giaodiện
A Cấu trúc của giaodiệ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ĩatrong 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 giaodiệ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>
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>