Bài giảng Java
MỤC LỤC
MỤC LỤC 1
Đề tài 0. Giới thiệu về Java 6
I. Lịch sử hình thành và phát triển ngôn ngữ lập trình Java 6
I.1. Giới thiệu về Java 6
I.2 Tóm tắt lịch sử hình thành của Java 6
II. Các đặc trưng của Java 7
II.1. Tính đơn giản 7
II.2. Tính hướng đối tượng 7
II.3. Tính phân tán 7
II.4. Tính mạnh mẽ 7
II.5. Tính an toàn 7
II.6. Tính trung lập 7
II.7. Tính di động 8
II.8. Tính thông dịch 9
II.9. Tính thực thi cao 9
II.10. Tính đa luồng 9
II.11. Tính động 9
III. Các loại ứng dụng của Java 9
IV. Công cụ và môi trường lập trình Java 9
V. Cài đặt Java 9
Đề tài 1. Ngôn ngữ mô hình hóa UML 12
I. Xây dựng hệ thống phần mềm theo hướng đối tượng 12
I.1 Các khái niệm căn bản của công nghệ hướng đối tượng 12
I.2 Quy trình chung phát triển hệ thống phần mềm 13
I.3 Những thách thức của ngành công nghiệp phần mềm hiện nay 13
II. Lịch sử phát triển ngôn ngữ mô hình hóa UML 13
II.1. Tóm tắt lịch sử UML 13
II.2. Khái niệm về UML 14
II.3 Đặc trưng của UML 14
III. Ngôn ngữ UML 15
III.1. Các thành phần của UML 15
III.2. Các hướng nhìn (view) 15
III.3 Ứng dụng UML trong quy trình làm phần mềm 22
IV. Quy trình Rational Unified Process (RUP) phát triển phần mềm dựa trên UML 23
IV.1. Giới thiệu về RUP 23
IV.2. Các nguyên tắc chính của RUP: 23
IV.3. Vòng đời của phần mềm theo quy trình RUP 24
IV.4. Các công cụ của RUP 25
Bài tập 26
Đề tài 2. Nhập môn Java 27
I. Viết và thực hiện một chương trình Java 27
I.1 Tìm hiểu mã nguồn một chương trình đơn giản 27
I.2. Thực hiện chương trình Java. 27
I.3. Một số chú ý khi lập trình Java 28
I.4. Cấu trúc một chương trình Java 28
II. Các kiểu dữ liệu trong Java 29
II.1 Các kiểu dữ liệu số nguyên 29
II.2 Các kiểu số thực 30
II.3 Kiểu ký tự (character) 30
II.4 Kiểu logic (boolean) 30
II.5 Kiểu chuỗi 30
II.6 Chuyển đổi giữa các kiểu số 30
III. Khai báo biến và hằng trong Java 31
III.1 Quy tắc đặt tên biến 31
III.2 Khai báo biến 31
III.3 Biến kiểu mảng 32
III.4 Hằng số (literal) 33
III.5 Phạm vi hoạt động của hằng và biến: 34
IV. Các toán tử và biểu thức 34
IV.1 Các toán tử và thứ tự ưu tiên 34
IV.2 Biểu thức 35
V. Các lệnh điều khiển rẽ nhánh 35
V.1 Lệnh if 35
V.2. Lệnh switch case 36
VI. Các lệnh lặp 37
VI.1. Vòng lặp for 37
VI.2. Vòng lặp while 38
VI.3. Vòng lặp do. while 38
VI.4. Phép nhảy 39
VII. Vào dữ liệu từ bàn phím và xuất dữ liệu ra màn hình 40
VII.1. Lấy giá trị nhập vào từ bàn phím 40
VII.2 Kết xuất dữ liệu ra màn hình 41
Bài tập 42
Đề tài 3. Lập trình hướng đối tượng trong Java 44
I. Khái niệm lập trình hướng đối tượng (Object-Oriented Programming - OOP) 44
I.1. Khái niệm OOP 44
I.2 Cơ sở lý luận của OOP 44
I.3 Trừu tượng hóa 44
II. Tính đóng gói trong Java 46
II.1 Khái niệm tính đóng gói 46
II.2 Mối quan hệ giữa các class 46
II.3 Một số gợi ý khi thiết kế class 46
IV. Sử dụng các Class xây dựng sẵn trong thư viện 47
V. Xây dựng Class trong Java 48
V.1 Cấu trúc của class 48
V.2 Các thuộc tính thành phần: 49
V.3 Các phương thức thành phần 50
V.4 Gọi và truyền tham số cho phương thức 51
V.6 Các hàm và phương thức đặc biệt 51
V.7 Khai báo chồng các phương thức 52
V.8 Lớp lồng nhau – lớp nội 53
VI. Tính kế thừa trong Java 54
VI.1 Sự kế thừa các thuộc tính và phương thức 54
VI.2 Sự kế thừa đối với các constructor 57
VII. Tính đa hình trong Java 58
VII.1 Sự ép kiểu và gán tham chiếu đối tượng 58
VII.2 Sự ràng buộc động –Dynamic Binding 58
VIII. Lớp Object 59
IX. Giao diện 60
IX.1 Cấu trúc của giao diện 60
IX.2 Các tính chất của giao diện 62
X. Package 62
X.1 Sử dụng các package trong thư viện Java 62
X.2 Đặt lớp vào package 63
Bài tập 63
Đề tài 4. Lớp và phương thức trừu tượng 64
I. Khái niệm lớp trừu tượng 64
II. Cài đặt lớp và phương thức trừu tượng trong Java 64
Bài tập 65
Đề tài 5. Lưu trữ và xử lý đối tượng 66
I. Lớp Vector và giao diện Enumeration 66
I.1 Lớp Vector 66
I.2 Giao diện Enumeration 67
II. Mảng trong Java và lớp ArrayList 69
II.1 Mảng trong Java 69
II.2. Các thuật toán cơ bản trên mảng 70
II.3 Class Arrays 71
III Danh sách trong java và giao diện Lists 73
Bài tập 74
Đề tài 6. Các luồng vào ra dữ liệu với file 75
I. Khái niệm luồng vào ra (I/O stream) 75
II. Lớp InputStream: 76
III. Lớp OutputStream 77
IV. Lớp FileInputStream 77
V. Lớp FileOutputStream 77
VI. Lớp File 77
VII. Nhập xuất lọc 78
VII.1 Lớp FilterInputStream: 79
VII.2 Lớp FilterOutputStream 79
VIII. Vào/ra có sử dụng bộ đệm 79
VIII.1 Lớp BufferedInputStream: 79
VIII.2 Lớp BufferedOutputStream 79
IX. Lớp RandomAccessFile 81
X. Đối tượng System.in 82
XI. Truy cập file ở chế độ tuần tự 82
XII. Truy cập file nhị phân 86
Bài tập 86
Đề tài 7. Xử lý ngoại lệ 88
I. Các tình huống sử dụng ngoại lệ 88
II. Cơ sở quản lý ngoại lệ trong Java 88
III. Cấu trúc cây kế thừa các xử lý ngoại lệ 89
IV. Sử dụng ngoại lệ được kiểm soát 90
V. Xây dựng một ngoại lệ 91
VI. Bài tập 92
Đề tài 8. Xử lý các sự kiện trong Java 93
I. Khái niệm và cơ sở xử lý sự kiện 93
II. Truy cập thông tin sự kiện 98
III. Xử lý các sự kiện trên window 99
IV. Các lớp thích nghi 100
V. Xử lý các sự kiện chuột 102
Bài tập 103
Đề tài 9. Applet 104
I. Xây dựng một Applet đơn giản 104
II. Cấu trúc cơ bản và vòng đời của một Applet 104
III. An ninh và khả năng của Applet 106
IV. Ứng dụng Applet với của sổ Popup 106
V. Các thẻ HTML của Applet 107
VI. Các phương thức, lập trình đồ họa và bắt sự kiện của applet 108
Đề tài 10. Lập trình giao diện đồ họa GUI 110
I. Giới thiệu AWT 110
II. Vật chứa (Container) 111
II.1 JFrame 111
II.2 JPanel 111
II.3 JDialog 112
II.4 JScrollPane 113
III. Giới thiệu về các thành phần GUI cơ bản 113
III.1 Nút nhấn 113
III.2 Nhãn (Label) 114
III.3 Nút đánh dấu (checkbox) 115
III.4 Nút chọn (radio button) 117
III.5 Hộp thoại Combo 118
III.6 Danh sách (Lists) 119
III.7 Ô văn bản (text field) và vùng văn bản (text areas) 121
III.8 Thanh trượt (Scrollbar) 123
IV. Thành phần Menu 124
V. Bộ quản lý cách trình bày (Layout Manager) 127
V.1 Cách trình bày FlowLayout: 128
V.2 Cách trình bày GridLayout: 128
V.3 Cách trình bày BorderLayout 128
VI. Các hộp thoại 128
VI.1 Hộp thoại thông báo 128
VI.2 Hộp thoại chọn File 129
VI.3 Hộp thoại chọn màu 130
Bài tập 130
Đề tài 11. Threading 132
I. Khái niệm thread 132
I.1 Khái niệm: 132
I.2. Lớp Thread 132
I.3 Các bước để tạo một thread 132
II. Các trạng thái của thread. 133
III. Các thuộc tính của thread 134
III.1 Độ ưu tiên của thread 134
III.2 Nhóm thread 135
III.3 Quản lý các ngoại lệ của thread 135
IV. Điều khiển các thread 136
IV.1 Interrupt một thread 136
IV.2 Dừng một thread 137
IV.3 Tạm dừng và phục hồi một thread 138
IV.4 Giải phóng thời gian cho CPU 138
IV.5 Đợi một thread kết thúc công việc 138
V. Đồng bộ thread 139
V.1 Tình trạng “đua tranh” 139
V.2 Khóa đối tượng 140
V.3 Đối tượng điều kiện 141
Bài tập 143
Phụ lục A. Các từ khóa của Java 144
Phụ lục B Một số hàm hay sử dụng 145
Tài liệu tham khảo 146
counts[from] < amount) return; System.out.print(Thread.currentThread()); accounts[from] -= amount; System.out.printf(" %10.2f from %d to %d", amount, from, to); accounts[to] += amount; System.out.printf(" Total Balance: %10.2f%n", getTotalBalance()); } finally { bankLock.unlock(); } } . . . private Lock bankLock = new ReentrantLock(); // ReentrantLock là một lớp cài đặt giao diện lock. } V.3 Đối tượng điều kiện Trong trường hợp thread đi vào vùng bảo vệ, nó cần hoàn thành công việc để có thể mở khóa cho các thread khác đi vào. Tuy nhiên, nếu trong đó công việc chính cần thực hiện bị giới hạn bởi một điều kiện nào đó, chẳng hạn ở đây, việc gọi transfer() để chuyển tiền chỉ được thực hiện khi số tiền của account gửi lớn hơn số tiền được gửi: if (bank.getBalance(from) >= amount) bank.transfer(from, to, amount); Khi có điều kiện này, một thread có thể không thỏa mãn và nó không thực hiện việc chuyển tiền, tức là công việc của nó là không hữu ích. Đến đây, ta có thể nghĩ ra một giải pháp là để thread đợi cho đến khi nó có đủ tiền để chuyển: public void transfer(int from, int to, int amount) { bankLock.lock(); try { while (accounts[from] < amount) // Đợi cho đến khi tài khoản của nó có đủ tiền { // đợi . . . } // Chuyển tiền . . . } finally { bankLock.unlock(); } } Việc đợi ở đây sẽ kết thúc khi một thread khác chuyển tiền vào cho nó. Tuy nhiên ta thấy rằng vùng chứa lệnh chuyển tiền lại đang bị khóa bởi chính thread này nên các thread khác không thể chuyển tiền được. Kết quả là thread này không bao giờ thoát khỏi tình trạng đợi, chương trình rơi vào deadlock. Đây là tình huống mà ta phải sử dụng đối tượng điều kiện: class Bank { public Bank() { . . . sufficientFunds = bankLock.newCondition(); } . . . private Condition sufficientFunds; } Nếu phương thức transfer() kiểm tra và thấy rằng nó chưa đủ tiền để chuyển thì nó sẽ gọi: sufficientFunds.await();Lúc này nó sẽ nằm chờ thread khác chuyển tiền. Có một sự khác nhau căn bản giữa một thread đang đợi để khóa (gọi phương thức lock() để đi vào vùng bảo vệ) và thread gọi phương thức await(). Nó sẽ không thể mở khóa khi đang nằm trong vùng khóa cho đến khi một thread khác gọi signalAll(). Một thread thực hiện xong việc chuyển tiền, nó nên gọi: sufficientFunds.signalAll() để mở khóa cho các thread đang nằm đợi thỏa mãn điều kiện đủ tiền. Một khi thread đã thoát khỏi tình trạng đợi do await() gây ra, nó sẽ được chạy tiếp và cố gắng đi vào vùng khóa và bắt đầu từ vị trí mà nó chờ đợi trước đó - vị trí gọi phương thức await() và kiểm tra lại điều kiện. Một phương thức await() nên được gọi trong một vòng lặp đợi: while (!(đủ tiền)) condition.await(); Nếu không có thread nào gửi signalAll() thì thread đang đợi không có cách nào chạy tiếp được. Nếu tất cả các thread khác đều đang bị chặn, thread gọi await() không giả phóng tình trạng này cho một thread nào đó thì bản thân nó cũng bị chặn, chương trình sẽ bị treo. Vấn đề là khi nào thì gọi signalAll()? Nguyên tắc chung là khi một thread hoàn thành việc thay đổi trạng thái đối tượng thì nó nên gọi signalAll(). Ở đây, sau khi cộng tiền vào cho tài khoản nhận và thì signalAll() sẽ được gọi. Việc gọi này sẽ giúp các thread cũng đang trong tình trạng chờ đợi này không bị chặn nữa và tiếp tục công việc với một giá trị tài khoản có thể đã bị thay đổi. public void transfer(int from, int to, int amount) { bankLock.lock(); try { while (accounts[from] < amount) sufficientFunds.await(); // Chuyển tiền . . . sufficientFunds.signalAll(); } finally { bankLock.unlock(); } } Chú ý là việc gọi signalAll() không phải là kích hoạt thread bị chặn ngay lập tức. Nó chỉ giải phóng tình trạng bị chặn của các thread khác cho đến khi nó kết thúc đoạn chương trình được bảo vệ. Một phương thức khác là sign() chỉ trao khóa cho một thread xác định thay vì tất cả. Một thread chỉ có thể gọi các phương thức signalAll(), sign() và await() trong vùng được bảo vệ. Chúng ta có thể kết thúc phần này bằng một câu chuyện minh họa: Có 10 người cùng đến ngân hàng để chuyển tiền cho nhau, mỗi người chuyển cho một người khác trong số 9 người còn lại. Mỗi thời điểm ngân hàng chỉ chuyển tiền cho một người, người được gửi tiền sẽ được vào trong ngân hàng và giữ khóa cổng, 9 người khác phải chờ ngoài cổng. Nếu chẳng may người đang thực hiện chuyển số tiền lớn hơn anh ta có, anh ta sẽ đợi ở trong ngân hàng (gọi await()) và ném khóa ra ngoài cổng cho tất cả 9 người kia. Một trong số 9 người ngoài cổng sẽ được đi vào trong ngân hàng, thực hiện việc chuyển tiền. Sau khi chuyển xong, anh ta thông báo cho tất cả các anh khác đang phải đợi trong ngân hàng là mình vừa chuyển tiền (gọi signalAll()) rồi đi ra ngoài, sau đó những người đang đợi cũng quay ra cổng để đợi đến lượt vào. Bài tập 1. Viết một chương trình tạo một thread thực hiện việc giải một phương trình bậc 2 với các hệ số cho trước. 2. Viết chương trình song song với 10 thread để cộng 10000 số tự nhiên liên tiếp từ 1 đến 10000. Phụ lục A. Các từ khóa của Java Từ khóa Ý nghĩa abstract Một lớp hoặc phương thức trừu tượng assert Được sử dụng để định vị lỗi nội bộ chương trình boolean Kiểu boolean break Thoát khỏi lệnh switch hoặc các vòng lặp byte Số nguyên 1 byte case Một lựa chon của switch catch Một mệnh đề của khối Try để bắt một ngoại lệ char Kiểu ký tự Unicode class Định nghĩa một class const Không được sử dụng continue Tiếp tục tại vị trí cuối vòng lặp hiện thời default Mệnh đề mặc định của switch do Phần trên của vòng lặp do/while double Kiểu số thực floating-number 8 byte else Mệnh đề else của một lệnh if extends Xác định lớp cha của một lớp final Một hằng số, hoặc một lớp hay phương thức không thể bị khai báo chống. finally Một phần của khối try mà luôn được thực hiện float Số thực 4 byte for Một kiểu vòng lặp goto Không sử dụng if Một lệnh điều khiển rẽ nhánh implements Chỉ ra các interfaces mà lớp sẽ cài đặt. import Nhập một package instanceof Kiểm tra xem đối tượng có phải là biểu hiện của một lớp int Số nguyên 4 byte interface Một kiểu trừu tượng với các phương thức được cài đặt tại các class long Sô nguyên 8 byte Native a method implemented by the host system new Cấp phát vùng nhớ cho một đối tượng hoặc mảng mới null Một tham chiếu null package Một gói các lớp private a feature that is accessible only by methods of this class protected a feature that is accessible only by methods of this class, its children, and other classes in the same package public a feature that is accessible by methods of all classes return returns from a method short the 16-bit integer type static a feature that is unique to its class, not to objects of its class strictfp Use strict rules for floating-point computations super the superclass object or constructor switch a selection statement synchronized a method or code block that is atomic to a thread this the implicit argument of a method, or a constructor of this class throw throws an exception tHRows the exceptions that a method can throw transient marks data that should not be persistent try a block of code that traps exceptions void denotes a method that returns no value volatile ensures that a field is coherently accessed by multiple threads while a loop Phụ lục B Một số hàm hay sử dụng Hàm toán học, lớp java.lang.Math; {java.math.*;} abs(number x): lấy |x|, x có thể là các kiểu long, int, float, double. acos(double x) = arccos(x). x từ 0.0 ... PI asin(double x) = arcsin(x). x từ -PI/2 ... PI/2 atan(double x) = arctag(x). ceil(double x): làm cận trên hoặc cận dưới của số x. cos(double x) = cos(x). x là radian. exp(double x) = ex. log(double x) = Ln(x). max(number x, number y) = max{x, y}, trong đó x, y có thể là kiểu int, float, double, long. min(number x, number y) = min{x, y}, trong đó x, y có thể là kiểu int, float, double, long. pow(double x, double y) = xy. random(): cho một số ngẫu nhiên trong [0.0, 1.0]. round(number x): làm tròn số x, nếu x là kiểu double thì thành kiểu long, nếu x là kiểu float thì thành kiểu int. sin(double x) = sin(x). sqrt(double x) = tan(double x) = tg(x). Khi sử dụng ta phải dùng Math.tên_hàm. b) Lớp String, khai báo java.lang.String; String() : Khởi động một đối tượng chuỗi. String(String s) : Khởi động một chuỗi bằng chuỗi s. length() : trả về giá trị int là độ dài một chuỗi. charAt(int i): trả về một ký tự thứ sau i. indexOf(int ch): trả về vị trí trước của ký tự ch đầu tiên tìm thấy. concat(String str): nối thêm chuỗi str vào sau. toLowerCase(): thay đổi chuỗi thành chữ thường. toUpperCase(): chuyển đổi chuỗi thành chữ HOA. Lớp Date khai báo java.util.Date; Date(): cho thứ, tháng, ngày, giờ, năm. getDate(): trả về giá trị của ngày trong tháng. getDay(): trả về giá trị int là thứ trong tuần, 0 = CN, 1 = mon, ..., 6 = Sat. getMonth(): trả về giá trị int là tháng trong năm (0..11). getYear(): trả về giá trị int là năm. Lấy mốc là 1900, năm thực = date.getYear()+1900. getTime(): trả về là một số được tính theo giây đồng hồ. getHours(): trả về giá trị int chỉ giờ trong ngày. getMinutes(): trả về giá trị int chỉ phút trong giờ. getSeconds(): trả về giá trị int chỉ giây đồng hồ trong phút. setDate(int date) đặt lại ngày trong biến. date lấy giá trị từ 1..31 setMonth(int month): thay đổi giá trị tháng trong biến date. month có giá trị 0..11. setYear(int year): thay đổi giá trị năm trong biến date. (year + 1900). setHours(int hour): thay đổi giá trị giờ trong biến date. setMinutes(int i): thay đổi giá trị phút trong biến date. setSeconds(int i): thay đổi giá trị giây trong biến date. Tài liệu tham khảo [1] Deitel & Associates (2001), “Java, How to program”, fourth edition. [2] Cay S. Horstmann, Gary Cornell (2004), “Core Java™ 2”, volume 1,2, Prentice Hall PTR [3] David Reilly, Michael Reilly (2002), “Network Programming and Distributed Computing”, Addison Wesley
File đính kèm:
- Bài giảng Java.doc