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....................................................................................................................8 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 ...........................................................................................................................10 Đề 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...............................................................23 IV.4. Các công cụ của RUP....................................................................................................25 Bài tập.........................................................................................................................................25 Đề tài 2. Nhập môn Java.................................................................................................................26 I. Viết và thực hiện một chương trình Java ...............................................................................26 I.1 Tìm hiểu mã nguồn một chương trình đơn giản................................................................26 I.2. Thực hiện chương trình Java............................................................................................26 I.3. Một số chú ý khi lập trình Java........................................................................................27

1

I.4. Cấu trúc một chương trình Java.......................................................................................27 II. Các kiểu dữ liệu trong Java....................................................................................................28 II.1 Các kiểu dữ liệu số nguyên..............................................................................................28 II.2 Các kiểu số thực...............................................................................................................29 II.3 Kiểu ký tự (character)......................................................................................................29 II.4 Kiểu logic (boolean)........................................................................................................29 II.5 Kiểu chuỗi........................................................................................................................29 II.6 Chuyển đổi giữa các kiểu số............................................................................................29 III. Khai báo biến và hằng trong Java.........................................................................................30 III.1 Quy tắc đặt tên biến........................................................................................................30 III.2 Khai báo biến..................................................................................................................30 III.3 Biến kiểu mảng...............................................................................................................31 III.4 Hằng số (literal)..............................................................................................................32 III.5 Phạm vi hoạt động của hằng và biến:.............................................................................33 IV. Các toán tử và biểu thức.......................................................................................................33 IV.1 Các toán tử và thứ tự ưu tiên..........................................................................................33 IV.2 Biểu thức........................................................................................................................34 V. Các lệnh điều khiển rẽ nhánh.................................................................................................34 V.1 Lệnh if..............................................................................................................................34 V.2. Lệnh switch …case.........................................................................................................35 VI. Các lệnh lặp..........................................................................................................................36 VI.1. Vòng lặp for...................................................................................................................36 VI.2. Vòng lặp while..............................................................................................................37 VI.3. Vòng lặp do... while......................................................................................................38 VI.4. Phép nhảy......................................................................................................................38 VII. Vào dữ liệu từ bàn phím và xuất dữ liệu ra màn hình.........................................................39 VII.1. Lấy giá trị nhập vào từ bàn phím.................................................................................39 VII.2 Kết xuất dữ liệu ra màn hình........................................................................................40 Bài tập.........................................................................................................................................41 Đề tài 3. Lập trình hướng đối tượng trong Java.............................................................................43 I. Khái niệm lập trình hướng đối tượng (Object-Oriented Programming - OOP)......................43 I.1. Khái niệm OOP................................................................................................................43 I.2 Cơ sở lý luận của OOP......................................................................................................43 I.3 Trừu tượng hóa..................................................................................................................43 II. Tính đóng gói trong Java.......................................................................................................45 II.1 Khái niệm tính đóng gói..................................................................................................45 II.2 Mối quan hệ giữa các class..............................................................................................45 II.3 Một số gợi ý khi thiết kế class.........................................................................................45 IV. Sử dụng các Class xây dựng sẵn trong thư viện...................................................................46 V. Xây dựng Class trong Java....................................................................................................47 V.1 Cấu trúc của class............................................................................................................47 V.2 Các thuộc tính thành phần:..............................................................................................48 V.3 Các phương thức thành phần...........................................................................................49 V.4 Gọi và truyền tham số cho phương thức..........................................................................50 V.6 Các hàm và phương thức đặc biệt....................................................................................50 V.7 Khai báo chồng các phương thức....................................................................................51 V.8 Lớp lồng nhau – lớp nội...................................................................................................52 2

VI. Tính kế thừa trong Java........................................................................................................53 VI.1 Sự kế thừa các thuộc tính và phương thức.....................................................................53 VI.2 Sự kế thừa đối với các constructor.................................................................................56 VII. Tính đa hình trong Java.......................................................................................................57 VII.1 Sự ép kiểu và gán tham chiếu đối tượng.......................................................................57 VII.2 Sự ràng buộc động –Dynamic Binding ........................................................................57 VIII. Lớp Object.........................................................................................................................58 IX. Giao diện..............................................................................................................................59 IX.1 Cấu trúc của giao diện....................................................................................................59 IX.2 Các tính chất của giao diện.............................................................................................61 X. Package..................................................................................................................................61 X.1 Sử dụng các package trong thư viện Java........................................................................61 X.2 Đặt lớp vào package........................................................................................................62 Bài tập.........................................................................................................................................62 Đề tài 4. Lớp và phương thức trừu tượng.......................................................................................63 I. Khái niệm lớp trừu tượng........................................................................................................63 II. Cài đặt lớp và phương thức trừu tượng trong Java................................................................63 Bài tập.........................................................................................................................................64 Đề tài 5. Lưu trữ và xử lý đối tượng...............................................................................................65 I. Lớp Vector và giao diện Enumeration....................................................................................65 I.1 Lớp Vector........................................................................................................................65 I.2 Giao diện Enumeration......................................................................................................66 II. Mảng trong Java và lớp ArrayList.........................................................................................68 II.1 Mảng trong Java...............................................................................................................68 II.2. Các thuật toán cơ bản trên mảng.....................................................................................69 II.3 Class Arrays.....................................................................................................................70 III Danh sách trong java và giao diện Lists ...............................................................................72 Bài tập.........................................................................................................................................73 Đề tài 6. Các luồng vào ra dữ liệu với file.....................................................................................74 I. Khái niệm luồng vào ra (I/O stream)......................................................................................74 II. Lớp InputStream:...................................................................................................................75 III. Lớp OutputStream................................................................................................................76 IV. Lớp FileInputStream............................................................................................................76 V. Lớp FileOutputStream...........................................................................................................76 VI. Lớp File................................................................................................................................76 VII. Nhập xuất lọc .....................................................................................................................78 VII.1 Lớp FilterInputStream: .................................................................................................78 VII.2 Lớp FilterOutputStream................................................................................................78 VIII. Vào/ra có sử dụng bộ đệm ................................................................................................78 VIII.1 Lớp BufferedInputStream:...........................................................................................78 VIII.2 Lớp BufferedOutputStream.........................................................................................78 IX. Lớp RandomAccessFile ......................................................................................................80 X. Đối tượng System.in..............................................................................................................81 XI. Truy cập file ở chế độ tuần tự...............................................................................................81 XII. Truy cập file nhị phân.........................................................................................................85 Bài tập ........................................................................................................................................86 Đề tài 7. Xử lý ngoại lệ..................................................................................................................87 3

....................................4 JScrollPane.............................................................. Vật chứa (Container).......................................................130 Bài tập............................................................................................130 Đề tài 11............................................... Các lớp thích nghi...................................................................5 Hộp thoại Combo ..........................................................................6 Danh sách (Lists).........................87 III..........110 II............................ Bộ quản lý cách trình bày (Layout Manager).................................................................................................................................................... Giới thiệu AWT ........................... Ứng dụng Applet với của sổ Popup....................................................................................128 VI..............113 III........................................... Xử lý các sự kiện trên window................................89 V......................................................................................................................... Các tình huống sử dụng ngoại lệ.....................................................................................................3 Cách trình bày BorderLayout...................................................................................................................... Truy cập thông tin sự kiện... Cơ sở quản lý ngoại lệ trong Java....117 III........................................................1 JFrame.................................................3 Nút đánh dấu (checkbox).......128 VI...........................................................................................................115 III.............................................127 V...................... Lập trình giao diện đồ họa GUI............................3 JDialog......................................................................... Thành phần Menu.................................................................................................................113 III........................................................92 I...........91 Đề tài 8..............105 IV......................... Xây dựng một Applet đơn giản........................................... Các phương thức.........................................................................................109 II................................................................................................................................................103 III............... Threading..105 V............................................................128 V...................................................................................................................................................1 Cách trình bày FlowLayout:................................................... Giới thiệu về các thành phần GUI cơ bản..................90 VI........................................................................................................112 II............................................................................................................................................88 IV.......................................................................................................................................................110 II.....................................................................124 V.............................................................................107 Đề tài 10........................................................................4 Nút chọn (radio button)..................................... Bài tập.............98 V............. lập trình đồ họa và bắt sự kiện của applet.....................................................................................................129 VI................................................................3 Hộp thoại chọn màu....128 VI.............. Khái niệm và cơ sở xử lý sự kiện.................................................................................................98 IV... Xây dựng một ngoại lệ............................ An ninh và khả năng của Applet.......2 Cách trình bày GridLayout:...101 Bài tập.. Sử dụng ngoại lệ được kiểm soát.................. Applet................................................................................................................ Xử lý các sự kiện chuột...............................................................................................................................................2 Nhãn (Label)......2 JPanel......I..1 Nút nhấn ..................................123 IV.......................132 4 ........1 Hộp thoại thông báo.....................................................................................................................118 III............2 Hộp thoại chọn File..113 III...............109 I....................................106 VI.........................103 II........................................................................8 Thanh trượt (Scrollbar)..........................................................92 II.....7 Ô văn bản (text field) và vùng văn bản (text areas)................................................................. Cấu trúc cơ bản và vòng đời của một Applet.......................97 III..............................................................................120 III..............................................102 Đề tài 9.................................110 II........ Các hộp thoại..........87 II..........................................................................................103 I.................................................................................................................. Cấu trúc cây kế thừa các xử lý ngoại lệ...........................................113 III......................117 III..................................................................................... Xử lý các sự kiện trong Java......................................................... Các thẻ HTML của Applet.....128 V.......

......146 5 .136 IV.................2 Khóa đối tượng..................................................................................................................................................................... Lớp Thread.................................................................................. Các từ khóa của Java.............................................................................3 Đối tượng điều kiện..............................................................................................................................3 Quản lý các ngoại lệ của thread...............................................................................140 V......139 V.............................................................................132 I..1 Khái niệm....................................................137 IV.....................................2 Nhóm thread..........................136 IV......................................................138 IV...........1 Interrupt một thread...............................................................141 Bài tập..........................................................................134 III...............133 III......1 Độ ưu tiên của thread....................................................................................................... Khái niệm thread........................................................................................................................................... Các thuộc tính của thread..........................................................................2......................................................................................I............................................132 I............................................................2 Dừng một thread.........................................................134 III...................... Đồng bộ thread.............132 II.....................................................................138 V................................................................................139 V............135 III............................................ Các trạng thái của thread......145 Tài liệu tham khảo....................................................................................................................5 Đợi một thread kết thúc công việc............................................................................................4 Giải phóng thời gian cho CPU..........................................................................................................1 Tình trạng “đua tranh”..........................3 Tạm dừng và phục hồi một thread..132 I...............................................................................................143 Phụ lục A............................................3 Các bước để tạo một thread..138 IV............................................................144 Phụ lục B Một số hàm hay sử dụng..............................................135 IV....................... Điều khiển các thread.

Các phiên bản 1. Trên thực tế. 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.0) đánh dấu sự tích hợp đầy đủ nhất các công nghệ Java. Giới thiệu về Java I. Năm 1992. Phiên bản đầu tiên 1. 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. sau đó là phiên bản 1. một nhóm kỹ sư của hãng SUN bao gồm Patrick Naughton.0 của Java ra đời vào năm 1996. Nhóm đã mở một dự án có tên là Green để hiện thực hóa ý tưởng này.4 là sự phát triển mở rộng tiếp theo của phiên bản 1. người lập trình được sở hữu một thư viện lớn.1 mặc dù khá mạnh nhưng cũng còn nhiều hạn chế. do các hãng khác nhau sử dụng các chíp xử lý (CPUs) khác nhau nên một đặc tính quan trọng mà ngôn ngữ này phải có là độc lập với các dòng CPUs khác nhau – gọi là đặc tính di động.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.2 làm cho Java tiến gần tới mục tiêu “viết một lần.Đề tài 0.1. 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. dự án Green cho ra đời sản phẩm đầu tiên có tên là “*7” nhưng đã không được chào đón như mong đợi. Bảng sau cho thấy sự phát triển thư viện Java qua các phiên bản: 6 . 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. Phiên bản 1. 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.2. Sun Fellow và James Gosling có ý tưởng phát minh ra một ngôn ngữ lập trình nhỏ gọn có thể thực thi được trên các thiết bị dạng như bộ chuyển kênh của truyền hình cáp vì các thiết bị kiểu này có bộ nhớ nhỏ. Các nhân viên tiếp thị của Java gọi đây là phiên bản “Java 2 Standard Edition Software Development Kit Version 1. Khi làm việc với Java. 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. chạy khắp nơi” (Write once. 1. Do đó.3. Bên cạnh đó. Về nền tảng ngôn ngữ. Để giải quyết vấn đề di động. sự phát triển của Internet đã tạo cơ hội để Java phát triển nhanh chóng. 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. Lịch sử hình thành và phát triển ngôn ngữ lập trình Java I. ngôn ngữ mới thiên về hướng đối tượng (Object Oriented) của C++ hơn là hướng thủ tục như Pascal.5 (chuyển sang gọi là phiên bản 5.2 Tóm tắt lịch sử hình thành của Java Năm 1991. 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. nhóm đã sử dụng ý tưởng của kỹ sư Niklaus Wirth – người sáng lập ngôn ngữ Pascal – về việc sử dụng cơ chế thông dịch và máy ảo (virtual machine). Run Anywhere). I. Ngoài ra. Từ năm 1994. Nhóm đã phát triển một trình duyệt có tên là HotJava cho phép các chương trình Java nhúng được trong đó (applet). 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. Đâ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.

II. Tính mạnh mẽ Việc loại bỏ con trỏ làm tăng độ tin cậy của chương trình. operator overloading.2. Java hoàn toàn thích hợp cho các ứng dụng Internet. • Ảnh hưởng tới bộ nhớ nằm ngoài phạm vi được cấp phát. FTP bằng các phương thức như RMI hay Socket. Lập trình viên không cần quan tâm đến thao tác cấp phát và giải phóng bộ nhớ.6 và liên tục được cập nhật. Java đã phát triển tới phiên bản 1.3. structures. Java được phát triển từ C++ nên nó là ngôn ngữ lập trình hướng đối tượng. Các đặc trưng của Java Java được biết đến với các đặc trưng sau: II. bộ nhớ được giải phóng tự động. Tính an toàn Ngôn ngữ Java được thiết kế để tránh các sự cố: • Nạp chồng stack lúc runtime. union.1.2 1.sun. Trong Java chỉ có thừa kế đơn mà không có tính đa thừa kế như của C++.5.1 1. Tính hướng đối tượng Như đã trình bày ở trên. 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.0 1.0 211 477 1524 1840 2723 3270 Hiện tại. Tuy nhiên tính đa thừa kế được biểu hiện thông qua việc sử dụng các Interface. Người sử dụng có thể download phiên bản mới nhất của Java tại địa chỉ: http://www.Phiên bản Số các Class và Interface 1. Các công nghệ JSP. II.jsp?cat=Java %20%26%20Technologies&tab=3&subcat=Java. Tính phân tán Java cho phép lập trình truy cập các đối tượng từ xa thông qua các giao thức HTTP.com/download/index. Servlet cho phép xây dựng các website tương tác với các tính năng thực thi tối ưu II.3 1. Với Java.4 5. • Đọc và ghi file tự do 7 . virtual base class. II. con trỏ.4. II.

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ười ta có thể xem nó như một hệ điều hành thu nhỏ. • Các toán hạng của mã bytecode. Tính di động Không giống C++ và C. Thiết kế này giúp cho trình biên dịch luôn có số bytecode như nhau trên mọi hệ máy và sau đó phát sinh mã máy theo khuôn dạng cố định.6.class • Quản lý bộ nhớ • Dọn “rác”. Từ mã nguồn -> Bytecodes: Trình biên dịch Java. 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. mã đã biên dịch. Trong các phiên bản đầu của Java. Việc không nhất quán của phần cứng làm cho máy ảo phải sử dụng ngăn xếp để lưu trữ các thông tin sau: • Các “Frame” chứa các trạng thái của các phương thức. Trình biên dịch chuyển mã nguồn thành tập các lệnh của máy ảo mà không phụ thuộc vào phần cứng cụ thể. • Các biến cục bộ. Ngày nay. Đ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. Nó có tập hợp các lệnh logic để xác định các hoạt động của máy tính. JVM thiết lập các lớp trừu tượng cho phần cứng bên dưới. 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. Trình thông dịch trên mỗi máy sẽ chuyển tập lệnh này thành chương trình thực thi. Máy ảo tạo ra một môi trường bên trong để thực thi các lệnh bằng cách: • Nạp các file . Từ Bytecodes -> machine code: Trình thông dịch Virtual machine. IBM Bytecode Trình biên dịch Trình thông dịch Java (Java Interpreter) Sparc Macintosh Java Virtual Machine – JVM Máy ảo là một phần mềm dựa trên cơ sở máy tính ảo. 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. thu hồi bộ nhớ cấp cho các biến không còn được sử dụng. Mã nguồn -> ByteCodes -> machine code. thư viện GUI của Java đã được viết lại 8 . Chẳng hạn kiểu dữ liệu int của Java luôn là 4 byte (32 bit) trong khi kiểu int của C++ có thể hiểu là 2 byte hoặc 4 byte tùy theo ngữ cảnh.7. II.II. hệ điều hành. • Các tham số truyền cho phương thức.

RMI. • Jcreator (thương mại). Servlet: Các class thực thi phía web server. Ứng dụng EJB. Applet: Nhúng trong các trang Web. Với công nghệ này. II. Tuy nhiên đây lại là giải pháp cho tính di động.10. 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. II. IV.9. Tính đa luồng Với chương trình Java.org/). Một số IDE thông dụng là: • Netbeans (miễn phí tại http://www. II.8. III. • Jbuilder (thương mại). Các phương thức mới có thể được cài đặt thêm vào các lớp đối tượng hay các giao diện trong thư viện của chương trình đang chạy. đặc biệt trong các ứng dụng thời gian thực. Ngày nay. • Eclipse (miễn phí http://www. Các loại ứng dụng của Java • • • • • • Ứng dụng console: Không có giao diện GUI. II.netbeans. 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. 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). JSP: Các file nhúng mã Java và HTML. những mã bytecode giống nhau sẽ chỉ cần thông dịch một lần.hoàn toàn và có tính độc lập cao giúp cho chương trình Java có giao diện giống nhau trên mọi hệ máy. Tính thực thi cao Java sử dụng công nghệ Just-In-Time (JIT) giúp quá trình thông dịch thực hiện nhanh hơn. Quá trình này cũng làm các chương trình Java chạy chậm hơn.org). lập trình viên có thể cùng lúc quản lý nhiều tiến trình khác nhau. công nghệ này liên tục được cải tiến và cho kết quả vượt trội so với các trình thông dịch truyền thống.11. 9 . 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. tối ưu chúng để nâng cao tốc độc thực hiện.eclipse. Đ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. JMS: Xây dựng ứng dụng bởi nhiều thành phần ghép lại. Ứng dụng đồ hoạ: Có giao diện GUI. giao tiếp từ xa. Ví dụ như JIT có thể quản lý các đoạn mã được sử dụng thường xuyên trong chương trình.

Thư mục cài đặt mặc định của Java trên Windows là C:\Program Files\Java\jdk1. các phương thức của một lớp.java Cài đặt đường dẫn mặc định. 1.Debug.. Chọn System 10 . Cú pháp:javap [options] classname • Công cụ sinh tài liệu. Sau đó cài đặt như ứng dụng bình thường... Cài đặt Java Java phiên bản Java mới nhất có thể download tại địa chỉ http://java.0_02 (nếu phiên bản cài là jdk1.V.6. 'jdb‘ Cú pháp:jdb [options] sourcecodename.com/j2se. 'java' Cú pháp:java [options] classname • Trình dịch ngược. 'javac' Cú pháp:javac [options] sourcecodename.sun. '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 /*. */). Trong đó có chứa các thư mục với ý nghĩa sau: bin Chứa các công cụ và trình biên dịch Java demo Chứa các chương trình Java Demo docs Chứa các tài liệu mô tả thư viện của Java includes Chứa các file dùng để biên dịch các đoạn mã nguồn viết bằng ngôn ngữ khác (native).0_02). 'javap' javap dịch ngược bytecode và in ra thông tin về các thuộc tính (các trường). Mở Control Panel 2. Cú pháp:javadoc [options] sourcecodename.java hay jdb -host -password [options] sourcecodename. jre Chứa các file lưu thông tin môi trường lúc thực thi lib Chứa các file thư viện src Chứa mã nguồn java Trong thư mục \bin có chữa các công cụ chính của Java: • Trình biên dịch.java • Chương trình tìm lỗi .6.java • Trình thông dịch.

Chọn Tab Advanced 4.3.6.Chọn Variable Path . 11 .0_02\bin”.Chọn Edit và copy thêm đường dẫn “C:\Program Files\Java\jdk1. Thêm đường dẫn C:\Program Files\Java\jdk1. Chọn Environment Variables 5.0_02\bin vào biến môi trường Path .6. chọn OK để kết thúc.

4. đối tượng (object). các đối tượng và mối quan hệ giữa chúng phản ánh quy trình nghiệp vụ. lớp 4 chân lại bao gồm các lớp như lớp mèo. Ứng viên gửi hồ sơ dự tuyển tới công ty. Sự trao đổi thông tin giữa hai đối tượng này cho thấy mối quan hệ phụ thuộc giữa chúng (dependence). các hệ thống phần mềm theo công nghệ hướng đối tượng phản ánh một cách tự nhiên và trung thực nghiệp vụ thực tế và có khả năng đáp ứng các thay đổi dễ dàng. thông điệp (mesage). lớp trâu. Công ty phỏng vấn ứng viên. Các hệ thống phần mềm hướng đối tượng cũng được cài đặt bởi các ngôn ngữ lập trình hướng đối tượng. được cài đặt dễ dàng bằng các ngôn ngữ hướng đối tượng. …và một danh mục các mặt hàng. Công ty đưa ra thông báo tuyển nhân sự tới các ứng viên có nhu cầu. dễ hiệu chỉnh. Sự chi tiết phụ thuộc vào phạm vi nghiệp vụ. Phát triển một hệ thống phần mềm theo hướng đối tượng dựa trên 5 khái niệm cơ bản: Lớp (class). Ngôn ngữ mô hình hóa UML I.Đề tài 1. Trong ví dụ trên có sự tham gia của hai đối tượng “công ty” và “ứng viên”. thừa kế (inheritance) và đa hình (polymorphism). Xây dựng hệ thống phần mềm theo hướng đối tượng I.1 Các khái niệm căn bản của công nghệ hướng đối tượng Hướng đối tượng là một công nghệ để sản sinh ra các mô hình phản ánh một cách tự nhiên các nghiệp vụ thực tế. Ví dụ như nghiệp vụ tuyển nhân sự cho một công ty có thể được tóm tắt qua một chuỗi các tương tác như sau: 1.… Mỗi đối tượng là một biểu hiện thực tế của một lớp. Lớp là sự trừu tượng hóa các đối tượng thực tế theo phạm vi nghiệp vụ. Công ty duyệt hồ sơ và gửi giấy hẹn phỏng vấn tới ứng viên.…cho thấy mối quan hệ dạng khác: các nhân viên làm công việc quản lý tất nhiên cũng là nhân viên của công ty nhưng có thêm các thuộc tính riêng biệt – một quan hệ kế thừa (inheritance). Lấy ví dụ về hệ thống quản lý sinh viên của trường ĐHBK Hà Nội cần quản lý rất nhiều đối tượng sinh viên khác nhau nhưng có thể chỉ được trừu tượng hóa thành một lớp đối tượng có tên SinhVien chẳng hạn. 3. Sự trừu tượng hóa một lớp đối tượng cho ta kết quả một tập các thuộc tính (attributes) và các hành vi (operations) đặc trưng cho bất kỳ đối tượng nào thuộc lớp đó. 2. Nói cách khác. Sự trừu tượng hóa diễn ra ở nhiều cấp độ. Một ví dụ khác là trong hệ thống quản lý nhân sự chúng ta có các đối tượng như: nhân viên. 12 . Đối tượng thực tế thì có vô số thuộc tính và hành vi nhưng chỉ thuộc tính và hành vi trong phạm vi nghiệp vụ là được xét đến. Xét cho cùng thì mọi quy trình nghiệp vụ trong thực tế đều là sự tương tác của các đối tượng theo một trình tự nhằm đạt được một mục đích cụ thể. Lấy ví dụ: lớp động vật có vú bao gồm lớp động vật 4 chân. quản lý. object = name + attributes + operations Hệ thống hướng đối tượng nếu được mô hình đúng sẽ rất linh hoạt. Khi này ta nói rằng giữa đơn hàng và mặt hàng tồn tại một quan hệ bao gồm (aggregation) Mục tiêu của công nghệ hướng đối tượng chính là thể hiện được các đối tượng và mối quan hệ giữa chúng vào trong các hệ thống phần mềm. ngày giờ. 5. mỗi đơn hàng bao gồm trong nó các thông tin về khách hàng. Công ty ký hợp đồng với ứng viên hoặc từ chối. Vì vậy. Trong một hệ thống bán hàng.

Đa dạng về nội dung. Sức ép về thời gian hoàn thành. 6. các công ty này lại muốn sử dụng các công cụ phần mềm hỗ trợ các quy trình của họ.OOAD).Hướng đối tượng không chỉ là một lý thuyết mà đã được chứng minh bằng những ứng dụng rất thành công trong thực tế ở nhiều lĩnh vực khác nhau. Design: Thiết kế. Vào đầu những năm 1990. lĩnh vực này vẫn cần được chuẩn hóa hơn nữa. Rumbaugh và Jacobson đã làm việc độc lập và đã đề xuất các quy trình thỏa mãn yêu cầu này. Điều này dẫn tới một đòi hỏi phải có một quy trình làm phần mềm tiếp cận theo hướng phân tích và thiết kế hướng đối tượng (Object Oriented Analyze and Design . các công ty khác nhau.v… I. 5. mô hình hướng chức năng hay mô hình hướng đối tượng v. Những thách thức này có thể nói là gắn liền với mọi công ty phần mềm đặc biệt là ở Việt Nam.2 Quy trình chung phát triển hệ thống phần mềm Xây dựng một hệ thống phần mềm hướng đối tượng cũng tuân theo quy trình chung như mọi công nghệ khác: 1. Năm 1994. 2. James Rumbaugh đã hợp tác cùng Grady Booch tại công ty phần mềm Rational Software Corporation để cùng xây dựng một quy trình thống nhất dựa trên kết quả của 13 .OOP) để xây dựng các ứng dụng. Theo nguyên tắc chung này. Sự gia tăng về quy mô từ nhỏ đến lớn của ứng dụng. Điều này cho thấy việc cần thiết phải có một quy trình với tập ký hiệu thống nhất. Mỗi một quy trình có một tập ký hiệu mô hình riêng để truyền đạt và diễn tả các kết quả phân tích và thiết kế. 2. 3. I. Analysis : Phân tích. Với quá nhiều quy trình khác nhau. Requirements : Thu thập yêu cầu.1.3 Những thách thức của ngành công nghiệp phần mềm hiện nay Mặc dù đã ứng dụng các công nghệ tiến tiến và quy trình phát triển chuẩn hóa nhưng ngành công nghiệp phần mềm vẫn phải đối mặt với những thách thức như: 1. Lịch sử phát triển ngôn ngữ mô hình hóa UML II. thậm chí là các bộ phận khác nhau của cùng một công ty đã sử dụng các quy trình khác nhau. Test: Kiểm thử. 4. mỗi công ty lại ứng dụng những công nghệ khác nhau để phát triển ứng dụng như các mô hình water fall. Tóm tắt lịch sử UML Những năm 1980 là thời kỳ bùng nổ số lượng các công ty phần mềm sử dụng ngôn ngữ lập trình hướng đối tượng(Object Oriented Programming . Deployment: Triển khai. 4. Sự phân tán về không gian làm việc. nơi mà vai trò của quá trình khảo sát. Nhiều nhà nghiên cứu phương pháp trong đó có Booch. Tuy nhiên. phân tích còn bị xem nhẹ cũng như các công ty còn đang bỡ ngỡ với sự mở rộng về quy mô và thiếu nhân lực chuyên môn về phân tích thiết kế. Thêm vào đó. 5. Sự thay đổi các yêu cầu của người sử dụng. Implementation: Cài đặt. các công ty phần mềm đã rất khó khăn trong việc cung cấp các công cụ này. 3. II.

UML là một ngôn ngữ đã được OMG chuẩn hóa và được đặc tả rõ ràng. Cũng cùng thời gian đó. Oracle và Rational Software đã nhận thấy lợi ích của UML và đã nhận lời tài trợ cho các dự án về UML của OMG. Thuật ngữ “Unified” ở đây có một ý nghĩa quan trọng. Các tập đoàn lớn như HP. • UML là một ngôn ngữ diễn tả. • Gắn kết chặt chẽ các khái niệm nội tại của hệ thống. Năm 1997. Philips Telecommunications N. • Mô hình tương tác (interaction diagrams).3 Đặc trưng của UML Hiện nay. • Nâng cao tính tái sử dụng các thành phần của một hệ thống phần mềm.2. Các đặc tính của UML bao gồm: • Mô hình class (class diagrams) mô tả cấu trúc tĩnh của hệ thống và mối quan hệ giữa các đối tượng. • Mô hình Use-case và mô hình hoạt động mô tả các yêu cầu và các luồng công việc trong hệ thống.. • Đơn giản nhất có thể trong khi vẫn mô hình được phần lớn các ứng dụng.0 và đang nghiên cứu phiên bản 2. Năm 1996.. sơ đồ của UML đều theo hướng đối tượng. Microsoft. II. American Airlines. 14 . Sun Microsystems. • Không phụ thuộc vào quy trình phát triển. ký hiệu.1. IBM. Hiện nay OMG đã phát hành tới phiên bản UML 2. OMG tiếp tục xem xét lại UML và đến năm 2001 thì phiên bản UML 1. mô hình hoạt động (activity diagrams) mô tả các hành vi động của các đối tượng trong hệ thống cũng như các thông điệp giữa chúng. Hewlett-Packard. Tất cả các mô hình. Canon. Khái niệm về UML UML – Unified Modeling Language là một ngôn ngữ dùng các sơ đồ và mô hình thống nhất để mô hình các hệ thống phần mềm. • Gắn kết giữa các chu trình phát triển.4 ra đời. OMG là một tổ chức phi lợi nhuận chuyên xúc tiến việc sử dụng công nghệ hướng đối tượng trong ngành công nghiệp phần mềm thông qua việc đưa ra các hướng dẫn và đặc tả OOP. Inc. • Mô hình triển khai (deployment diagrams) mô tả việc triển khai phần mềm trên một môi trường xác định. thuật ngữ. một tổ chức có tên Object Management Group (OMG) đã mời nhóm đệ trình một ngôn ngữ mô hình. • Không phụ thuộc vào ngôn ngữ lập trình và môi trường thực hiện. nhóm đã cho xuất bản phiên bản đầu tiên của UML tới cộng đồng phát triển phần mềm và yêu cầu phản hồi. • Không phụ thuộc vào lĩnh vực ứng dụng. mô hình trạng thái (state diagrams). • Các mô hình cấu trúc hỗn hợp (composite structure diagrams) mô tả sự hợp tác cũng như các đặc điểm về cài đặt. nó nói lên các nguyên tắc của UML: • Thống nhất phương thức.từng người. và Unisys Corporation. Các thành viên của OMG ban đầu là 3Com Corporation. Mục đích của UML là: • Trở thành ngôn ngữ mô hình mà tất cả mọi người làm mô hình có thể sử dụng. Sau đó Ivar Jacobson cũng sớm gia nhập nhóm này. II. UML không phải là một quy trình.V. Data General. • Tập trung hướng tới giải quyết các vấn đề tồn tại trong phát triển phần mềm.

Các hướng nhìn (view) Use-case view: Đây là hướng nhìn về mặt chức năng của hệ thống được thực hiện bởi các tác nhân bên ngoài.1. UML có đầy đủ các mô hình và sơ đồ để thể hiện hầu hết các khía cạnh của hệ thống phần mềm. object. message (thông điệp) và mối quan hệ giữa chúng bao gồm quan hệ dependence. Một phần tử mô hình có thể được sử dụng trong nhiều sơ đồ nhưng chúng luôn có cùng ý nghĩa và ký hiệu giống nhau. UML 2. thuật ngữ.2. Các thành phần của UML Xét trên khía cạnh ngôn ngữ diễn tả. 15 . Ngôn ngữ UML III. III. Các thành phần của ngôn ngữ UML bao gồm: • Các Views (các hướng nhìn): Các view thể hiện các cách nhìn khác nhau tới hệ thống. Các General Mechanisms (các đặc tả chung mở rộng): Mô tả các thông tin chú thích. Một hệ thống không thể chỉ được mô tả bởi một sơ đồ. Nhiều hướng nhìn khác nhau cho ta nhiều sơ đồ mô tả đầy đủ về hệ thống.III. inheritance và aggregation. ngữ nghĩa của các phần tử mô hình. Các hướng nhìn cũng liên kết ngôn ngữ mô hình với các quy trình được chọn cho việc phát triển hệ thống. Các Model Elements (các phần tử mô hình): Các khái niệm được sử dụng trong các sơ đồ và các phần tử của sơ đồ diễn tả các khái niệm phổ biến của công nghệ hướng đối tượng như class. • • • Các Diagrams (các sơ đồ): Các sơ đồ bao gồm các phần tử hình vẽ dùng để mô tả nội dung của các View.0 bao gồm 13 loại sơ đồ khác nhau.

  •  Các use-case phải đầy đủ. người làm mô hình có thể sử dụng mô tả bằng văn bản chi tiết cho mỗi   detail).                                      sử      Bên cạnh sơ đồ.                                                 6.      cần           use-case (text     Mỗi mô tả   đảm bảo các thông tin sau:                    1.       2. Các tác nhân chính. Tiền điều kiện. 5. Tên use-case. Phạm vi của use-case.                                                 4.ud Primary Use Cases                                                                                                                           HÖthèng b¸n hµng qua m¹ng Interrnet                                                Chän hµng                                                             s¶n phÈm                                Kh¸chhµng                         Göi th«ng Xem chi tiÕ t    hµng                        CËp nhËt giá                     tin ph¶n håi                                                                                    hµng                       § ¨ng ký       LËp ® n mua                   ¬                danh môc              Qu¶n trÞhÖ                          thèng hµng hãa Tr¶ lêi Qu¶n lý kh¸ch hµng                                                                                                                                                                                                                                                  kh¸chhµng                    th«ng tin                                      Theo Nh© viªn                   dâi    n   kinh  ® n hµng ¬   doanh m t hµng Æ CËp nhËt                                                                           Các nguyên tắc cho việc xây dựng use-case view là:   •  Các use-case    hình thành trên cơ sở nhìn từ bên ngoài vào trong hệ thống         được                       (out-> in). Dòng chính. chúngđược tổng    theo phương pháp đi từ tối đa đến                     hợp              tối thiểu (ban đầu mở rộng tối đa các use-case có thể sau đó thu hẹp lại theo nhu     cầu khách hàng).                                           • Các use-case cần có tính độc lập tương đối để dễ tổ chức nhóm làm việc và có tính     tái   dụng cao.  Mục tiêu của use-case. 7. Dòng phụ.                                        3.                                                                      16                                                                                    .

nhắc nhở. 2a. Người đòi bồi thường gửi đơn yêu cầu với các dữ liệu bằng chứng về tai nạn. Dòng chính 1. 4b. Sau đây là một ví dụ về use-case text detail: Use-case: Đòi tiền bồi thường. 1a1. Công ty bảo hiểm từ chối yêu cầu. Không có đại lý nào rảnh rỗi. 2a1. Công ty bảo hiểm từ chối yêu cầu. 4. uc Use Case Model Use Case Principal «extend» Use Case Extend 17 . 3. Đại lý đối chiếu tất cả các chi tiết trong đơn theo chính sách bảo hiểm của công ty 5. ghi lại và kết thúc xử lý vụ việc. 3a. Người đòi bồi thường không có chính sách bảo hiểm hợp lệ. ghi lại và kết thúc xử lý vụ việc. uc Use Case Model Use Case Include Use Case Principal «include» • Extend: use-case mới xảy ra khi một điều kiện xảy ra trong use-case chính. Dòng phụ 1a. Bằng chứng tai nạn không đầy đủ. 4b1. (Công ty bảo hiểm sẽ làm gì trong trường hợp này???-cần trao đổi kỹ hơn) 4a. 9. 3a1. 1a2. Vụ tai nạn chỉ vi phạm chính sách bảo hiểm nhỏ.8. Công ty bảo hiểm yêu cầu dữ liệu thiếu. Công ty bảo hiểm điều đình với người đòi bảo hiểm và đồng ý trả bảo hiểm. Vụ tai nạn vi phạm chính sách bảo hiểm cơ bản. 4a1. Người đòi bồi thường gửi lại các dữ liệu thiếu. Hậu điều kiện. nhắc nhở. Công ty bảo hiểm xác nhận người viết đơn có quyền lợi bảo hiểm hợp lệ. Công ty bảo hiểm phân công cho một đại lý xác minh trường hợp này. Actor chính: Người đòi bồi thường. Phạm vi: Công ty Bảo hiểm PCM. Trong trường hợp các use-case quá phức tạp và chưa được mô tả rõ ràng. chúng có thể được tách ra thành các use-case nhỏ hơn theo hai dạng: • Include: use-case mới được tách ra và được bao gồm trong use-case chính một cách vô điều kiện. Ngoại lệ. 2. Công ty bảo hiểm trả tiền bảo hiểm.

Sau đây là một số sơ đồ quan trọng thường được sử dụng.date: Date                -  deliveryInstructions: String             .   .  Author: string                       -item . Các cấu trúc này được gọi là tĩnh vì chúng không phụ thuộc vào thời gian.String)                 property get + getBasket() : ShoppingBasket                     + getBillingAddress() : String + getClosed() : boolean   getDeliveryAddress() : String                  + + getEmailAddress() : String +   getName() :String                 + getOrder() : Order property set                    + setBasket(ShoppingBasket) : void + setBillingAddress(String) : void   setClosed(boolean): void                + + setDeliveryAddress(String) : void +   setEmailAddress(String) :void                 + setName(String) : void +   setOrder(Order): void                            -account                             + createNewBasket() : void + loadAccountHistory() : void +  deleteItem() :void                                + loadOpenOrders(): void     + processOrder() : void property get property get                              Account + getAccount() :          + getLineItem() : LineItem + getDate() : Date property set  setLineItem(LineItem) :               + getLineItem() :LineItem                void        + + getOrderNumber() : String property set                                       + setAccount(Account) : void -history + setDate(Date) : void                           + setLineItem(LineItem) :void            + setOrderNumber(String) : void                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           18                                           .emailAddress: String     name: String                      -bask et                           -                           Transaction                           date: Date orderNumber: String                                        - billingAddress: String closed: boolean                           shoppingBasketNumber: String - ShoppingBasket                        +  addLineItem() :void                -                                   + createNewAccount() : void   loadAccountDetails() :void                 + + markAccountClosed() : void   retrieveAccountDetails(): void                + + submitNewAccountDetails() : void +   validateUser(String.closed: int + getDeliveryInstructions() : String . packed: int        property set    + setDate(Date) : void                +  setDeliveryInstructions(String) : void              + setLineItem(LineItem) : void                +  setOrderNumber(String) : void               + setStatus(OrderStatus) : void Account   . các đặc điểm nội tại cũng như mối quan hệ giữa chúng.Nói chung.delivered: int +  getLineItem(): LineItem                             .new: int + getStatus() : OrderStatus                   . Đây là sự mô hình các khái niệm trong ứng dụng. Các khái niệm Mô hình hóa Classes Attributes Operations Object Ví dụ về mô hình class: cd Java Model                                                                   Order                                                     quantity: int LineItem                           StockItem               . Logical views Đây là hướng nhìn cho biết các chức năng được thiết kế vào trong hệ thống như thế nào (HOW?) thông qua việc mô tả các cấu trúc tĩnh và các hành vi động của hệ thống. use-case view giúp ta trả lời câu hỏi WHAT? về hệ thống. catalogNumber: string  costPrice:                      number listPrice: number  title:                      string                       property get             + getItem() : StockItem                       +  getQuantity(): int          property set         +  setItem(StockItem): void           + setQuantity(int) : void                                                                                                         property get +  getAuthor(): string                + getCatalogNumber() : string +  getCostPrice() : number                  + getListPrice() : number + getTitle() : string                    property set + setAuthor(string) : void +  setCatalogNumber(string) :                 void + setCostPrice(number) : void +  setListPrice(number)  void              :   + setTitle(string) : void                                                                                                                -account                                         deliveryAddress:                      String . Các cấu trúc tĩnh (static structure): Cấu trúc tĩnh được mô hình bằng UML chính là các class diagrams.dispatched: int + getOrderNumber() : String .orderNumber: String  «enumeration»       +  checkForOutstandingOrders() : void                      OrderStatus property get enum             +  getDate() :Date                 -status .

Sơ đồ hành động (activity diagrams): Đây là sơ đồ mô tả luồng nghiệp vụ trong hệ thống. 19 .Các hành vi động: State machine: Sơ đồ sau mô tả sự chuyển đổi trạng thái của một máy tính PC: Sơ đồ sau mô tả sự chuyển đổi trạng thái của một thang máy: Đây là mô hình mô tả việc chuyển đổi trạng thái của đối tượng trong quá trình tham gia các hoạt động nghiệp vụ của hệ thống. Trạng thái của đối tượng bị thay đổi bởi một hành vi nào đó.

Sơ đồ triển khai (Deployment Diagram): Đây là sơ đồ cho thấy các thành phần cả về phần cứng và các các gói phần mềm được triển khai như thế nào. 20 .

Các class trong hệ thống được chia thành ba loại tách biệt: M (Model) – V (View) – C (Control).Sơ đồ tương tác (interaction diagram): Đây là sơ đồ mô tả sự tương tác giữa các đối tượng theo trình tự thời gian (còn gọi là sequence diagram). Các class V chịu trách nhiệm hiển thị giao diện tương tác với người sử dụng. Các sơ đồ sequence có thể được mô tả ở mức hệ thống (Sequence System – chỉ có user tương tác với hệ thống) hoặc mức chi tiết (Sequence Detail – Các đối tượng và thông điệp giữa chúng đã được định hình).    sd Sequence            V                                           Khach mua       DangKy               hang Page           Nhap thong tin dang ky                                                                                                                       Click "Dang Ky"       C                   M                              AccountUtilities      AccountTable                                                                               DangKyKhachHang()                                                                                                                       XacNhanThongTinDangKy()                                                          sd MuaHang                  V             C       M                                                                                                                                                                                         Chon xem san pham theo hang Khach Hang TrangChu TrangDanhMucSanPham SanPhamUtilities SanPhamTable                                                                                     Redirect                                        LayDanhSachSanPham                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 21                                                                                                                                                             HienT hi . các class M lưu trữ dữ liệu được mô hình hóa từ thông tin đối tượng quản lý trong khi các class C là nơi điều khiển việc dữ liệu từ M được đưa tới giao diện V như thế nào hoặc xử lý các yêu cầu từ V sau đó cập nhật vào M.

ta cần linh hoạt sử dụng các mô hình và sơ đồ để thể hiện sát đúng các yêu cầu nghiệp vụ nhằm mục tiêu cuối cùng là chương trình ứng dụng khi được triển khai sẽ gặp lỗi ít nhất. các bước tiếp theo cần làm song song là xây dựng mô hình use-case và vẽ phác thảo giao diện chương trình. Một khi các mô hình và tài liệu đặc tả đã hoàn chỉnh. Sau đây là một số công cụ giúp sử dụng UML trong phát triển hệ thống phần mềm: 22 . Ngoài ra. Như vậy việc lập trình cài đặt chỉ được tiến hành sau khi các mô hình đã hoàn tất. sơ đồ trạng thái và sơ đồ hành động. UML chỉ thuần túy là một ngôn ngữ mô hình dùng cho việc mô tả mọi khía cạnh của hệ thống phục vụ cho việc xây dựng và phát triển cũng như bảo trì sau này. việc coding thực sự chỉ chiếm khoảng 20% tổng số thời gian.3 Ứng dụng UML trong quy trình làm phần mềm Như đã trình bày ở trên. Đây là cơ sở để xây dựng sequence detail và hoàn chỉnh mô hình class với các quan hệ đầy đủ. Sơ đồ trên cho thấy một trình tự sử dụng các mô hình UML để xây dựng một ứng dụng. được khách hàng chấp thuận. Không nhất thiết mọi hệ thống phải sử dụng tất cả các mô hình UML nhưng quan trọng nhất là các sơ đồ đã trình bày ở trên. Sau đó xây dựng mô hình class ở mức phác thảo.III. Do đó. Đến đây ta đã biết user tương tác với cụ thể đối tượng nào của system và các thông điệp giữa các đối tượng từ mô hình class. Tiếp theo xây dựng mô hình sequence system vì thông qua giao diện ta đã biết user tương tác với system như thế nào. Trong thực tế ứng dụng UML. ta cũng cần chú ý tới tính tái sử dụng và khả năng thích ứng với các thay đổi của các mô-đun chương trình. Các công ty phần mềm khác nhau tuy đều ứng dụng UML nhưng có thể sử dụng các quy trình phát triển khác nhau. Xuất phát từ ý tưởng ban đầu thuần túy mang tính nghiệp vụ (business). trong quá trình xây dựng các mô hình cần tuân thủ quy trình và liên tục tiếp xúc với khách hàng để đảm bảo tính chính xác và đầy đủ. Theo quan điểm về phân tích thiết kế bằng UML thì việc lập trình rõ ràng không chỉ bắt đầu khi cài đặt các class và các sequence detail bằng một ngôn ngữ lập trình mà thực tế chúng ta đã lập trình ngay từ khi xây dựng mô hình use-case và viết text detail cho nó.

6. 3. Kết thúc mỗi quy trình cần theo dõi kết quả và kiểm tra chặt chẽ. Động cơ phát triển RUP là tìm ra nguyên nhân của các lỗi phần mềm và tìm cách khắc phục chúng thông qua một quy trình. Giới thiệu về RUP Trong số các quy trình hiện nay.1. Lịch sử: RUP là sự phối hợp giữa cách tiếp cận công nghệ hướng đối tượng của Rational trong những năm 1980s và 1990s với công nghệ xử lý đối tượng của Ival Jarcobson.0 phát hành 2005.IV. IV. Construction và Transition. Các nguyên tắc chính của RUP: 1. có 4 pha: Inception.Nâng cao mức độ trừu tượng (Elevate the level of abstraction).Tập trung theo dõi chất lượng liên tục (Focus continuously on quality).Tuân thủ tiến trình (Adapt the process).2. 23 .Thể hiện kết quả theo quy trình lặp (Demonstrate value iteratively). 5. IV.Cân bằng các ưu tiên của stakeholder (Balance stackeholder priorities). Phiên bản mới nhất của RUP là version 7. Stakeholder là những người đưa ra những ý kiến có ảnh hưởng lớn tới tư tưởng thiết kế hệ thống. Vòng đời của phần mềm theo quy trình RUP Trong một vòng đời của phần mềm. RUP được phát triển bởi công ty Rational Software được sử dụng khá phổ biến. 4. 2. Quy trình Rational Unified Process (RUP) phát triển phần mềm dựa trên UML IV.3.Cộng tác giữa các nhóm (Collaborate across teams). Elaboration.

Các công việc như thiết kế chi tiết. • Phân tích và thiết kế (analysis & design): mô tả kiến trúc hệ thống thông qua các sơ đồ phân tích thiết kế. chuẩn bị nhân lực. pha inception chủ yếu làm các công việc mang tính chất khởi động như mô hình hóa nghiệp vụ (business modeling). • Inception: Đây là giai đoạn chuẩn bị. Trong biểu đồ trên. vật tư kỹ thuật. Một biểu đồ khác chi tiết hơn cho ta thấy các các giai đoạn phát triển được tiến hành khi nào và mức độ sử dụng tài nguyên của chúng trong các pha theo các nguyên tắc chung. Các giai đoạn công việc của RUP bao gồm: • Mô hình hóa nghiệp vụ (business modeling): mô tả cấu trúc và quy trình nghiệp vụ. tiếp xúc với khách hàng để nắm bắt ý tưởng và thu thập yêu cầu. tài nguyên của công ty. thu thập yêu cầu (requirements). 24 . • Lập trình (Implement): thực hiện các việc xây dựng chương trình bằng ngôn ngữ lập trình. Tài nguyên ở đây thể hiện về nhân lực và cơ sở vật chất được huy động.…đều được tiến hành trong pha này. • Elaboration: Sau khi đã thu thập được yêu cầu thì đây là pha thiết kế phác thảo sử dụng các sơ đồ UML để mô hình hóa các yêu cầu. kiểm thử. • Xác định yêu cầu (requirement): mô tả nghiệp vụ bằng phương pháp sử dụng các use-case. • Transition: Pha chuyển giao cho khách hàng.… • Construction: Pha xây dựng hệ thống yêu cầu sử dụng nhiều nhân lực.Biểu đồ trên cho biết trình tự các pha và lượng tài nguyên (resources) sử dụng cho mỗi pha. các quy trình nghiệp vụ của ứng dụng. cài đặt.

Hãy tiết text detail và xây dựng mô hình sequence system cho các use-case : “Mượn sách” và “Trả sách”. xác định các tác nhân của hệ thống cùng những tình huống sử dụng. Quản trị cấu hình và quản trị thay đổi (Configuration & Change Management): kiểm soát các thay đổi và duy trì sự hợp nhất của các thành phần dự án. Hãng Rational đã xây dựng một hệ thống công cụ như vậy. triển khai. Hãy mô tả một quy trình ứng dụng UML trong phát triển hệ thống phần mềm. mà tiêu biểu và thường dùng nhất là: • Phần mềm Rational Requisite Pro: cho phép phân tích các yêu cầu.“Đăng nhập hệ thống” trong một hệ thống có yêu cầu xác thực account. Bài tập 1. Quản trị dự án (project management): quản lý toàn bộ quá trình làm việc của dự án. • Phần mềm Rational Rose: cho phép xây dựng các mô hình phân tích. • Phần mềm Rational Clear Case: quản trị dự án phân tích thiết kế. tiến hành thử nghiệm hệ thống phần mềm. Triển khai (Deployment): đưa hệ thống phần mềm vào sử dụng. . 3. Các công cụ của RUP Để áp dụng được quy trình phát triển hệ thống phần mềm của Rational thì yêu cầu không thể thiếu là hệ thống các phần mềm công cụ hỗ trợ. . IV.4. • Phần mềm Rational XDE: cho phép vừa xây dựng các mô hình vừa kết sinh mà nguồn chương trình song song với nhau. xây dựng kế hoạch thực hiện. Xây dựng mô hình use-case cho hệ thống quản lý việc mượn và trả sách tại thư viện.“Đăng ký học” trong hệ thống tuyển sinh. Đảm bảo môi trường (environment): đảm bảo các hạ tầng cần thiết để có thể phát triển được hệ thống.• • • • • Thử nghiệm (Test): mô tả các tình huống và kịch bản thử nghiệm.“Mua hàng” trong hệ thống bán hàng ở siêu thị. cho phép làm việc theo nhóm. Hãy viết text detail cho các use-case trong các hệ thống khác nhau: . 25 . thiết kế. 2.

Dòng 4: Khai báo hàm main. /* Day la chuong trinh vi du*/ 2. 3. { 6. Để thực hiện chương trình Java trong ví dụ trên. { 4.java để trình biên dịch Java biết đây là file chứa mã nguồn Java. Từ dấu nhắc gõ lệnh: javac C:\JavaSample\Vidu.2. Dòng 5 và 7 cũng là đánh dấu mở và đóng cho một khối lệnh thuộc hàm main. Cùng với dòng 8 tạo thành một cặp {} dùng để đánh dấu việc mở và đóng cho một khối lệnh.Đề tài 2. I.. chọn Run và gõ vào lệnh “cmd”. các dòng chú thích giúp ta nhanh chóng nhận ra vai trò và ý nghĩa của từng đoạn code. Các chú thích trong chương trình Java được đặt trong cặp /* và */ khi cần chú thích nhiều dòng hoặc để sau cặp // khi chỉ chú thích một dòng. Nhập môn Java I. public class Vidu 3. Trong khi lập trình.class 26 . Dòng 6: Câu lệnh in ra màn hình dòng chữ “Hello.println("Hello. ta cần chú ý viết các dòng chú thích để mô tả về mã nguồn. Dùng một trình soạn thảo bất kỳ hoặc một IDE Java thì càng tốt để soạn chương trình. trong trường hợp này.out. World!”.class mặc định cũng nằm trong thư mục C:\JavaSample. mọi chương trình nếu cần thực thi đều bắt đầu từ hàm main.java Sau lệnh này. Gọi cửa sổ Command Line của Windows: Từ Menu Start. Java sẽ sinh ra một file mã bytecode có tên Vidu. 7. Viết và thực hiện một chương trình Java I. 5. Giả sử ghi vào thư mục C:\JavaSample. tên file phải bắt buộc là Vidu giống như tên lớp trong chương trình. 4. } Dòng 1: Dòng chú thích trong một chương trình Java.1 Tìm hiểu mã nguồn một chương trình đơn giản 1. Thực hiện chương trình Java. Các lệnh trong Java luôn được kết thúc bởi dấu . Từ dấu nhắc gõ lệnh: java C:\ JavaSample\Vidu. Dòng 3. Trình thông dịch sẽ tìm hàm main làm điểm khởi phát cho một ứng dụng Java.java. nếu chương trình không có lỗi cú pháp. Ở đây. Phần mở rộng cũng bắt buộc là . World!"). System. Điều này rất quan trọng khi chương trình lớn và gặp lỗi. Ghi file vừa soạn với tên Vidu. Tuy nhiên các cặp /* và */ hay được dùng hơn vì các đoạn chú thích này sẽ được tự động đưa vào tài liệu khi ta dùng công cụ javadoc để sinh tài liệu cho mã nguồn. ta thực hiện theo các bước sau: 1. tất cả các lệnh nằm trong cặp này đều thuộc phạm vi của lớp Vidu. 2. Trong Java. public static void main(String[] args) 5. Dòng 2: Khai báo một lớp có tên Vidu. } 8.

Ở đây. hàm hay thủ tục bên ngoài lớp. Khai báo gói: 27 . • Sử dụng phương thức (method) để thay thế cho hàm và thủ tục.6. Hàm main trong Java luôn luôn là static.class và in ra màn hình dòng chữ “Hello. • Tên khai báo lớp phải trùng với tên tệp “Vidu. Không được khai báo phương thức. khi cài đặt Java ta đã đặt đường dẫn mặc định đến thư mục chứa các lệnh này là: C:\Program Files\Java\jdk1. Cấu trúc một chương trình Java /*Khai bao goi*/ package <tên gói>. I. /*Hàm main*/ public static void main(String[] args) { // Các lệnh trong hàm main } } /*Cac lop lien quan khac*/ class A { …………. I. } Các thành phần trong một chương trình Java gồm có: 1. } class B { …………. /*Khai bao thu vien*/ import <tên gói thư viện>.java” • Trong Java tất cả hàm và thủ tục đều phải được đặt trong một lớp cụ thể. • Hàm main phải nằm trong file gọi thực hiện.Lệnh này sẽ thông dịch file mã bytecode Vidu. Một số chú ý khi lập trình Java • Java phân biệt chữ viết hoa và viết thường. java. /*Cac phuong thuc*/ ……………………. ta cần chú ý Windows không tự động hiểu các lệnh javac.4. Tuy nhiên.3. ta phải gọi các lệnh này với đường dẫn đầy đủ của nó. /*Khai bao lop chua ham main*/ public class <tên lớp> { /*Các thuoc tinh cua lop */ …………………….0_02\bin Trường hợp chưa đặt đường dẫn mặc định. World!”.

class Vidu sau khi biên dịch sẽ được đặt trong gói my. public class Application { 4.java. Java dùng ký từ “*” để ngụ ý việc nhập tất cả các class trong <tên thư viện>. ở đây gói “java” nằm trong gói “my” và class Vidu nằm trong gói “java”.println(“Hôm nay "+date).” chỉ sự bao gồm. hàm thành phần: Các khai báo này sẽ được bàn chi tiết trong mục “Lập trình hướng đối tượng trong Java”. nó cần truy cập theo đường dẫn gói “my. Trong trường hợp ứng dụng gồm nhiều class và cần tổ chức các class vào các gói riêng thì ta cần khai báo gói. /*Chương trình in ra ngày tháng hiện hành*/ 3.Vidu”. chúng ta sẽ rất khó khăn để tìm ra một class để sử dụng.util.java.out. Sau đây là một chương trình ví dụ sử dụng import: 1. Ví dụ: import my. Khi một chương trình Java khác muốn truy cập tới lớp Vidu.*. 7.Date. // Nhập tất cả các class có trong gói my. Thực ra. Khai báo các lớp khác: Thông thường 1 file chương trình Java chúng ta chỉ khai báo 1 class. System. Trong số 5 phần trên.Date” tại dòng số 5. II.1 Các kiểu dữ liệu số nguyên Java có 4 kiểu số nguyên: 28 . class Date đã được khai báo import nên không cần khai báo đầy đủ “java. Chỉ có class được gọi thực thi đầu tiên mới cần chứa hàm main. //tạo biến đối tượng thuộc class Date 6. Khai báo hàm main: Không phải tất cả các class trong Java đều chứa hàm main. 3. Nhập thư viện.java import my. // Nhập duy nhất class Vidu trong gói my.java.java. Trong hàng ngàn class được Java hỗ trợ trong các gói thư viện. public static void main(String[] args) { 5. ý nghĩa quan trọng của gói là việc tổ chức một cách logic các lớp vào trong các domain riêng để người phát triển ứng dụng dễ dàng truy cập.Cú pháp: package <tên gói>. khi sử dụng các class nằm trong gói theo <tên thư viện> ta không cần viết đầy đủ tên gói mà chỉ cần viết tên class. 5. Khai báo class. } Ở đây. tất nhiên là bao gồm cả class Vidu. Date date = new Date(). Tên của gói có chứa các dấu “. 4. thuộc tính. Các kiểu dữ liệu trong Java II. 2. chúng đều được nhóm lại theo chức năng và mục đích sử dụng với tên gói có tính chất gợi ý. } 8. import java.java.Vidu. Khai báo này là không bắt buộc với một chương trình Java. Tuy nhiên khi class đó quá phức tạp chúng ta có thể tách ra thành các class khác. Cú pháp: import <tên thư viện> Nếu có khai báo này. //Khai báo thư viện 2. tất cả các class đều có phần 3. Nếu không làm như vậy. Trong chương trình trên.util. các phần còn lại có thể có hoặc không tùy theo nhu cầu.

II.372.40282347E+38F double 8 bytes Xấp xỉ ±1.372.483.036.483.5 Kiểu chuỗi Java xem chuỗi là một đối tượng. Một biến char sẽ có một giá trị là một ký tự Unicode.0/0.String.775. • Số 0. 647 Từ –32. • Số âm/dương. II.147. Biến đối tượng chuỗi thường được khai báo từ lớp String nằm trong gói java.2 Các kiểu số thực Java có 2 kiểu số thực dấu chấm động: float 4 bytes Xấp xỉ ±3. II.4 Kiểu logic (boolean) Là kiểu dữ liệu chỉ có hai giá trị true và false dùng để xác định kết quả một điều kiện.6 Chuyển đổi giữa các kiểu số char byte short int long double float 29 .648 đến 2.lang.775.79769313486231570E+308 Số dấu chấm động có thể nhận các giá trị: • Vô cực âm/dương. • NaN (không là một số = 0.0f).147.223.223.854.767 Từ –9.768 đến 32. Chú ý: kiểu boolean không được thể hiện là 0 và 1.036.3 Kiểu ký tự (character) Là kiểu dữ liệu biểu diễn 1 ký tự unicode.808 đến 9.int short long byte 4 bytes 2 bytes 8 bytes 1 byte Từ –2. II.807 Từ –128 đến 127 II.854.

• Không trùng với các từ khoá. float y. int k = 1.45d. char ch = ‘T’.2 Khai báo biến Các biến trong Java rơi vào hai trường hợp: • Toán học: Các biến có kiểu nguyên thủy của Java đều thuộc dạng này. Ví dụ về khai báo biến kiểu địa chỉ: String strHello. boolean bQuit. có thể dùng các ký tự (chữ). Sau khi khai báo. // ví dụ lớp của AudioClip Khởi động giá trị cho biến Ví dụ về khởi động biến ngay lúc khai báo: byte i = 3.III. short j = 10. III. long x. • Địa chỉ: Các biến đối tượng được lưu ở dạng này. con trỏ. ta cần chú ý tuân thủ các điểm sau: • Chỉ bắt đầu bằng một ký tự (chữ). đối tượng. Các giá trị mặc định byte 0 short 0 int 0 30 . float y = 1. Các biến địa chỉ thường sử dụng để lưu trữ các địa chỉ mảng. String strHello = “Hello everybody”. //khai báo một chuỗi AudioClip music. boolean bQuit = true. dấu dollard.1 Quy tắc đặt tên biến Khi khai báo các biến trong chương trình Java. long x = 1234567L. int k. Ví dụ khai báo cho từng kiểu biến toán học: byte i. Khai báo biến và hằng trong Java III. • Không có khoảng trống giữa tên. double z. ký tự số. Ở đây cần chú ý rằng khi khởi tạo giá trị cho các kiểu số nên xác định rõ kiểu dữ liệu của giá trị. biến được cấp phát một vùng nhớ cố định tùy theo kích thước của kiểu dữ liệu của biến đó. Biến chỉ lưu giá trị địa chỉ đầu của một vùng nhớ được cấp phát cho đối tượng. short j.25f. dấu gạch dưới. char ch. • Sau ký tự đầu. một dấu gạch dưới (_) hay một dấu dollard ($). double z = 23.

Dùng từ khoá new để định vị cho một mảng trong vùng nhớ. boolean false. //Phần tử thứ 0 (đầu tiên) có giá trị là 99.3 Biến kiểu mảng Khi cần làm việc với một tập các giá trị có cùng kiểu dữ liệu. ta có thể sử dụng một biến mảng để lưu trữ chúng. Ví dụ: int IntArray[] = {1. float 0. Định vị mảng Sau khi khai báo. 4. bản thân mảng chưa xác định hay chưa được định vị vì chưa được cấp phát vùng nhớ . • Sử dụng cặp ngoặc vuông đặt sau kiểu dữ liệu. ‘b’.//tạo mảng 100pt float floatArray[]. 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. char [] charArray = {‘a’. Ví dụ b[‘a’] tương ứng với b[97]. ‘c’}. char null. Tuy nhiên nếu dùng kiểu char thì Java sẽ tự động chuyển sang mã ASCII tương ứng. for (sort i=1. và phần tử cuối cùng của một mảng có n phần tử là n-1. 2. floatArray = new float[10]. mảng cần được cấp phát vùng nhớ trước khi sử dụng. 5}. ví dụ: int IntArray[] = new int[100].0d. i<10. Do đó. 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. 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ó. double 0. 2. 3. Phần tử đầu tiên là phần tử thứ 0. Ví dụ: int intList[] = new int[10]. hoặc int intArray[]. ví dụ: int IntArray[] = {1. đều cho ta một mảng số nguyên có tên là intArray. 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. Các biến dẫn suất null III. //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ó. 2. 4. intArray2. Ví dụ: int [] intArray. 5}. intArray3. 4. i++) 31 . //tạo mảng 10pt intList[0] = 99.0f.long 0L. 3. int a = IntArray[2].//a=3 int b = IntArray[0]. 5}.//b=1 Ta có thể gán các giá trị của mảng thông qua truy nhập vào từng phần tử của mảng. IntArray[] = new int[] {1. 3. Kiểu dữ liệu của chỉ số là kiểu int.

intList[i] = 1; //các phần tử còn lại bằng 1 Ví dụ: int x, y, k; x = intList[0]; //x=99 y = intList[5]; //y=1 k = intList[y+1]; //k=intList[6]=1 Mảng nhiều chiều: Khai báo mảng 2 chiều: <kiểu phần tử>[][] <tên mảng> = {<danh sách phần tử>}; Ví dụ: int[][] b = {{1,2},{3,4}}; Đây là khai báo và khởi tạo giá trị cho một mảng 2 chiều kích thước 2 x 2. {1,2} là các phần tử của hàng 1; {3,4} là các phần tử trên hàng thứ 2. Hoặc ta có thể khai báo rõ số hàng và số cột của mảng: int b[][] = new int[ 3 ][ 4 ]; Thậm chí ta có thể khai báo một mảng 3 chiều hoặc hơn. int b[][][] = {{{1,2},{3,4}},{{5,6},{7,8}}}; Ta được b[0][0][0] =1; b[0][0][1]=2;b[1][1][1]=8;b[0][1][0]=3; III.4 Hằng số (literal) Là một giá trị không đổi được sử dụng trong chương trình. Hằng số được biểu diễn như chính nó chứ không là một giá trị của biến hay một kết quả của biểu thức. Giá trị của hằng số không thể bị thay đổi. Ví dụ: Pi = 3.1415. Tên của hằng số được đặt tên như tên biến. Cách khai báo hằng cũng tương tự như biến nhưng có dùng thêm từ khóa final: <phạm vi> final <kiểu dữ liệu của hằng> <tên hằng> = <giá trị> Ví dụ: public final String mauda ="vang"; Hằng số có thể là: Hằng số nguyên: Hằng có thể được biểu diễn dưới dạng thập phân, bát phân, thập lục phân. Ví dụ: biểu diễn số 15 dạng int: 15. dạng long: 15L. dạng bát phân: 017. dạng thập lục phân: 0xF. Hằng số thực: Tương tự như hằng số nguyên, để chỉ rõ hằng là float ta thêm vĩ ngữ “ f ” hay “F”, hằng là double ta thêm “d” hay “D”. Hằng Boolean: Một hằng số kiểu boolean có giá trị là true hoặc false. Trong Java, các giá trị 0 và 1 không được dùng thay thế cho false và true như trong C hoặc C++. Hằng ký tự: Là một ký tự đơn giản hay một chuỗi ESCAPE, hằng ký tự được đặt trong hai dấu ngoặc đơn ‘’. Các chuỗi ESCAPE: ‘\b’ : Xoá lùi. ‘\n’ : Xuống dòng. ‘\t’ : Tab ngang. 32

‘\f’ : đẩy trang. ‘\r’ : dấu enter. ‘\”’ : nháy kép. ‘\’’ : nháy đơn. ‘\\’ : sổ ngược. ‘uxxxx’: ký tự unicode. Ví dụ: System.out.println(“Xin chào bạn \n Nguyễn Văn A”); Sẽ in ra màn hình kết quả: Xin chào bạn Nguyễn Văn A Hằng chuỗi ký tự: Một hằng chuỗi ký tự có thể có 0 ký tự (hằng chuỗi rỗng) hay nhiều ký tự. Ví dụ: “A String”, “” //chuỗi rỗng, “dong 1 \t\n dong 2”. III.5 Phạm vi hoạt động của hằng và biến: Khối lệnh Block 1 chứa 2 khối lệnh con Block 2, Block 3.

{ Block 1
{ Block 2 }

{
Block 3

}

}
Biến hay hằng sẽ chỉ có ý nghĩa trong phạm vi khối lệnh mà nó được khai báo.

IV. Các toán tử và biểu thức
IV.1 Các toán tử và thứ tự ưu tiên Các toán tử thường sử dụng: Toán tử Ý nghĩa = Gán != so sánh khác > so sánh lớn hơn < so sánh nhỏ hơn >= lớn hơn hoặc bằng <= nhỏ hơn hoặc bằng + cộng trừ * Nhân

Ví dụ x=10 x!=5 x>5 x<20 x>=10 x<=10 y=x+1 y=x-1 y=x*3

33

/ % ++ -+= -= *= /= ^ | & ! && || ==

Chia Lấy phần dư tăng giá trị lên 1 giảm giá trị đi 1 cộng kết hợp phép gán trừ kết hợp phép gán nhân kết hợp phép gán chia kết hợp phép gán phép XOR trên bit phép OR trên bit phép và trên bit Toán tử logic NOT Toán tử logic AND Toán tử logic OR So sánh bằng nhau

y=x/3 10%3 = 1 x++ x-x+=y tương đương x=x+y x-=y tương đương x=x-y x*=y tương đương x=x*y x/=y tương đương x=x/y x^y x|y

Thứ tự ưu tiên: ( ), *, /, %, +, -,= =, !=, &, ^, |, &&, ||, =, %=, /=, *=, -=, += IV.2 Biểu thức Biểu thức là sự kết hợp các biến số, các giá trị bởi các toán tử hoặc có thể là một phép gán giá trị một biểu thức cho một biến số. Ví dụ: (x+3)/(y-2); Có 3 loại biểu thức chính là: • Biểu thức số liên kết các biến số, các hằng bằng các phép toán số, kết quả là một giá trị số. • Biểu thức gán dùng để gán giá trị cho một biến, một hằng. • Biểu thức logic chỉ cho ra kết quả là các giá trị true hay false. Khi sử dụng câu lệnh gán kết quả của một biểu thức cho một biến, ta cần chú ý tới vấn đề đồng nhất kiểu dữ liệu giữa hai vế để tránh mất thông tin. Ví dụ: double delta = 0.0d; //khai báo một biến số thực có tên delta. delta = 1/ 100; // Gán cho delta kết quả của phép chia 1 cho 100. Trong tình huống này, ta không thu được delta = 0.01 như mong đợi mà là delta =0. Lý do là các số 1 và 100 đều được hiểu là các số nguyên và kết quả của phép chia được tự động làm tròn thành một giá trị nguyên trước khi gán cho delta. Để khắc phục tình trạng này, ta cần xác định rõ các số 1 và 100 là các số double. delta = 1d/100d;

V. Các lệnh điều khiển rẽ nhánh
V.1 Lệnh if Lệnh if...{...}: là một phép kiểm tra giá trị của một biểu thức boolean, nếu cho giá trị là true thì khối lệnh sẽ được thực hiện. Cấu trúc: if <biểu thức boolean>

34

break. case . } }} Dạng 2 của câu lệnh if: if <biểu thức boolean> { <khối lệnh 1>. break. Cấu trúc: switch <biểu thức>{ case <giá trị 1>: <khối lệnh 1>. Ví dụ: public class dkIfThen { public static void main(String[] args) { int x=1. case <giá trị 2>: <khối lệnh 2>. if (x<y) { System.out..println("x>y").println("x>y"). } Nếu biểu thức boolean đúng thì <khối lệnh 1> được thực hiện. break. } 35 . khối lệnh sẽ được thực hiện.{ <khối lệnh>. còn nếu biểu thức boolean sai thì <khối lệnh 2> được thực hiện.out.out. break. } else { System..2.. default: <khối lệnh default>. Lệnh switch …case Lệnh switch .: Cho phép chọn nhiều trường hợp xảy ra của giá trị so sánh.. case <giá trị n>: <khối lệnh n>. }}} V. Ví dụ: public class dkIfThen { public static void main(String[] args) { int x=1. còn nếu biểu thức đó sai thì khối lệnh sẽ bị bỏ qua. . int y=x+1.. } else { <khối lệnh 2>. if (x<y) { System.println("x<y").. } Nếu biểu thức boolean đúng. int y=x-1.

[<biểu thức kiểm tra>]. biến đếm thay đổi giá trị một lượng bằng <bước nhảy> và <biểu thức kiểm tra> được tính lại.i<accounts. Các lệnh lặp VI.2.1. các lệnh tiếp theo sẽ được thực hiện.1. còn nếu là false.Một số chú ý khi sử dụng lệnh switch-case: Các giá trị: <giá trị 1>. ta có thể sử dụng một vòng lặp for.i++){ sum+=accounts[i]. 36 . Lưu đồ hoạt động của vòng lặp for như sau: Biểu thức biến điều khiển Biểu thức điều chỉnh theo bước nhảy Biểu thức kiểm tra true false Thực hiện khối lệnh Kết thúc vòng for Ví dụ: tính tổng 1 dãy số thực public class vdFor { public static void main(String[] args) { double accounts[]={1. 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. } Bắt đầu với giá trị <khởi tạo> của biến đếm. [<bước nhảy>]) { <Khối lệnh>.4. Sau mỗi lần thực hiện xong <khối lệnh>.…<giá trị n> phải là các hằng số. Vòng lặp for Khi muốn một khối lệnh được thực hiện với một số lần biết trước. double sum=0. <khối lệnh> được thực hiện.1. vòng lặp chấm dứt. for (int i=0.length. Cấu trúc lệnh: for([<khởi tạo>]. <giá trị 2>. Nếu biểu thức kiểm tra là true thì lại thực hiện khối lệnh.6}. VI.

] .2. } [các câu lệnh. } Khối lệnh được thực hiện khi <bt boolean> còn có giá trị true.. Lưu đồ thực hiện: Bt boolean false true Các câu lệnh Câu lệnh tiếp theo 37 .} System. 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. j<5. Vòng lặp while Khi một khối lệnh cần được thực hiện.. i<10.2 Các vòng for có thể được đặt lồng nhau nếu cần Ví dụ: for(int i=0. thường là với một số lần không được biết trước. Cấu trúc lệnh: while <bt boolean> { <Khối lệnh>. i++) { [các câu lệnh. j++) { [các câu lệnh.println(sum). ] } VI. ] for(int j=0. ta có thể sử dụng vòng lặp while. } }//kết quả là: 4.out.

Ví dụ: while <bt boolean 1>{ lệnh 1. Vòng lặp do. nếu tìm thấy phải thôi duyệt dãy ngay. Lệnh continue Cho phép chương trình bỏ qua vòng hiện tại và nhảy đến vòng tiếp theo. sum=0. lệnh 2. Cấu trúc lệnh: do { <khối lệnh>. Ví dụ: while <bt boolean 1>{ 38 .out. if <bt boolean 2> break. do{ sum+=x. Ví dụ tính tổng 10 số nguyên dương đầu tiên: public class vdDoWhile { public static void main(String[] args) { int x=1. } } //kết quả là: 55 VI. x++. nếu không sẽ dừng vòng lặp. Khi thực hiện vòng lặp duyệt dãy. 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>. } while <biểu thức boolean>. Phép nhảy Trong một số trường hợp. lệnh 3. Lệnh break Lệnh này kết thúc ngay vòng lặp trong cùng (nếu có nhiều vòng lồng nhau) chứa nó. Nếu <biểu thức boolean> có giá trị true thì tiếp tục thực hiện <khối lệnh>.. System. so sánh các phần tử của dãy với giá trị cần tìm từ phần tử đầu tiên cho đến phần tử cuối cùng. } while (x<11).4.println(sum).VI. việc thực hiện các vòng lặp đôi khi không theo hết vòng mà có thể dừng hoặc thoát khỏi vòng lặp. } lệnh 4.3. 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>.. Ví dụ: Tìm một giá trị nào đó trong một dãy 1000 phần tử. Việc nhảy ra khỏi vòng lặp được thực hiện với lệnh break hoặc kết thúc vòng hiện tại với lệnh continue.

you'll be " + (age + 1)).lệnh 1.nextLine().out.*. 2. } lệnh 3.print("What is your name? ").util.print("How old are you? "). Tương tự cho các kiểu dữ liệu khác.nextInt(). // Khai báo một biến Scanner có tên là “nhap”.nextInt(). } } 39 .in). Khai báo biến thuộc lớp Scanner. String name = nhap.print("What is your name? "). Vào dữ liệu từ bàn phím và xuất dữ liệu ra màn hình VII.out.5 và nằm trong gói java. VII. public class InputTest { public static void main(String[] args) { Scanner nhap = new Scanner(System. Java.. } lệnh 4. // 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. lệnh 2. continue.in).nextLine(). if <bt boolean 2> { …….1.println("Hello. Lấy giá trị nhập vào từ bàn phím Để lấy giá trị mà người sử dụng nhập từ bàn phím.util. // Lay gia trị nhap ho ten System.next().Scanner nhap = new java. " + name + ". Lớp Scanner chỉ được hỗ trợ từ phiên bản Java 1. lệnh continue được thực hiện.*/ String name = nhap.out.Scanner(System. // Lay gia tri nhap tiep theo System. // Hien thi ket qua nhap tren man hinh System. Ví dụ: import java. Để đọc 1 từ trong chuỗi nhập vào: String firstName = nhap. Nếu đọc vào một số nguyên: int Tuoi = nhap.out.util. Next year. Lấy giá trị nhập vào: System. chương trình sẽ không thực hiện tiếp <lệnh 3> mà quay lại kiểm tra <bt boolean 1>. ta làm theo các bước sau: 1. Khi <bt boolean 2> có giá trị true. int age = nhap.util.

out. }} Lưu ý rằng khi sử dụng các ký tự định dạng ta cần dùng hàm System.printf(“%8.println() như thường lệ.printf() thay vì System.songuyen).09898765. ta đã biết dùng hàm System.out. public class TestFormat { public static void main(String[] argvs) { double sothuc = 10.out. 10/3).sothuc).VII.59e+01 Sau đây là ví dụ sử dụng các ký tự định dạng khi xuất dữ liệu ra màn hình. int songuyen =100.out.9 0x1.printf(“Hello. /*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.songuyen).money). System.fccdp3 Hello H True 42628b2 Số thực float theo ký pháp cơ số e 1.3f \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.print("\"Mot tram phan tram\" thi in ra the nao: 100%").2 Kết xuất dữ liệu ra màn hình Trong các chương trình ví dụ trên. You have %f VND ”.1f”.out. /*In ra số nguyên ở hệ cơ số 8*/ System.print để in dữ liệu ra màn hình.out. System. %s.printf("He 8 cua 100 duoc viet la: %o \n". Tuy nhiên. Sau đây là bảng các ký tự định dạng: Ký tự định dạng D X O F E A S C B H tx % N Định dạng Số nguyên thập phân Số nguyên hệ 16 Số nguyên hệ 8 Số thực float Số thực float dạng Hexa String Ký tự Boolean Hash code Date and time Ký hiệu phần trăm Xuống dòng % Ví dụ 159 9f 237 15.printf("Ket qua 3 so sau dau phay la %10. /*In ra số nguyên ở hệ cơ số 16*/ System.out.out. /*In ra ký tự đặc biệt “” */ System.print() hay System. name.out.out. 40 .printf("He 16 cua 100 duoc viet la: %x \n".

Viết chương trình đếm tần suất xuất hiện của các từ trong một chuỗi nhập từ bàn phím.out. d) Đoạn mã sau sẽ in ra các số nguyên chẵn từ 2 đến 100 ?: counter = 2. Viết chương trình tìm số nhỏ nhất trong số các số được nhập vào từ bàn phím. x >= 1. j <= 5.println( x ). Cho biết số nguyên đầu tiên nhập vào sẽ chính là số các con số được nhập. Đoạn chương trình sau làm gì? public class Printing { public static void main( String args[] ) { for ( int i = 1. x >= 1. } c) Đoạn mã sau sẽ in ra các số nguyên lẻ từ 19 đến 1 ?: for ( x = 19. k.println( "Odd integer" ).out. System. i++ ) { for ( int j = 1. Ví dụ: nguyen van nam -> Nguyen Van Nam 5. x++ ) System.…. j++ ) System. Tìm các lỗi trong các đoạn chương trình sau: a) For ( x = 100. 8. i <= 10. Các từ cách nhau bởi dấu space.out. 3. b) Đoạn mã sau sẽ in ra các giá trị chẵn hay lẻ: switch ( value % 2 ) { case 0: System.out. và . Nhập vào một chuỗi họ tên của một người.print( '@' ). } } } 7. hãy sửa lại các ký tự đầu các từ cho đúng quy định viết hoa và khoảng cách giữa các từ. 2.. counter += 2.out.…nhập từ bàn phím): A = 1 + 1/2! + 1/3! + … + 1/n! B = 1/1! – 1/2! + 1/3! .out.println( x ).1/4! + … + 1/(2k+1)! . do { System.out. Viết chương trình in ra màn hình các mẫu như sau: 41 . x += 2 ) System.println(). Viết chương trình tính giá trị các biểu thức (Giá trị n. 4.Bài tập 1. Viết chương trình đếm số từ có trong một chuỗi ký tự nhập vào.println( "Even integer" ). } While ( counter < 100 ).println( counter ). 6. case 1: System.

9. 42 .141. Tính số PI theo công thức sau: In ra 10 giá trị chính xác hơn 3.

Vậy làm thế nào để đưa chúng vào máy tính? Câu trả lời là chúng ta cần một quá trình trừu tượng hóa. Quan sát thế giới thực. khai thác thông tin cũng như các mối quan hệ từ chúng hoặc thay đổi trạng thái của chúng. 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. Chúng ta gọi chúng là những đối tượng. Thực tế thì ta không thể viết chương trình hướng đối tượng bằng các ngôn ngữ cấu trúc (như Pascal chẳng hạn) vì các ngôn ngữ này không hỗ trợ cú pháp cài đặt và kỹ thuật biên dịch các đặc tính của hướng đối tượng. Môi trường này bao gồm một thư viện được thiết kế tốt. Chúng ta sử dụng kỹ thuật hướng đối tượng để ánh xạ những thực thể chúng ta gặp phải trong đời sống thực thành những thực thể tương tự trong máy tính. Do đó. Như vậy. Đây là một điểm mạnh của OOP và phương pháp trước đây không có được. ta thấy mọi vật đều có vị trí riêng của nó. I. lập trình viên phải nắm được sự tương ứng giữa các các đối tượng thực tế.OOP) I. 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. Thông tin về đối tượng và mối quan hệ giữa chúng thực tế là vô cùng. từ nghiệp vụ thực tế chúng ta không thể ngay lập tức đem vào cài đặt trong ngôn ngữ OOP mà phải qua một quy trình phân tích và thiết kế theo hướng đối tượng như chúng ta đã thấy qua việc nghiên cứu ngôn ngữ mô hình hóa UML – một ngôn ngữ giúp chúng ta trừu tượng hóa thế giới thực. các hành vi. các dự án phần mềm phân tích và thiết kế theo UML bắt buộc phải sử dụng kỹ thuật OOP để cài đặt thì mới phát huy hiệu quả.1. Lập trình hướng đối tượng trong Java I. phát triển phần mềm theo kỹ thuật lập trình hướng đối tượng có khả năng giảm thiểu sự lẫn lộn thường xảy ra giữa hệ thống và lĩnh vực ứng dụng. Tuy nhiên. Hơn nữa. Đối với một ngôn ngữ lập trình hỗ trợ OOP thì việc triển khai kỹ thuật lập trình hướng đối tượng sẽ dễ dàng hơn. các mối quan hệ của các đối tượng là nhiệm vụ mà lập trình OOP phải làm. 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. Khái niệm lập trình hướng đối tượng (Object-Oriented Programming . I. chúng sở hữu các tính chất và thuộc tính riêng.3 Trừu tượng hóa Quản lý thông tin. 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ường là ngôn ngữ OOP. OOP là phương thức tư duy mới để giải quyết vấn đề bằng máy tính. 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. 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. 43 . Ngôn ngữ OOP cung cấp đầy đủ phương tiện để thực hiện điều này. Để đạt kết quả. cách thức vận động riêng.Đề tài 3. Khái niệm OOP Lập trình hướng đối tượng là sự cài đặt một chương trình theo hướng đối tượng bằng các ngôn ngữ lập trình.2 Cơ sở lý luận của OOP Chúng ta thấy rằng thuật ngữ “hướng đối tượng” có nghĩa là lấy đối tượng làm trung tâm và tất cả nằm trong đối tượng.

Trong khi đó. Tóm lại. 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. Qua đây. Một hệ thống quản lý sinh viên có thể chỉ cần quan tâm tới: Họ và tên. 44 . chúng ta có một mô hình trừu tượng hóa của một sinh viên: Sinh viên Họ và tên Ngày sinh Tên lớp Địa chỉ Điểm môn học Thay đổi lớp Thay đổi nơi ở Điểm quan trọng là sau khi trừu tượng hóa từ một lớp các sinh viên (tất cả các sinh viên trong phạm vi quản lý).Classes Trừu tượng hóa Thế giới thực = Các đối tượng + Các mối quan hệ • • Tóm lại: Các thực thể tồn tại trong thế giới thực được mô hình hóa thành các lớp đối tượng. 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ác mối quan hệ giữa các thực thể trong thế giới thực được mô hình hóa bằng các mối quan hệ giữa các lớp đối tượng. huyết áp. 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. điểm các môn học. mô hình này đại diện cho tất cả sinh viên và là khuôn mẫu để tạo ra bất kỳ sinh viên nào khác. Khi quan tâm tới giá trị của các thuộc tính. một anh sinh viên bất kỳ có thể có hành vi “xin đổi lớp học” hoặc “đổi địa chỉ nơi ở” làm cho giá trị các thuộc tính “lớp học”. cân nặng. Quá trình xác định các hành vi của đối tượng phục vụ cho nghiệp vụ quản lý cũng là một quá trình trừu tượng hóa hành vi. nhóm máu. Các lớp đối tượng trong chương trình . 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. cân nặng. ngày sinh. địa chỉ nơi ở.… chúng ta không cần quan tâm. Ở đây ta không quan tâm tới giá trị cụ thể của các thuộc tính này. “địa chỉ nơi ở” bị thay đổi. anh ta được quản lý như một bệnh nhân. các thông tin khác về sinh viên – cũng là một con người – như chiều cao. lớp học. Cũng là một sinh viên nhưng nếu chẳng may anh ta bị ốm nằm viện. Trong ví dụ trên.Giả sử đối tượng quản lý là một sinh viên.…và tất nhiên là cũng có các mô hình hành vi khác.

một sự mô hình hóa một lớp đối tượng trong thực tế. • Bao gồm (Aggregation): Class A có quan hệ bao gồm với class B nếu đối tượng của class A chứa đối tượng của class B.3 Một số gợi ý khi thiết kế class • Khai báo dữ liệu private: Điều này tránh việc truy cập tùy ý từ bên ngoài lớp. Cấp độ public cho phép sự truy cập từ bên ngoài lớp trong khi private chỉ cho phép nội bộ lớp truy cập. 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. 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. hành vi làm thay đổi trạng thái đối tượng thông qua việc thay đổi giá trị các thuộc tính. Ví dụ: Trong hệ thống bán hàng chúng ta có: • class DanhMucMatHang • class TaiKhoan • class HoaDon • class HoaDonThanhToanNhanh Mỗi HoaDon bao gồm 1 DanhMucMatHang: Quan hệ aggregation. • 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. II. Khi một HoaDon được tạo ra.2 Mối quan hệ giữa các class Các class trong chương trình có thể quan hệ với nhau theo 1 trong 3 dạng: • Phụ thuộc (Dependence): Class A có quan hệ phụ thuộc với class B nếu phương thức của class A có sử dụng đối tượng thuộc class B. Tính đóng gói trong Java II. ngoài ra class B còn định nghĩa các phương thức và thuộc tính khác của riêng nó. • Thừa kế (inheritance): Class B gọi là thừa kế class A nếu class B có các phương thức và thuộc tính của class A.II. private. • 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 thườ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 45 .1 Khái niệm tính đóng gói Tính đóng gói thể hiện bởi việc thuộc tính mô tả đối tượng và hành vi của đối tượng được gắn chặt với nhau. Thuộc tính thể hiện trạng thái đối tượng. Hành vi được cài đặt thông qua mã lệnh Java bởi các phương thức. phương thức khác: Quan hệ inheritance. nó cần truy cập đến class TaiKhoan để kiểm tra tình trạng thẻ tín dụng: Quan hệ dependence. object = attributes (các thuộc tính) + operations(các hành vi) + name (tên định danh) Như vậy tính đóng gói thể hiện việc chuyển mô hình đối tượng thực tế thành các lớp trong Java. Đối tượng được sinh ra bởi class . Thông tin và hành vi đối tượng được bảo vệ bằng các cấp độ truy cập: public. II.

image java.awt.crypto Hỗ trợ các class cần thiết cho việc tạo ra các Applet và giao tiếp giữa Applet với môi trường ngữ cảnh của nó. Hỗ trợ cho các thao tác vào / ra dữ liệu trên hệ thống file.lang java.beans java.rmi java. numbers và các thông điệp.math java. Cung cấp các lớp nền tảng để thiết kế ngôn ngữ lập trình Java. 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. 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. Cung cấp các lớp tạo và hiệu chỉnh hình ảnh.security java.com/j2se/1. Sử dụng các Class xây dựng sẵn trong thư viện Java hỗ trợ cho lập trình viên một thư viện phong phú các lớp đối tượng đã được xây dựng và thiết kế cẩn thận.awt. Cung cấp các lớp và giao diện cho mục đích in ấn. Cung cấp các lớp cho việc cài đặt các ứng dụng mạng.2/docs/api/overview-summary.sql java. Cung cấp các lớp cho không gian màu.awt. 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. 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.io java. ngày tháng.event java.4.font java. dates.net java. Lập trình viên chỉ cần biết cách lấy chúng ra và sử dụng chúng theo kịch bản của ứng dụng.….awt.color java. 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.sun.• • 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.text java. Hỗ trợ các lớp và giao diện cho các thao tác mã hóa dữ liệu.html ) Các gói thường dùng trong Java 2 SE java. Đặ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ó.util javax. Cung cấp các gói cho lập trình RMI – Remote Method Invocation.applet java. Tuy nhiên điều này là không bắt buộc.awt.print java. 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. 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ệ.awt java. Hỗ trợ các giao diện và lớp liên quan đến font chữ. 46 . Cung cấp các lớp và giao diện cho việc quản lý text. 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. IV.

Cung cấp các lớp và giao diện làm việc với cây javax. } Ta sẽ lần lượt xem xét từng thành phần: <Cách truy xuất>: • public: Có thể truy cập lớp từ các lớp khác. // In ra tháng hiện tại V. V. Cung cấp các lớp và giao diện làm việc với bảng. Các lớp trừu tượng được thiết kế chỉ cho mục đích kế thừa.tree javax. Cung cấp các hàm API cho việc truy cập dữ liệu phía server. myDate chưa được cấp phát vùng nhớ. • abstract: Lớp trừu tượng. mặc định là public.out. Cung cấp các lớp cơ bản cho các dịch vụ in ấn qua mạng.javax.1 Cấu trúc của class [<Cách truy xuất>] class <tên lớp> [extends <tên lớp cha>] [implements <tên giao diện>] { <các thành phần của lớp>.getMonth()). Xây dựng Class trong Java Cài đặt các lớp là công việc thường xuyên của lập trình viên Java. Khai báo: Date myDate. Hỗ trợ các lớp cho việc xử lý các tài liệu XML.JTree.event javax.swing javax.parsers Cung cấp các lớp cho lập trình mạng. Cung cấp một tập các thành phần giao diện được chấp nhận và thống nhất trên hầu hết các hệ thống máy tính. Sau đây là hướng dẫn ví dụ về sử dụng lớp Date có sẵn trong thư viện của Java: Khai báo biến đối tượng với toán tử new Date myDate = new Date().swing.xml. 47 . • Nếu <cách truy xuất> không được xác định.swing. Date() là phương thức contructor của class Date.net javax.print javax.swing. Một đối tượng luôn được tạo ra từ một constructor của lớp đó. 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. ta có thể áp dụng các phương thức và thuộc tính của class Date cho myDate. Xác định rằng myDate là một đối tượng thực sự thuộc class Date.swing. không được khởi tạo đối tượng của lớp này. System.println(myDate.table javax. Câu lệnh: myDate = new Date(). Hỗ trợ cho các sự kiện kích hoạt bởi các thành phần của Swing.sql javax. • final: Không cho phép kế thừa. 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ế.

<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.2 Các thuộc tính thành phần: Khai báo thuộc tính chính là việc khai báo các biến. 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. các biến thông thường có phạm vi private. Do đó.MaSo = 10. SinhVien sv = new SinhVien(20.”. Các biến có phạm vi lớp rất ít khi được sử dụng.Tuoi.”Nguyen Van A”). <tên lớp cha>: Tên của lớp cha mà lớp hiện tại thừa kế. Hơn nữa. Khi khai báo trong lớp chúng thường được xác định phạm vi hoạt động là một trong các dạng: • public: Biến có thể truy cập ở bất cứ lớp nào.<tên lớp>: Tên của lớp. <tên giao diện>: Tên của giao diện được cài đặt tại lớp. phụ thuộc vào biến thuộc dạng nào trong 2 dạng sau: 1. Mặc định thì phạm vi truy cập của biến là public.Tuoi=21. cố định có ở mọi đối tượng. V. // 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. Đây có thể là một danh sách các giao diện phân tách bởi dấu “. Ví dụ: public int Tuoi. 48 . Ví dụ: public static final String MauDa = “Vang”. trước hết phải khởi tạo một đối tượng thuộc lớp. trong khi các hằng static lại rất hay được dùng. • private: Chỉ được truy cập trong chính lớp đó. Lý do là trong thực tế. Khi truy cập ta chỉ cần gọi: Math. ví dụ gán Tuoi của sinh viên này bằng 21: Sv. 2. Là hằng số của lớp Math. khi chúng đã không phụ thuộc vào một đối tượng cụ thể nào thì ta cũng không cần khởi tạo một đối tượng để truy cập. Ta sẽ lần lượt xem xét tới các thành phần này. 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). private String HoVaTen. 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. Truy cập vào biến Tuoi như sau: sv.PI Chú ý: Các biến rất ít khi được khai báo là public vì có thể thay đổi giá trị của nó bên ngoài lớp nên khó quản lý. Giá trị của biến được dùng chung giữa các đối tượng.14159265358979323846. Biến có phạm vi lớp (biến tĩnh): Đây là biến có phạm vi tồn tại trong mọi đối tượng của lớp được tạo ra trong chương trình đang chạy. 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. Khi truy cập. ta cần thêm từ khóa static như ví dụ sau: public static int MaSo. Khi khai báo một biến có phạm vi lớp. Muốn truy cập vào biến. các lớp đối tượng thường có các thuộc tính chung. • protected: Chỉ được truy cập trong lớp đó và các lớp kế thừa. Cách truy cập biến rất đơn giản. 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. ta sẽ cài đặt chúng như là các hằng static.

. public void PrintNumber() { int number =20. 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.println(number). 49 . không cài đặt gì ở trong lớp khai báo nó. • Nếu không khai rõ cách truy xuất. // khai báo trùng với biến của lớp System.: là các kiểu dữ liệu mà phương thức trả về.println(this. float. • public: có thể truy xuất từ bất kỳ lớp bên ngoài nào.3 Các phương thức thành phần Phương thức thành phần là sự cài đặt các hành vi của đối tượng. } <Cách truy xuất>: • private: phương thức này chỉ được truy xuất bên trong lớp chứa nó. 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 đó. char. • abstract: phương thức đơn giản nhất.out. Cú pháp khai báo một phương thức trong lớp như sau: [<Cách truy xuất> <cách cập nhật>] <Kiểu giá trị trả về> <Tên phương thức>([<danh sách biến hình thức>]) [<mệnh đề throws>] { <Nội dung của phương thức>.Thường dùng biến this để truy cập đến các thuộc tính của lớp bị khai báo trùng trong phạm vi các phương thức của lớp. void: phương thức không trả về giá trị. Lớp có chứa phương thức abstract cũng phải được khai báo abstract.out. String..//in bien number =10 } } V.. <Kiểu giá trị trả về>: integer. //in bien number = 20 System. • 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. • native: là phương thức được viết bằng ngôn ngữ khác java. • final: phương thức này được bảo vệ không cho các lớp dẫn xuất khai báo và cài đặt lại. nó có thể được gọi mà không cần khởi tạo đối tượng của lớp. Ví dụ: public class TestThis { private int number = 10. tức là nó không có phần thân.number). • protected: chỉ các lớp là dẫn xuất của lớp chứa phương này mới truy xuất được nó. Khi xác định kiểu giá trị trả về. < 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ể. các phương thức sẽ có cách truy xuất mặc định là public. Phương thức này sẽ được phát triển trong các lớp là dẫn xuất của lớp chứa nó.

Constructor không được kế thừa. nó chỉ được định nghĩa cho chính lớp cha. việc gọi phương thức thường được xử lý như một giá trị.println("Hello!").4 Gọi và truyền tham số cho phương thức • Các tham số kiểu cơ bản được truyền theo kiểu tham trị. Nếu phương thức trả về void. Trong trường hợp cần thiết ta có thể khai báo phương thức hủy theo cú pháp: protected void finalize() { // Body of Method } Hàm main() Đây là một hàm đặc biệt được cài đặt trong lớp được gọi thực thi đầu tiên trong chương trình.public static int max(int num1. việc gọi phương thức là câu lệnh. phương thức hủy được gọi khi đối tượng được giải phóng. int num2) { if(num1>num2) return num1.out. Các chú ý khi truyền tham số cho phương thức: • Các phương thức không thể làm thay đổi giá trị của các tham số có kiểu nguyên thủy. • Phương thức không thể làm cho tham số đối tượng tham chiếu tới một đối tượng mới. • Các tham số có kiểu đối tượng được truyền theo kiểu tham chiếu. 50 . V. Vì nó được gọi khi chưa có đối tượng nào được tạo ra nên nó luôn được khai báo là static.println(max(3. 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ề. lập trình viên không cần quan tâm. 5). Khi không khai báo phương thức khởi tạo. } Về <mệnh đề throws> chúng ta sẽ xem xét kỹ trong phần xử lý ngoại lệ. 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ị. hoặc ta có thể in giá trị trả về của cuộc gọi phương thức: System. Ví dụ phương thức println() trả về void: System.6 Các hàm và phương thức đặc biệt Phương thức khởi tạo: Phương thức khởi tạo (constructor) dùng để khởi tạo một đối tượng của lớp và đặt trạng thái ban đầu cho đối tượng bằng cách xác định giá trị cho các thuộc tính của lớp. 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. V. Ví dụ: int larger = max(3. 5)). trong Java công việc này được làm tự động. • Phương thức có thể làm thay đổi trạng thái của tham số kiểu đối tượng. else return num2. Mỗi lớp có thể có 1 hoặc nhiều phương thức khởi tạo.out. đối tượng được tạo ra bằng phương thức khởi tạo mặc định không tham số với các giá trị mặc định của các thuộc tính. Tuy nhiên.

private double DiemTongKet. } // Hàm main public static void main(String[] argvs) { // Truy cập vào biến lớp không cần khởi tạo đối tượng SinhVien.double dtk) { super(t. Điều này gọi là khai báo chồng phương thức. // biến lớp // Phương thức khởi tạo public SinhVien(int t.} Sau đó.String ht) { Tuoi=t. ta có một lớp SinhVien kế thừa từ lớp People trên: public class SinhVien extends People { private String Lop. 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.String ht. } // Phương thức hiển thị tên và tuổi của một người public String toString(){ return HoVaTen + ".ht). V.valueOf(Tuoi). }. //hằng số // Phương thức khởi tạo public People(int t.Hơn nữa. 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. // 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. public static int MaSo. DiemTongKet=dtk. public static final String MauDa=”Vang”. 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. protected String HoVaTen.5. 51 .7 Khai báo chồng các phương thức Các phương thức trong cùng một lớp có thể có cùng tên nhưng nhất định số lượng các tham số hoặc kiểu của chúng phải khác nhau. Hàm main() có một tham số là một mảng các chuỗi chứa nội dung các tham số dòng lệnh.MaSo=10." + String. Từ phiên bản Java 1.String l. HoVaTen=ht. việc gọi hàm main() đương nhiên là diễn ra bên ngoài lớp nên nó cũng cần có mức độ truy cập là public.

void test() { Inner inner = new Inner(). System..print(k. Lớp lồng tĩnh (static nested class) được bổ sung từ khoá static.// Khởi tạo một đối tượng sinh viên..toString()). Hầu hết các lớp lồng là lớp nội bộ. inner. mà chỉ dùng chúng thông qua đối tượng. SinhVien.MaSo=11."Pham Anh Thu". // Khởi tạo một đối tượng sinh viên."Letio3". Tuy nhiên. Trình biên dịch Java sẽ báo lỗi nếu một đoạn mã bất kỳ của lớp bên ngoài truy cập trực tiếp lớp lồng. V. Nó có thể truy cập trực tiếp đến các biến và phương thức đối tượng."Nguyen Thi Mai"."Pham Anh Hoa"). } class InnerClass { // Lớp lồng phi tĩnh hay lớp nội bộ .. System.15).out.out.8. // Báo lỗi dòng này } } Trong chương trình trên. Một lớp lồng có quyền truy cập đến các thành viên của lớp bao bên ngoài.8 Lớp lồng nhau – lớp nội Có thể định nghĩa một lớp bên trong một lớp khác.7.print(k.. } class Inner { // có thể truy xuất trực tiếp biến đối tượng của lớp Outer 52 . Nó không thể tham chiếu trực tiếp đến biến hay phương thức đối tượng được định nghĩa trong lớp bao.display_x()."Letio3".. việc khởi tạo một đối tượng thuộc lớp People sẽ bị báo lỗi do lớp này là lớp trừu tượng. Chúng ta sẽ trở lại vấn đề này trong phần “Tính kế thừa”. Vì giới hạn này nên lớp lồng tĩnh ít được dùng. lớp bao không thể truy xuất các thành phần của lớp lồng. MaSo của sinh viên này sẽ là 11 SinhVien k1 = new SinhVien(20. } } Lớp lồng chỉ được biết bên trong phạm vi của lớp bao bên ngoài. còn được gọi là lớp nội bộ (inner class). MaSo của sinh viên này sẽ là 10 SinhVien k = new SinhVien(23. Lớp như vậy gọi là lớp lồng (Nested Class) và được cài đặt như sau : class EnclosingClass{ // Lớp bao bên ngoài . static class StaticNestedClass { // Lớp lồng tĩnh . Có hai kiểu lớp lồng : tĩnh và phi tĩnh.15). thậm chí nếu chúng được khai báo private. Lớp lồng phi tĩnh (nonstatic nested class) không bổ sung từ khoá static. class Outer { int outer_x = 100.. People p = new People(20.MaSo).

double s. khi xử lý các sự kiện.out. VI. outer. void display_x() { System. VI. Luong = s. int year.println(“display : outer_x = “ + outer_x). // Error } } class InnerClassDemo { public static void main(String args[]) { Outer outer = new Outer(). 53 . } } Trong Java có sử dụng một kỹ thuật cài đặt lớp nội nặc danh. int month. Tính kế thừa trong Java Để theo dõi tính kế thừa trong Java được cài đặt như thế nào.util. 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. } public void windowIconified(WindowEvent e) {System. Ví dụ: frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { System. } } void display_y() { // không thể truy xuất biến đối tượng của lớp Inner System. month . Nó được khai báo chồng 2 phương thức của WindowAdapter. class Employee { // Phương thức khởi tạo public Employee(String n.test(). tức là không có tên. day).} } ). GregorianCalendar calendar = new GregorianCalendar(year. import java.int inner_y = 10.exit(0).println(“display : inner_y = “ + inner_y). ta có một lớp nặc danh kế thừa từ lớp WindowAdapter.Date.1 Sự kế thừa các thuộc tính và phương thức Giả sử trong công ty.out. Lớp Employee được định nghĩa như sau: import java. đội ngũ quản lý (managers) được đối xử khác với nhân viên (employees) bình thường. Ở đây. int day) { HoVaTen = n.exit(0).util.GregorianCalendar.1.

Luong += PhanTang. private double Luong.. private Date NgayBatDau. supperclass. với Employee chỉ được trả lương theo một hợp đồng có sẵn trong khi Manager ngoài lương ra còn được hưởng một khoản tiền thưởng. Lớp đang tồn tại còn được gọi là lớp cha. Lớp Manager có thêm thuộc tính TienThuong và phương thức để thiết đặt giá trị cho nó: class Manager extends Employee { . } 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. } // Phương thức tăng lương public void raiseSalary(double PhanTram) { double PhanTang = Luong * PhanTram / 100. } // Các thuộc tính thành phần private String HoVaTen. Đây chính là ngữ cảnh tốt để cài đặt tính kế thừa. Tuy nhiên. } //phương thức lấy ngày bắt đầu làm việc public Date getNgayBatDau() { return NgayBatDau. lớp con.// GregorianCalendar coi 0 là Tháng 1 NgayBatDau = calendar. lớp kế thừa còn được gọi là lớp dẫn xuất.getTime(). Chúng ta sẽ thiết kế một lớp Manager nhưng kế thừa lại những gì đã viết ở lớp Employee.. class Manager extends Employee { //Các thuộc tính và phương thức bổ sung } Từ khóa extends xác định rằng chúng ta đang tạo ra một lớp mới được dẫn xuất từ một lớp đang tồn tại. } // Phương thức lấy lương public double getLuong() { return Luong. Các lớp dẫn xuất thường được cài đặt nhiều tính năng hơn lớp cha. hoặc lớp cơ sở (base class). } // Phương thức lấy họ tên public String getHoVaTen() { return HoVaTen. 54 .

Tuy nhiên điều này có thể cho phép tất cả các lớp dẫn xuất từ Employee thay đổi giá trị các thuộc tính này làm tính đóng gói của OOP bị phá vỡ.public void setTienThuong(double b) { TienThuong = b. // Không thực hiện } Tuy nhiên nó không thực hiện. Tuy nhiên. Tuy nhiên. ta cần định nghĩa một phương thức mới trong lớp Manager đè lên phương thức cũ: class Manager extends Employee { .. phương thức getLuong() đối với lớp Manager phải là tổng của Luong và TienThuong. } Việc sử dụng các thuộc tính và phương thức này không có gì đặc biệt. Luong. Đế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.. ta có thể gọi: boss. lớp con chỉ việc khai báo thêm các thuộc tính và phương thức đặc biệt. Thuộc tính Luong trong Employee được khai báo là private nên chỉ các phương thức trong lớp Employee mới được phép truy cập. Theo lý thuyết. Tất nhiên là đối tượng của lớp Emplyee không thể gọi phương thức setTienThuong() vì nó không phải là phương thức được định nghĩa trong lớp Employee.. NgayBatDau và TienThuong. } private double TienThuong. } Chúng ta có thể nghĩ việc cài đặt cho phương thức mới này rất đơn giản như: public double getLuong() { return Luong + TienThuong. // vẫn không thực hiện 55 . Do đó.setTienThuong(10000).. Nếu ta có một đối tượng Manager có tên boss. chúng ta có thể sử dụng các phương thức getHoVaTen().. public double getLuong() { . một số phương thức của lớp cha có thể không còn phù hợp ở lớp con. public double getLuong() { double LuongCoBan = 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. Lớp Manager có 4 thuộc tính là HoVaTen. getLuong(). việc xác định cho các thuộc tính lớp Employee cấp độ truy cập là protected có vẻ là hợp lý. Luong và NgayBatDau cũng được kế thừa. getNgayBatDau() đối với các đối tượng của lớp Manager vì chúng được tự động kế thừa từ lớp Employee. Lý do là vì sự truy cập vào Luong ở đây là không hợp lệ. Tương tự như thế. } . các thuộc tính HoVaTen. Ở đây..

s. s. super(n. year. } // Phương thức tính lương public double getLuong() { double LuongCoBan = super. ta dùng từ khóa final khi khai báo phương thức. } //Phương thức đặt tiền thưởng public void setTienThuong(double b) { TienThuong = b. double s. month. Tuy nhiên ta có thể sử dụng phương thức khởi tạo của lớp cha để khởi tạo giá trị cho các thuộc tính được kế thừa ở lớp con: public Manager(String n. day). } Ở đây. int day) { super(n. } Nếu không cho phép lớp con kế thừa một phương thức của lớp cha.getLuong(). day). VI. year. int month. 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. } 56 . TienThuong = 0. Lý do là phương thức getLuong() lúc này được coi là chính phương thức getLuong() của lớp Manager nên nó không có tác dụng. year. // OK return LuongCoBan + TienThuong. Lưu ý là lệnh gọi super phải là lệnh đầu tiên trong phương thức constructor ở lớp con. month. month và day. ta dùng từ khóa super để chỉ lớp cha. Để gọi được phương thức getLuong() của lớp Employee. int day) { super(n. s. year. public double getLuong() { double LuongCoBan = super. s. int month. // OK return LuongCoBan + TienThuong. day). đoạn mã này cũng chưa thực hiện được. TienThuong = 0.return LuongCoBan + TienThuong. double s. int year.2 Sự kế thừa đối với các constructor Như đã đề cập. month. các phương thức khởi tạo không được tự động kế thừa cho lớp con.getLuong(). } Tuy nhiên. Đến đây. thay cho việc gọi constructor của Employee với 5 tham số n. int year.

12. Manager boss = new Manager ("Nguyen Tan Minh". // Chuyển kiểu OK boss1 = (Manager) me. 1987. boss. 12. 1). 12. // Cha không chuyển kiểu sang con được Thậm chí một mảng các đối tượng Employee có thể được gán cho một mảng các đối tượng Manager mà không cần chuyển kiểu: Manager[] managers = new Manager[10]. thậm chí là cùng danh sách tham số. Trong ví dụ trên. 1987. Employee you = new Employee("Nguyen Anh Tai". phương thức getLuong() được định nghĩa ở cả lớp cha và lớp con.// 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. boss. 50000. Manager boss1 = new Manager ("Nguyen Tan Phat". boss1. 1987. 10. đối tượng lớp con không thể được gán tham chiếu tới một đối tượng lớp cha nhưng có thể chuyển kiểu sang lớp cha. } VII. 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. 15). nó không có phương thức setTienLuong(). 80000. 2000. Trường hợp ngược lại là không thể.setTienThuong(15000).setTienThuong(5000). phương thức vẫn được gọi theo đúng đối tượng sở hữu nó. sự chuyển đổi này chỉ diễn ra trong thời gian chạy chương trình. Nếu khi lập trình ta viết: you = boss. 52000. Employee[] staff = managers. 57 . 81000. // OK Tuy vậy. cơ sở của tính đa hình cũng đã được cài đặt. đô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. Đây chính là thể hiện tính đa hình của đối tượng.setTienThuong(2000). 2000.setTienThuong(5000). // không gán tham chiêu được me=boss1. Trong khi chúng ta cài đặt tính chất thừa kế của OOP. 15).2 Sự ràng buộc động –Dynamic Binding Xét ví dụ sau: // Khai báo một đối tượng Manager Manager boss = new Manager("Phan Thanh Ha".private double TienThuong. Ví dụ: Employee me = new Employee("Nguyen Anh Minh". //OK. 15). // OK you. hoặc: you = (Employee)boss. Cho dùng là cùng một tên gọi. 80000. boss = me.1 Sự ép kiểu và gán tham chiếu đối tượng Trong quan hệ thừa kế. Tính đa hình trong Java Tính đa hình là một khả năng của OOP cho phép một phương thức thực thi theo ngữ cảnh lúc chương trình đang chạy. 10. Ngược lại. 1). chúng ta sẽ xem nó được gọi như thế nào. VII. VII.

Kết quả in ra là: Phan Thanh Ha 85000. 50000. Nếu lớp D không có. 1990. một lớp dẫn xuất từ C (Ban đầu x là một đối tượng lớp C nhưng sau đó được gán tham chiếu tới một đối tượng của D). giả sử là x. ví dụ f(int) và f(String). Bây giờ.getHoVaTen() + " " + e. Lớp Object Lớp Object là lớp cha của mọi lớp trong Java.setTienThuong(2000). Ta gọi việc getLuong() của Manager được gọi trong tình huống này là sự ràng buộc muộn hay ràng buộc động (Dynamic Binding). Tiếp theo. thì không được phép khi biên dịch.println(e. 2. 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. static và final hoặc là một constructor. nó sẽ đưa ra thông báo lỗi. Mặt khác.0 Nguyen Hai Nam 50000. Ngược lại. nó sẽ tìm lên các lớp cha của D (trong đó có lớp C). 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. Nếu trong danh sách phương thức có tên f chỉ có 1 phương thức có kiểu tham số phù hợp thì phương thức này được gọi. // Gán boss cho đối tượng thứ 0 staff[0] = boss. Trong đó x được khai báo là đối tượng của lớp C. Trong lớp C có thể có nhiều phương thức có cùng tên f nhưng khác nhau ở tham số. 1). Cơ chế này gọi là ràng buộc động.// Khai báo một mảng 3 đối tượng Employee Employee[] staff = new Employee[3]. 10. 15). Tuy nhiên chúng ta không bao giờ phải khai báo: class Employee extends Object 58 . 1989. Trình biên dịch sẽ liệt kê tất cả các phương thức tên f trong lớp C và phương thức tên f có mức độ truy cập public trong các lớp cha của C. 3. 40000. Ví dụ câu lệnh là x.f(param).0 Ở đây chúng ta thấy đối tượng thứ 1 và 2 in ra các giá trị vốn có của nó theo phương thức getLuong() của Employee.0 Pham Quyet Tan 40000. // Dùng vòng lặp để in ra tên và lương từng người for (Employee e : staff) System. Nếu trình biên dịch không thể tìm thấy phương thức có tham số phù hợp hoặc có nhiều hơn 1 phương thức phù hợp. 3. phương thức được gọi tùy theo kiểu hiện tại của đối tượng. Nếu D có định nghĩa một phương thức f(String) thì phương thức này sẽ được gọi. Nếu phương thức là private. VIII.getLuong()).f(“Chao ban”) thì hàm f(String) được gọi chứ không phải f(int). 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ố). Điều này gọi là ràng buộc tĩnh (static binding). staff[2] = new Employee("Pham Quyet Tan". 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. Để kết thúc phần này ta sẽ xem xét cơ chế của việc gọi phương thức của một đối tượng trong Java được thực hiện như thế nào: 1. Tuy nhiên đối tượng thứ 0 đã gọi phương thức getLuong() của Manager. giả sử kiểu hiện tại của x là D. Đặc trưng thể hiện tính đa hình trong Java. Cơ chế này gọi là nạp chồng (overloading).out. // Khởi tạo cho 2 đối tượng còn lại staff[1] = new Employee("Nguyen Hai Nam". nếu viết: staff[0].

Giao diện không phải là một class nhưng nó chỉ ra các phương thức sẽ được định nghĩa trong các lớp cài đặt nó. Object obj = new Employee("AAA". do đó. 35000). } Ví dụ các lớp muốn cài đặt giao diện Comparable<Employee> phải cài đặt phương thức: int compareTo(Employee objKhac). obj = staff. Cấu trúc của một giao diện rất đơn giản: public interface <tên giao diện> { //Danh sách các phương thức } Tại lớp có cài đặt giao diện: public class <tên lớp> implements <tên giao diện> { //Phân thân lớp có chứa định nghĩa phương thức của giao diện } Ví dụ: Trong lớp Arrays của Java có phương thức sort dùng để sắp xếp các đối tượng trong một mảng. kết quả so sánh biểu hiện qua một số nguyên. // OK IX.1 Cấu trúc của giao diện Trong Java không hỗ trợ tính đa thừa kế.0 (1. Bây giờ chúng ta định nghĩa: 59 . Điều này dẫn đến việc thiết kế một giao diện: public interface Comparable { int compareTo(Object objKhac). Các lớp có sử dụng tới các phương thức này phải khai báo cài đặt giao diện bằng từ khóa implement. Tuy nhiên. đối tượng thuộc lớp Object có thể được tham chiếu tới bất kỳ đối tượng nào khác. Giao diện IX. Từ phiên bản Java 5. muốn sắp xếp được thì trong định nghĩa lớp của các đối tượng này phải có cài đặt một phương thức so sánh compareTo(Object objKhac). đó là các interface hay còn gọi là các giao diện. Mở rộng hơn. các giao diện có thể được xác định cho một kiểu tổng quát: public interface Comparable<T> { int compareTo(T objKhac). Employee[] staff = new Employee[10]. Tuy nhiên. // OK obj = new int[10]. } 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.Mọi lớp đều là hậu duệ của Object. tất cả các lớp muốn sử dụng phương thức sort của Array đều phải cài đặt phương thức này trong định nghĩa của nó. Tất cả các phương thức khai báo trong interface mặc định là public nên ta không cần khai báo public cho nó.5). Java hỗ trợ một kỹ thuật thay thế và rất linh hoạt.

} . return 0.. các hằng số. Rõ ràng là một đối tượng Manager vẫn có thể được so sánh với một đối tượng Employee về tiền lương.. Tuy nhiên nếu ta cũng khai báo chồng một phương thức compareTo() thì không được do vi phạm quy tắc chuyển kiểu: class Manager extends Employee { public int compareTo(Employee objKhac) { Manager otherManager = (Manager) objKhac. if (Luong > objKhac. return 0.compareTo(y) <0 nếu x < y x.compareTo(y) >0 nếu x > y Trong interface ta đang xem xét thì nó chỉ có một phương thức.Luong) return 1. nhất định ta phải có khai báo public.. } .x. if (Luong > other. // Chuyển kiểu if (Luong < other. Đối với phiên bản Java 5.. ta có thể cài đặt: class Employee implements Comparable<Employee> { public int compareTo(Employee objKhac) { if (Luong < objKhac. // không được .0. } Chú ý rằng các phương thức trong interface không khai báo public nhưng khi cài đặt chúng. Khai báo cài đặt Comparable cho Employee: class Employee implements Comparable Giả sử các Employee được so sánh thông qua tiêu chí Luong.compareTo(y) =0 nếu x = y x. Các interface thường có nhiều phương thức. Trong phần sau đây chúng ta sẽ cài đặt một phương thức compareTo cho việc so sánh các đối tượng Employee.Luong) return -1. Các interface có thể xem như các lớp trừu tượng không có thuộc tính thành phần tuy rằng chúng có nhiều điểm khác biệt..Luong) return -1.Luong) return 1. } May mắn là ta không cần làm điều này vì tính kế thừa đã đảm bảo Manager cài đặt Comparable<Employee> chứ không phải Comparable<Manager>. ta cài đặt compareTo như sau: public int compareTo(Object objKhac) { Employee other = (Employee) objKhac. Tuy nhiên trong interface ta không thể khai báo các biến thành phần và không thể cài đặt nội dung của các phương thức. } Đối với lớp Manager thì sao. Khi đưa một đối tượng 60 ..

Nếu muốn sử dụng cả hai Date trong chương trình ta phải khai báo trực tiếp: java. .*. X. Ví dụ: import java.util. public interface Comparable<Employee> { double greater = 1.1 Sử dụng các package trong thư viện Java Để sử dụng các class nằm trong một gói thư viện của Java mà không cần viết đường dẫn đầy đủ của gói.util. import java. } Trong interface. // Lỗi • Có thể khai báo một biến interface. .util.2 Các tính chất của giao diện Khi sử dụng interface ta cần chú ý mấy điểm sau: • Giao diện không phải là class nên không dùng từ khóa new để tạo một đối tượng kiểu giao diện: x = new Comparable(.*. nó tự động được ép sang kiểu Employee. Comparable x. x = new Employee(.sql. Vị trí của dấu “*” có thể là tên một class cụ thể.util. import java.*.sql. 61 . // OK Biến interface phải tham chiếu tới một đối tượng của một lớp có cài đặt interface đó. int compareTo(Employee other). IX. Việc so sánh vì thế diễn ra thoải mái giữa các đối tượng Employee và Manager với nhau. ta khai báo nhập thư viện: import java. Package X. • Một lớp chỉ có thể kế thừa từ một lớp khác trong khi có thể cài đặt nhiều giao diện.Date(.sql. java. . Các lớp có cài đặt interface cũng tự động được thừa kế các hằng số này. . Thì trình biên dịch báo lỗi vì không biết Date của gói nào. // OK • Có thể dùng toán tử instanceof để kiểm tra xem một đối tượng có được cài đặt interface hay không: if (anObject instanceof Comparable) { . } • Các interface cũng có thể được kế thừa.Date today = new java.Date(). Khi này ta phải khai báo rõ ràng cho Date ở gói nào: import java. .). . sử dụng dấu “*” có thể gây ra lỗi. khai báo “double greater =1” được tự động hiểu là: public static final double greater =1.. • Có thể khai báo các hằng số trong interface. Trong một số trường hợp.)..sql.Date.Date deadline = new java.Manager vào làm tham số so sánh. Dấu “*” đại diện cho tất cả class.*.).util. Trong cả hai gói này đều có lớp Date nên trong dòng lệnh: Date myDate = new Date().

Tuổi. Hãy xây dựng các class điểm. Sắp xếp danh sách. ta phải có đường dẫn đầy đủ: Javac com\myproject\employee\Employee. hóa đơn. Trong đó các thành viên của lớp là các đối tượng Sinh viên có các thuộc tính như Họ và tên. Trong hệ thống đồ họa: a. Xóa Sinh viên.class sẽ nằm trong thư mục: com\myproject\employee tính từ thư mục hiện thời.print(“Khong co ten lop System”). 2) + pow(y. 5.. 2. Xây dựng một lớp đối tượng phương trình bậc 2 sao cho ta có thể khởi tạo một phương trình bậc 2 và biết ngay các tình trạng của nó như có nghiệm hay không và giá trị nghiệm. ta phải có khai báo package ở dòng đầu tiên của chương trình: package com. PhuongTrinhBac2 có cài đặt giao diện này. Hãy cài đặt một phương thức toString() cho các lớp trên theo kỹ thuật ràng buộc động. 7. thống kê giới tính. X. Phương thức toString() in ra màn hình giá trị tất cả các thuộc tính của một đối tượng. Xem danh sách. đoạn thẳng. 6.Ta cũng có thể có một khai báo nhập thư viện với từ khóa static: import static java. Hãy cho biết một thứ tự phân cấp kế thừa của các lớp này. Thực hành cài đặt các ví dụ trong đề tài trên. tam giác. Do đó. Khi đó các phương thức và thuộc tính tĩnh của lớp System được truy cập mà không cần có tên lớp: out. Xây dựng một lớp PhuongTrinhBac1 để giải phương trình bậc 1. Xây dựng một giao diện GiaiPhuongTrinh dùng cho việc giải các phương trình bậc 1 và bậc 2 sau đó xây dựng lại các lớp PhuongTrinhBac1. c. Trong ví dụ trên Employee. hình vuông.System. public class Employee { . Khóa học.. 3. hình thoi. thống kê học tập.myproject. giỏ hàng trong một hệ thống quản lý bán hàng ở siêu thị. Điểm tổng kết và các phương thức phù hợp (sinh viên tự xác định xem cần những phương thức gì). tứ giác. sản phẩm. Xây dựng các class trong java để cài đặt các lớp đối tượng: Khách hàng. 2)).employeee. đa giác. Xây dựng một lớp đối tượng để cài đặt cho lớp đối tượng lớp học bao gồm các thuộc tính như: Sĩ số. Ta thường dùng phương pháp này với các hàm của class Math: sqrt(pow(x. Các lớp trong gói sẽ tự động thuộc vào một đường dẫn đầy đủ theo tên của package. Giới tính. } Nếu không có khai báo đó. 4. khi biên dịch hoặc chạy chương trình từ cửa sổ dòng lệnh CommandLine.*. b. 62 . hình chữ nhật.2 Đặt lớp vào package Để đặt một lớp vào một package.java Bài tập 1.lang. danh sách lớp và các phương thức như: Thêm sinh viên. Các đối tượng sinh viên được so sánh theo tiêu chí điểm tổng kết. lớp tự động thuộc vào một package mặc định không có tên. Tên lớp.

Trong lập trình cũng vậy. Để cho các định nghĩa này thêm sáng tỏ. Cài đặt lớp và phương thức trừu tượng trong Java Khai báo: Lớp trừu tượng được khai báo như lớp thông thường nhưng có thêm từ khóa abstract. } public String getHoTen() { return HoTen. Các đối tượng này đều có một phương thức toString để trả về một chuỗi bao gồm toàn bộ thông tin về chúng. Khái niệm lớp trừu tượng Những khái niệm trừu tượng trong thế giới thực được cài đặt trong chương trình như là các lớp trừu tượng. String ht) { NamSinh= ns. ……. Lớp SinhVien kế thừa từ People được cài đặt như sau: 63 . GiaoVien. Đến đây ta lại bắt gặp một khái niệm trừu tượng hơn là “động vật” v.…. một khái niệm chung cần được làm rõ là “động vật bốn chân”. Trong các định nghĩa trên. HoTen = ht. Các con mèo là động vật bốn chân hay bắt chuột. abstract String toString().Đề tài 4. public People(int ns. Chú ý là các phương thức trừu tượng không có phần thân. } Ta thấy rằng một lớp trừu tượng thực sự là một lớp với đầy đủ các thành phần. Các con hổ là động vật bốn chân sống trong các khu rừng. ta cần một định nghĩa về “động vật bốn chân” Động vật bốn chân là động vật có bốn chân để di chuyển. } abstract String toString().v…và có rất nhiều khái niệm dùng đến khái niệm này như động vật ăn cỏ. không giống như interface. Giả sử trong chương trình có các đối tượng SinhVien. động vật ăn thịt. Ví dụ: abstract class People { private int NamSinh. động vật bò sát. private String HoTen. II. Lớp và phương thức trừu tượng I. Chúng thực sự không có một biểu hiện nào (hoặc nếu ta bắt buộc chúng có biểu hiện thì biểu hiện đó cũng không có ý nghĩa trong phạm vi đang xét). Đây là tình huống sử dụng phương thức trừu tượng một cách hiệu quả. Chúng thường làm cơ sở để giúp ta có được các định nghĩa cụ thể hơn: Ví dụ: Các con trâu là động vật bốn chân được nuôi phục vụ cày bừa. những lớp đối tượng sinh ra chỉ để cho các lớp khác kế thừa gọi là các lớp trừu tượng.

Xây dựng chương trình nhập vào dữ liệu cho 5 chiếc xe cả ô tô và mô tô và in ra màn hình theo thứ tự tăng dần của giá sửa. 4 chỗ. Lop = l. tiền điều trị. Một nhà máy sửa chữa phương tiện vận chuyển có các loại xe ô tô thuộc nhiều hàng khác nhau như Honda. Ngoài ra.String ht. Ford. } } Khi một phương thức được khai báo là abstract thì lớp chứa nó cũng phải là một lớp abstract. 12 chỗ và 24 chỗ. Mercedec. } // Cài đặt phương thức toString public String toString() { return String. Hãy xây dựng một giao diện trong đó có phương thức so sánh phương tiện theo tiêu chí giá sửa. a. Mỗi hãng ô tô lại có nhiều kiểu khác nhau như 2 chỗ. Nhà máy có các chế độ khuyến mại và bảo hành khác nhau tùy theo xe của từng hãng. DiemTongKet=dtk.double dtk) { //Dùng phương thức khởi tạo của lớp cha super(ns. Khi sử dụng phương thức abstract cho một lớp thì nhất thiết phải có một lớp khác kế thừa và khai báo cài đặt chồng thì mới có tác dụng. Sau đó xây dựng hai lớp BenhNhanNoiTru và BenhNhanNgoaiTru kế thừa lớp BenhNhan. Xây dựng một lớp BenhNhan trừu tượng có các thuộc tính như họ và tên. Mishubishi. Toyota.valueOf(DiemTongKet) + HoTen.ht). Kia.valueOf(NamSinh) + String.public class SinhVien extends People { private String Lop. Hãy xây dựng một lớp PHUONG_TIEN trừu tượng có phương thức trừu tượng là Xac_Dinh_Gia() trong đó việc tính giá sửa cho một phương tiện bằng giá của nhà máy trừ đi tiền khuyến mại. có phương thức tính tiền phải thanh toán bằng tiền điều trị cộng với tiền giường nằm.String l. Bài tập 1. // Phương thức khởi tạo public SinhVien(int ns. private double DiemTongKet. b. Khi kế thừa một lớp có chứa phương thức trừu tượng thì phương thức đó bắt buộc phải được cài đặt. c. 64 . Trong hệ thống quản lý bệnh nhân ở bệnh viện có 2 loại bệnh nhân là nội trú và ngoại trú trong đó bệnh nhân nội trú có tính tiền giường nằm. 7 chỗ. (Gợi ý: Phương thức TinhTien ơ lớp BenhNhan khai báo trừu tượng sau đó được khai báo chồng tại các lớp thừa kế). 3. nhà máy còn nhận bảo dưỡng cho các loại xe mô tô tay ga và xe số.

13. • Nếu là 1 tham số thì đó là số phần tử ban đầu. 2.util. 5.out. Chúng ta sẽ xem xét việc sử dụng interface Enumeration để cho phép duyệt lặp trên các cấu trúc như Vector. Dòng 2-7: Vòng lặp để nhập và lưu kết quả nhập vào Vector.get(i)). { 11.lang. { 4.out. Lưu trữ và xử lý đối tượng Trong phần này chúng ta sẽ đề cập tới các lớp tiện ích của Java trong gói java. Để lưu các giá trị dữ liệu nguyên thủy. v. tham số thứ 2 chỉ số phần tử được thêm vào mỗi khi dung lượng của Vector bị hết.out.i++) 3.Đề tài 5. Ở đây ta phải khai báo một biến đối tượng kiểu Integer chứ không phải là một kiểu nguyên thủy int. 15. Ở đây ta đã dùng một constructor với 2 tham số là số phần tử ban đầu và số sẽ tăng khi Vector có nhu cầu tăng (mặc định sẽ gấp đôi số hiện có). 65 .1 Lớp Vector Lập trình viên dùng lớp Vector để lưu trữ các đối tượng có kiểu giống nhau nhưng có thể thay đổi động về kích thước tùy theo nhu cầu.valueOf(i) + " la:"). Sau đây là một ví dụ nhập vào 10 số nguyên.Vector v = new java. System.nextInt()). 6. Long hay Float thay vì dùng chính kiểu đó.print("So nguyen thu " + String. java. Dòng 1: Khai báo một đối tượng v thuộc lớp Vector.util dùng cho việc lưu trữ và xử lý các đối tượng. // In ra de kiem tra 9. lưu vào một Vector rồi in ra để kiểm tra: // Nhâp 10 doi tuong so nguyen 1.println(v.println(v.i<10. • Nếu là 2 tham số thì tham số thứ nhất chỉ số phần tử ban đầu.2).Vector(5.addElement(p). System. Vì vậy thao tác chèn một phần tử mới vào một Vector sẽ nhanh hơn khi kích thước của nó còn đủ dùng.util. System.println(v. I. Sau đó dùng phương thức addElement() để thêm đối tượng này vào vị trí cuối của Vector.valueOf(i) + ":"). for (int i=0. Lớp Vector có 3 constructor: • Nếu dùng constructor không tham số thì Java tự động cấp cho ta số phần tử ban đầu là 10 và nhân đôi mỗi khi có nhu cầu mở rộng. Vector lưu trữ tham chiếu của các đối tượng nên chương trình có thể dùng Vector để lưu tham chiếu đến bất kỳ đối tượng nào. Lớp Vector và giao diện Enumeration I. } 14. 12. java.i<10.size()). Kích thước của Vector được tăng theo một lượng đặt trước hoặc được tự động tăng gấp đôi khi ta cần tăng dung lượng của nó. ta phải sử dụng các lớp trong java. 7.capacity()).lang. System.lang như Integer.i++) 10.Integer p = new java. System. } 8. for (int i=0.print("Nhap so nguyen thu " + String. khi cần cũng tự động nhân đôi.Integer(nhap.out.out.

I.2 Giao diện Enumeration Sử dụng phương thức elements() của một đối tượng Vector sẽ trả về một đối tượng Enumeration cho phép chương trình duyệt lặp trên danh sách phần tử của Vector. Dòng 15: Kích số lượng các phần tử tối đa hiện có của Vector (=11). Đoạn chương trình sau duyệt và in ra danh sách các sinh viên: abstract class People { protected int NamSinh. Đối tượng key và các phần tử của Vector được so sánh với nhau bởi phương thức equals(). lastElement(): Trả về tham chiếu tới phần tử cuối cùng trong Vector. Đối tượng Enumeration có các phương thức quan trọng sau: • hasMoreElement(): Trả về true nếu vẫn còn phần tử trong Vector. Một số phương thức của Vector: removeElementAt: Xóa một phần tử ở một vị trí xác định. //Ho Va Ten //constructor public People(int ns. } // Ke thua lop People public class SinhVien extends People { 66 . indexOf(Object): Trả về chỉ số của đối tượng đầu tiên so khớp với Object. tức là số phần tử thực sự Vector lưu trữ (=10) .Ngoài ra ta cũng có thể sử dụng insertElementAt() để chèn phần tử vào một vị trí xác định hoặc sử dụng setElementAt() để đặt giá trị cho một phần tử tại một vị trí. trimToSize(): Giảm số lượng phần tử của Vector. isEmpty(): Xác định liệu Vector là trống. firstElement(): Trả về tham chiếu tới phần tử đầu tiên. Thực ra thì phương thức get(chỉ số) cho ta một tham chiếu đến đối tượng có chỉ số tương ứng được lưu trong Vector nhưng ở đây đối tượng số nguyên đã tự động in ra giá trị. Các lớp thường khai báo chồng phương thức equals() để dùng trong việc so sánh các đối tượng của mình. HoVaTen=ht. Dòng 14: Phương thức trả về kích thước thực tế của Vector. • nextElement(): Trả về tham chiếu tới phần tử tiếp theo trong Vector. Sử dụng removeElement(Object) để xóa một phần tử xuất hiện đầu tiên trong Vector có giá trị bằng với Object.//Nam Sinh protected String HoVaTen. removeAllElements(): Xóa tất cả các phần tử. public abstract String toString(). Dòng 12: Dùng phương thức get(chỉ số) để in ra giá trị của phần tử có chỉ số tương ứng.String ht) { NamSinh=ns. } // Phuong thuc tinh tuoi protected abstract int TinhTuoi(). contains(key): để kiểm tra xem trong vector có phần tử so khớp với key hay không.

String ht."Letio3"."Letio3".Date().8).valueOf(DiemTongKet)+"\n" +"Ho va ten:"+ HoVaTen.9).valueOf(ID)+ "\n" +"Tuoi:"+ String. sv.valueOf(this.Vector sv = new java. // Diem tong ket public final String mauda ="vang". sv. sv."Letio3". } // Khai bao chong phuong thuc toString() public String toString() { return "Ma so:" + String.//goi constructor cua lop cha la People Lop = l.6)."Phan Thi Mai 4"."Tran Thi Mai 2".//Hang so private int ID. } // Ham main public static void main(String[] argv) { // Dat gia tr? bien static. sv.addElement(k3). SinhVien k3 = new SinhVien(82. sv."Nguyen Thi Mai 1".ht). return (homnay. 67 .addElement(k5).private String Lop.NamSinh +1).double dtk) { super(ns. DiemTongKet=dtk.// Ma so SinhVien protected static int MaSo.util.// ma so chung de cap phat cho moi sinh vien // constructor public SinhVien(int ns.Date homnay = new java."Pham Thi Mai 3".Vector(5). } // Phuong thuc tinh tuoi protected int TinhTuoi() { java. // Them sinh vien vao Vector SinhVien k2 = new SinhVien(81.7).addElement(k2). SinhVien k1 = new SinhVien(80. SinhVien k4= new SinhVien(83.String l."Letio3". // Tang ma so len 1 den gan cho SinhVien sau MaSo+=1. sinh vien dau tien co ma so 1 SinhVien.getYear() .util."Hoang Thi Mai 5".TinhTuoi()) + "\n" +"Diem Tong Ket:"+ String.util. // bien doi tuong Vector java.addElement(k1).MaSo=1.util. SinhVien k5= new SinhVien(84. // Id cua SinhVien duoc gan bang gia tri MaSo hien thoi cua lop ID=MaSo.addElement(k4).5).// Ten lop private double DiemTongKet."Letio3".

Ví dụ: Đếm tần suất của các phần tử của một mảng: import javax.Enumeration enu = sv.out. bao loi vi People là lớp trừu tượng } } Kết quả thực hiện như sau: II.swing.*. } //People p = new People(20. System. Mảng trong Java và lớp ArrayList II.// Dung interface Enumeration de duyet cac phan tu cua Vector java.toString()).util. while (enu.hasMoreElements()) { // Ep kieu.nextElement().1 Mảng trong Java Trong phần “Ngôn ngữ Java căn bản” ta đã xem xét một biến mảng được khai báo và sử dụng như thế nào. kieu Object la kieu cha cua moi kieu nen luon ep duoc SinhVien g = (SinhVien)enu.elements().println(g. public class StudentPoll { // Hàm main public static void main( String args[] ) 68 . Trong phần này ta sẽ đi sâu khai thác các đặc tính của mảng và một số thuật toán thông dụng thông qua các ví dụ."Pham Anh Hoa").

pass. element. 7. 9. 1.tức là sau mỗi vòng lặp duyệt. rating < TanSuat. int second ) { int hold. // In ra System. 6. 8. 8. 10 }. 6. Chỉ cần duyệt mảng TraLoi 1 lần ta đã có ngay kết quả. for ( int answer = 0.length . 6. 3. 6. 4. II. 8. // Với mỗi phần tử của mang TraLoi.print(output). 6. 2.length. các câu trả lời nằm trong khoảng từ 1 đến 10 nên khai báo một mảng 11 phần tử để có thể sử dụng chính giá trị 10 làm chỉ số của mảng. 7. answer < TraLoi. // Biến trung gian để hoán đổi hold = array3[ first ].length. pass++ ) { // Vòng lặp so sánh và đổi chỗ for ( int element = 0. 5. int first. 6. 6. 7. 6. 4. element + 1 ). element < array2. // Mảng đếm tần suất int TanSuat[] = new int[ 11 ]. 8. // Đưa kết quả vào một chuỗi String output. array3[ first ] = array3[ second ]. 8. 8. Các thuật toán cơ bản trên mảng Ví dụ: Sắp xếp tuyến tính. 10. 6. sử dụng giá trị đó như là chỉ số của mảng TanSuat // sau đó đếm sự xuất hiện của nó trong TraLoi. 69 . 5. Đây là một ví dụ sắp xếp các phần tử của mảng tăng dần theo thuật toán “nổi bọt” . 7. pass < array2. answer++ ) ++frequency[ TraLoi[ answer ] ].2. array3[ second ] = hold. element++ ) { // So sánh 2 phần tử liền kề và đổi chỗ nếu cần if ( array2[ element ] > array2[ element + 1 ] ) swap( array2.length. }} Trong ví dụ này. phần tử nào lớn nhất sẽ bị đẩy xuống cuối cùng. 2. }} } // Hàm đổi chỗ 2 phần tử của một mảng public void swap( int array3[]. 7. 5.{ // Khai báo một mảng các câu trả lời int TraLoi[] = { 1. 5. // Sắp xếp các phần tử của mảng public void bubbleSort( int array2[] ) { // Duyệt qua mỗi phần tử của mảng for ( int pass = 1. 3. 6. rating++ ) output += rating + "\t" + TanSuat[ rating ] + "\n". for ( int rating = 1. lưu giá trị vào mảng TanSuat tại vị trí // tương ứng. 6. 8. 10. 5.out.

} Ví dụ: Tìm kiếm nhị phân trên mảng đã được sắp xếp: Thông thường việc tìm kiếm diễn ra bằng phép duyệt lần lượt các phần tử của mảng.67. đặt lại chỉ số dưới else low = middle + 1. Ta gọi phương pháp này là tìm kiếm tuyến tính. // Nếu khóa nhở hơn phần tử giữa. đặt lại chỉ số trên else if ( key < array[ middle ] ) high = middle .89. // Chỉ số dưới int high = array. // Khóa lớn hơn phần tử giữa. so sánh 7 với 5 thì 7>5 nên phần tử cần tìm nếu có sẽ nằm ở phần sau của nửa này gồm 2 phần tử 7. 70 . Arrays hỗ trợ các phương thức: • fill: để nạp giá trị cho mảng. Thủ tục này được cài đặt như sau: public int binarySearch( int array2[].56. // chỉ số của phần tử trung gian // Lặp cho đến khi chỉ số dưới lớn hơn hoặc bằng chỉ số trên while ( low <= high ) { // Xác định chỉ số phần tử giữa middle = ( low + high ) / 2. đã được sắp xếp tăng dần.length . Thay vì phải lập trình.3 Class Arrays Java hỗ trợ một lớp mảng trong thư viện java.7.34.8. gọi là tìm kiếm nhị phân. Giả sử ta cần tìm vị trí của một phần tử có giá trị 7. } return -1. // Không tìm thấy } II. Đối với các mảng đã được sắp xếp.1.Arrays để lập trình viên thao tác trên mảng. Lần phân đôi cuối cùng này cho ta kết quả. Giả sử ta có một mảng: int[] b={1. ta có một phương pháp tìm kiếm hiệu quả hơn.5. // Chỉ số trên int middle. • sort: để sắp xếp mảng. Trước tiên.1. ta so sánh 7 với vị trí đứng giữa của mảng là 34 thì 7 < 34 nên ta chắc chắn nếu có thì 7 sẽ nằm ở nửa trước của mảng.util. // Nếu khóa cần tìm trùng với phần tử giữa thì trả về kết quả ngay if ( key == array[ middle ] ) return middle. Chủ yếu các phương thức của lớp này là static. int key ) { int low = 0. Tiếp tục làm việc này với nửa trước của mảng.100}.8.

length. public class UsingArrays { private int intValues[] = { 1.4. 3. for ( int count = 0. for ( int count = 0. intValuesCopy. 4. Sau đây là ví dụ về sử dụng lớp Arrays: import java. count++ ) System. // Sao chép mảng } // In giá trị của các mảng public void printArrays() { System.print( "\nintValues: " ).print( "\nintValuesCopy: " ). } // Tìm một giá trị trong mảng intValues 71 .print( doubleValues[ count ] + " " ).fill( filledInt. 0. System. for ( int count = 0. // Khởi tạo các mảng public UsingArrays() { filledInt = new int[ 10 ].print( filledInt[ count ] + " " ).3. Arrays. // Sắp xếp mảng doubleValues System. intValues.out. 5. intValuesCopy[]. 7. // Nạp giá trị cho mảng filledInt với giá trị 7 Arrays.sort( doubleValues ).out.9. count++ ) System. for ( int count = 0.out. 6 }. 7 ). count < intValuesCopy. System.print( intValuesCopy[ count ] + " " ).*.• binarySearch: Tìm kiếm nhị phân trên mảng đã được sắp.print( intValues[ count ] + " " ). count < filledInt.out.out. 0. count < doubleValues.2.arraycopy( intValues. private double doubleValues[] = { 8. intValuesCopy = new int[ intValues.util. count++ ) System. count < intValues.length.out.4 }.length ). private int filledInt[].length ]. 9.out.println(). 2. count++ ) System.out. 0.length.length. • equals: So sánh mảng.print( "doubleValues: " ).out. System. System.print( "\nfilledInt: " ). 3.

} // Hàm main public static void main( String args[] ) { UsingArrays usingArrays = new UsingArrays().out.Color. Sau đây là chương trình ví dụ sử dụng ArrayList.println( "intValues " + ( b ? "==" : "!=" ) + " intValuesCopy" ). System. import java.add( Color.println( "intValues " + ( b ? "==" : "!=" ) + " filledInt" ). Về cơ bản thì ArrayList giống với Vector chúng ta đã xem xét ở trên.equals( intValues. "white".searchForInt( 5 ). usingArrays. // Thêm một đối tượng Color 72 . "blue" }.println( ( location >= 0 ? "Tìm thấy 8763 tại " + location : "Không thấy 8763" ) + " trong mảng intValues" ). ArrayList là một lớp tập hợp có thể thay đổi kích thước. value ).println( ( location >= 0 ? "Tìm thấy 5 tại vị trí " + location : "Không thấy" ) + " trong mảng intValues" ). Ở đây ta đặt các đối tượng String và Color vào cùng một ArrayList sau đó xóa đi các phần tử String sử dụng một đối tượng Iterator.out. // Thêm đối tượng cho nó list. b = Arrays. filledInt ). public class CollectionTest { private String colors[] = { "red".out. } // So sánh nội dung mảng public void printEquality() { boolean b = Arrays. // Tạo một ArrayList. int location = usingArrays.magenta ). System.equals( intValues.searchForInt( 8763 ). System.printEquality(). Các lớp tập hợp cài đặt Lists là ArrayList. usingArrays.awt.public int searchForInt( int value ) { return Arrays.out. intValuesCopy ). LinkedList và Vector. import java.printArrays().binarySearch( intValues. thêm các phần tử cho nó public CollectionTest() { ArrayList list = new ArrayList(). }} III Danh sách trong java và giao diện Lists Lists là một chuỗi có thứ tự các phần tử cho phép các phần tử có thể giống nhau. System.*.util. location = usingArrays. Lists là một giao diện kế thừa giao diện Collections nên nó cho phép lập trình viên truy cập các phần tử qua chỉ số.

// Thêm các đối tượng String for ( int count = 0.remove().Xóa sinh viên . Sau đó: . count++ ) System. // Xóa phần tử } // Hàm main public static void main( String args[] ) { new CollectionTest().Tìm kiếm sinh viên . } } Bài tập 1.Sắp xếp n số theo thứ tự tăng dần . count < list.println( "\nArrayList: " ).Thêm sinh viên.Sắp xếp danh sách theo tên 2.size().cyan ).size().hasNext() ) if ( iterator. count < list. // Lặp trong khi tập hợp vẫn còn phần tử while ( iterator.print( list. 73 .length. for ( int count = 0.out.out. count < colors.out. n nhập từ bàn phím. // output list contents System. // Thêm một đối tượng Color // In ra nội dung System. .get( count ) + " " ). Viết chương trình nhập vào n số nguyên và số thực. Viết chương trình quản lý danh sách một lớp học với các chức năng . count++ ) System.add( Color.add( colors[ count ] ).next() instanceof String ) iterator.out.iterator(). list. for ( int count = 0.Nhập vào từ bàn phím 1 số khác và tìm xem số đó có trong số n số vừa nhập không. // Xóa tất cảcác đối tượng String removeStrings( list ). . } public void removeStrings( Collection collection ) { // Khai báo đối tượng iterator iterator iterator = collection. count++ ) list.print( list.Tính tổng của n số này.get( count ) + " " ).println( "\n\nArrayList sau khi gọi removeStrings: " ).

như đọc từ bàn phím. như màn hình.io.out: Dòng xuất chuẩn dùng để hiển thị kết quả trên màn hình. Đối với mội luồng lại có các dòng bao gồm: • Lớp System.io thể hiện qua bảng sau: java. • Lớp System. Khi cần làm việc với luồng. Sự phân cấp các class trong gói java. . FileWriter và rất nhiều lớp khác. • Luồng xuất (output stream): là tất cả những gì được gửi từ máy tính ra ngoài thông qua các thiết bị ngoại vi. Có 2 loại luồng: • Luồng nhập (input stream): là tất cả gì từ thế giới bên ngoài được đưa vào máy tính. ta khai báo khối thư viện: import java... FileOutputStream. Khái niệm luồng vào ra (I/O stream) Luồng là dòng chảy của dữ liệu. I. tệp tin. đọc từ tập tin. Các dòng này có thể bị đổi hướng đến nhiều nguồn khác nhau.in: Dòng nhập chuẩn thường đến từ bàn phím và được dùng để đọc các ký tự dữ liệu.Đề tài 6...Object File FileDescriptor InputStream ByteArrayInputStream FileInputStream FilterInputStream BufferedInputStream DataInputStream PushbackInputStream ObjectInputStream PipedInputStream SequenceInputStream OutputStream ByteArrayOutputStream FileOutputStream FilterOutputStream BufferedOutputStream DataOutputStream PrintStream 74 . FileReader. máy in. • Lớp System. Thư viện này cho phép ta làm việc với các luồng nhập xuất qua việc cung cấp các lớp: FileInputStrem.*.err có thể đưa thông báo lỗi ra một file. Ví dụ System. Các luồng vào ra dữ liệu với file Một khả năng quan trọng mà các ngôn ngữ lập trình phải có là việc quản lý các luồng dữ liệu vào ra hệ thống máy tính giúp các chương trình có thể giao tiếp dữ liệu với thế giới bên ngoài.err: Đây là dòng lỗi chuẩn cho phép một chương trình đưa ra các thông báo lỗi trên màn hình.lang.

Khi một phương thức phải chờ. • markSupported(): Trả về giá trị boolean chỉ ra rằng dòng có hỗ trợ các khả năng mark và reset hay không.int. 75 . Nó gây ra ngoại lệ IOException nếu lỗi xảy ra.ObjectOutputStream PipedOutputStream RandomAccessFile Reader BufferedReader LineNumberReader CharArrayReader FilterReader PushbackReader InputStreamReader FileReader PipedReader StringReader Writer BufferedWriter CharArrayWriter FilterWriter OutputStreamWriter FileWriter PipedWriter PrintWriter StringWriter Sau đây chúng ta xem xét các class quan trọng thường được sử dụng: II. Nó trả về số byte hiện tại có trong dòng. Nó không phải là phương thức tin cậy để thực hiện tiến trình xử lý đầu vào. Nó gây ra ngoại lệ IOException nếu lỗi xảy ra. Nó gây ra ngoại lệ IOException nếu lỗi xảy ra.int): Nó cũng đọc vào một mảng byte. Nó gây ra ngoại lệ IOException nếu có lỗi xảy ra. • close(): Phương thức này đóng dòng. Nếu như không có byte dữ liệu nào. • mark(): Đánh dấu vị trí hiện tại của dòng. Nó trả về true nếu dòng hỗ trợ ngược lại trả về false. • read(byte[]): Trả về số byte đọc được hay ‘-1’ nếu như đã đọc đến cuối dòng. • available(): Phương pháp này trả về số lượng byte có thể đọc được mà không phải chờ. nó phải chờ. các luồng đang thực hiện phải tạm dừng cho đến khi có dữ liệu. • read(byte[]. Nó trả về số byte thực sự đọc được cho đến khi kết thúc dòng. Nó dùng để giải phóng mọi tài nguyên dòng đã sử dụng. • reset(): Phương thức này định vị lại dòng theo vị trí được đánh lần cuối cùng. Luôn luôn đóng dòng để chắc chắn rằng dòng xử lý được kết thúc. Có các phương thức chính sau: • read(): Đọc các byte dữ liệu từ một dòng. Lớp InputStream: Là một lớp trừu tượng định nghĩa cách thức nhận dữ liệu.

• flush(): Phương thức này xả sạch dòng. • FileOutputStream(File f). được dẫn xuất từ lớp cha OutputStream. • FileOutputStream(FileDescriptor fdObj) VI. Dòng phải chờ cho đến khi tác vụ ghi hoàn tất. Lớp này cung cấp các phương thức thiết lập các tập tin và các thư mục. Lớp File Lớp này được sử dụng để truy cập các đối tượng tập tin và thư mục. • write(byte[].• skip(): Phương thức này bỏ qua ‘n’ byte dòng vào. Lớp này có 3 phương thức khởi tạo sau: • FileInputStream(String name): Tham số là tên của tập tin để tạo luồng. ghi và xử lý kết xuất các dòng. Các phương thức bao gồm: • write(int): Phương thức này ghi một byte. Nó được dùng để giải phóng mọi tài nguyên gắn với dòng. Nó gây ra ngoại lệ IOException nếu lỗi xảy ra. Lớp OutputStream Là lớp trừu tượng định nghĩa cách ghi các kết xuất đến dòng. Lớp OutputStream định nghĩa ba dạng khác nhau của phương thức để có thể ghi một byte riêng lẻ. hay một đoạn của một mảng byte. Nó cung cấp một tập các phương thức trợ giúp tạo ra. đối tượng File. int. Như vậy. • FileInputStream(File f): Tham số là đối tượng file để tạo luồng. int): Phương thức này ghi mảng các byte. Nó gây ra ngoại lệ IOException nếu lỗi xảy ra. lớp này cho phép đọc vào từ một tập tin dưới dạng một stream. ’-n’ chỉ định số byte được bỏ qua. Ví dụ: InputStream in = new FileInputStream(“C:\\LETI\\JAVA\\Account. • FileInputStream(FileDescriptor fdObj): Tham số là đối tượng FileDescriptor để tạo luồng. Lớp FileOutputStream Lớp này cung cấp khả năng ghi dữ liệu xuống tập tin. hoặc đối tượng FileDescriptor làm một đối số. Tất cả các thao tác thư mục và tập tin được thực hiện thông qua các phương thức của lớp File. Các tập tin đặt tên theo qui ước đặt tên tập tin của hệ điều hành. ta dùng File trong tất cả các thao tác quản lý file và thư mục. • write(byte[]): Phương thức này phong toả cho đến khi một byte được ghi. Nó kích hoạt IOException nếu lỗi xảy ra. V. một mảng các byte. Lớp FileInputStream Kế thừa từ InputStream. Nó kích hoạt IOException nếu lỗi xảy ra. IV. III. Phương thức này sử dụng để di chuyển tới vị trí đặc biệt bên trong dòng vào. Đệm dữ liệu được ghi ra dòng.txt”). Có 3 cách để tạo các đối tượng từ lớp File: 76 . Có 3 phương thức khởi tạo: • FileOutputStream(String name). Các đối tượng của lớp này được tạo ra nhờ đường dẫn tới file. • close(): Phương thức đóng dòng.

• public String getAbsolutePath(): lấy đường dẫn tuyệt đối của tập tin. • public String getParent(): lấy tên thư mục cha.• File(String path).out.java"). // Kiểm tra sự tồn tại } } 77 . File f = new File(curDir. Chương trình ví dụ: public class Test { public static void main(String args[]) { File f = new File("test"). true nếu xoá thành công."). • public boolean mkdir(): tạo một thư mục từ đối tượng file. • public boolean isHidden(): kiểm tra xem tập tin có ẩn hay không (true nếu có). • public void deleteOnExit(): yêu cầu xoá tập tin khi chương trình chấm dứt. • public String[ ] list(): lấy danh sách các tập tin và thư mục. • File(String path. ví dụ *.java"). hoặc File curDir = new File(". • public boolean canRead(): cho biết tập tin được phép đọc hay không (true nếu có) • public void setReadOnly(): đặt thuộc tính chỉ đọc.4\bin\hello.4\bin". System. String name). • renameTo(File dest): đổi tên tập tin hiện tại sang tên mới. Ví dụ:File f = new File("C:\jdk1. • public long length(): cho biết kích thước tập tin (byte). // Lấy đường dẫn tuyệt đối System. • public boolean canWrite(): cho biết tin có cho phép ghi hay không (true nếu có). • public boolean isDirectory(): cho biết tập tin có phải thư mục hay không (true nếu có). • public void createTempFile(String pattern.getAbsolutePath()). • File(File dir. "Hello. • public String gePath(): lấy đường dẫn của tập tin. File dir): tạo tập tin tạm thời. Các phương thức: • public String getName(): lấy tên đối tượng tập tin. • public String[ ] list(FilenameFilter filter): lấy danh sách tập tin thoả mãn điều kiện lọc. • public String toString(): trả về đường dẫn của tập tin.exists()). • public booean delete(): xoá tập tin.println(f.java"). • public String toURL(): trả về đối tượng URL tương ứng với tập tin.gif. "hello. hoặc File f = new File("C:\jdk1. true nếu thành công.out.println(f. • public Boolean createNewFile(): tạo một tập tin mới. String name). • public boolean isFile(): cho biết tệp tin có hợp lệ hay không (true nếu có).

io.util. Nhờ đó chương trình có thể đọc dữ liệu từ dòng từng byte một mà không ảnh hưởng đến tốc độ thực hiện của hệ thống. Chúng ta có thể lấy dữ liệu từ vùng đệm thay vì quay trở lại nguồn ban đầu của dữ liệu. Bộ lọc nằm giữa một dòng nhập và một dòng xuất. Để thực hiện điều này chúng ta dùng vài tầng lồng nhau. public class SinhVien extends People { private String Lop.2 Lớp FilterOutputStream Lớp này là một dạng bổ trợ cho lớp FilterInputStream. VIII.//Hang so private int ID. Lớp này định nghĩa chồng tất cả các phương thức của OutputStream và không đưa thêm bất kì phương thức mới nào. Nó là lớp cha của tất cả các lớp dòng xuất lọc. Nó là cha của tất cả các lớp dòng nhập lọc. Dữ liệu ghi vào lớp này có thể sửa đổi theo nhu cầu để thực hiện tác vụ lọc và sau đó được chuyển tới đối tượng OutputStream. Vào/ra có sử dụng bộ đệm Vùng đệm là kho lưu trữ dữ liệu. Một dòng có thể được đọc và đưa kết quả cho một dòng khác. một sử dụng kích cỡ vùng đệm ngầm định. VII. VIII. một cho phép chỉ định kích cỡ của vùng đệm xuất. VII.2 Lớp BufferedOutputStream Lớp này định nghĩa hai phương thức thiết lập.VII. Các lớp. Chương trình sau đây đọc và ghi thông tin của đối tượng SinhVien theo một format. Các bộ lọc có thể ghép với nhau khi đó đầu ra của bộ lọc này trở thành đầu vào của bộ lọc kia. Nó thực hiện xử lý một quá trình nào đó trên các byte được truyền từ đầu vào đến đầu ra.*.1 Lớp BufferedInputStream: Lớp này tự động tạo ra và duy trì vùng đệm để hỗ trợ thao tác vào. Java sử dụng cơ chế nhập/xuất có lập vùng đệm để tạm thời lập cache dữ liệu vào/ra của một dòng.// Ma so SinhVien 78 . Nó giúp chương trình đọc/ghi lượng dữ liệu nhỏ không ảnh hưởng lớn đến hiệu năng chung của hệ thống.StringTokenizer. // Diem tong ket public final String mauda ="vang". các dòng nhập xuất lọc của java sẽ giúp ta lọc vào/ra theo một số cách. mỗi sinh viên nằm trên một dòng trong file: // Ke thua lop People import java. VIII. Lớp FilterInputStream được thiết kế sao cho có khả năng kết chuỗi nhiều bộ lọc. import java. Nhập xuất lọc Là một kiểu dòng có được từ việc thay đổi cách xử lý dòng hiện có.// Ten lop private double DiemTongKet.1 Lớp FilterInputStream: Đây là lớp trừu tượng.

"|").nextToken()).Date(). HoVaTen = t. } // Ghi thông tin sinh viên vào file public void GhiData(PrintWriter out) throws IOException { out. DiemTongKet = Double. } // Đọc thông tin 1 sinh viên từ bộ đệm đọc public void DocData(BufferedReader in) throws IOException { String s = in.ht).getYear() .println(this. } // Khai bao chong phuong thuc toString() public String toString() { return String.util. MaSo = Integer. NamSinh = Integer.String l.MaSo=1. // Đọc một dòng trong bộ đệm StringTokenizer t = new StringTokenizer(s.nextToken()). return (homnay.Date homnay = new java.NamSinh +1).//goi constructor cua lop cha la People Lop = l.readLine().String ht.protected static int MaSo.valueOf(this. // bien doi tuong Vector lưu các sinh viên 79 .parseInt(t.double dtk) { super(ns.util. // Tang ma so len 1 den gan cho SinhVien sau MaSo+=1. sinh vien dau tien co ma so 1 SinhVien. } // Ham main public static void main(String[] argv) { // Dat gia trị bien static.toString()). } // Phuong thuc tinh tuoi protected int TinhTuoi() { java. // Id cua SinhVien duoc gan bang gia tri MaSo hien thoi cua lop ID=MaSo.nextToken()).valueOf(DiemTongKet)+"|" + HoVaTen.parseInt(t.nextToken(). DiemTongKet=dtk.valueOf(ID)+ "|" + String.parseDouble(t.TinhTuoi()) + "|" + String.// ma so chung de cap phat cho moi sinh vien public SinhVien(int ns.

Vector sv = new java.addElement(k4). } out. while (enu."Tran Thi Mai 2".i++) System.9).util. try { PrintWriter out = new PrintWriter(new FileWriter("C:\\LETI\\JAVA\\Sinhvien. SinhVien k3 = new SinhVien(82.dat")).8).util. Trong lớp này. g.addElement(k1)."Letio3". sv.i++) { svs[i] = new SinhVien(0. Lớp RandomAccessFile Lớp RandomAccessFile cung cấp khả năng thực hiện vào/ra theo một vị trí cụ thể bên trong một tập tin."". SinhVien k4= new SinhVien(83.0."Letio3".hasMoreElements()) { // Ep kieu. try { BufferedReader in = new BufferedReader(new FileReader("C:\\LETI\\JAVA\\Sinhvien."Nguyen Thi Mai 1".6).length. SinhVien k5= new SinhVien(84. } catch(Exception ep) {} // Doc tu file ra SinhVien[] svs = new SinhVien[5].DocData(in). }} IX.java.addElement(k5).length."Letio3". } } catch(IOException ep) {} for(int i=0.addElement(k3).0).""."Pham Thi Mai 3". sv.i<svs.nextElement()."Letio3". for(int i=0.util.elements(). sv.Enumeration enu = sv.5).i<svs.out. sv. sv."Letio3".println(svs[i].dat")). svs[i]. SinhVien k1 = new SinhVien(80. 80 . dữ liệu có thể đọc hoặc ghi ở vị trí ngẫu nhiên thay vì liên tục."Phan Thi Mai 4". // Dung interface Enumeration de duyet cac phan tu cua Vector java."Hoang Thi Mai 5".toString()).GhiData(out).close().Vector(5).7). // Them sinh vien vao Vector SinhVien k2 = new SinhVien(81. kieu Object la kieu cha cua moi kieu nen luon ep duoc SinhVien g = (SinhVien)enu.addElement(k2).

• RandomAccessFile(File f. String mode). • getFilePointer( ): Trả về vị trí hiện hành của con trỏ tập tin. lập trình viên phải đảm bảo rằng mọi biến của lớp phải có kiểu Serializable hoặc phải khai báo một biến là transient để bỏ qua trong quá trình tuần tự hóa. Trong các ứng dụng quản lý ta thường xuyên phải đọc và ghi dữ liệu về các đối tượng lên ổ cứng. có thể thực hiện I/O bằng các kiểu dữ liệu nguyên thuỷ. lớp đó phải khai báo cài đặt giao diện Serializable. Trong một lớp cài đặt Serializable.txt”. Đối tượng System. "r"). điều này cho phép đọc tập tin theo chế độ chỉ đọc hoặc đọc-ghi. Các lớp ObjectInputStream và ObjectOutputStream cho phép chúng ta đọc và ghi đối tượng vào file. private double balance.chế độ chỉ đọc. Để cho phép một đối tượng của một lớp có thể sử dụng với ObjectInputStrems và ObjectOutputStreams. XI. Các phương thức mới thêm vào bao gồm: • seek( ): Thiết lập con trỏ tập tin tới vị trí cụ thể bên trong tập tin. Giao diện Serializable được biết đến như là một giao diện “đính kèm” bởi vì bản thân nó không chứa bất kỳ một phương thức nào. mode = "rw" . Đối tượng thuộc lớp RandomAccessFile có thể được khởi tạo theo hai cách: • RandomAccessFile(String name. ta có thể sử dụng phương thức read() hoặc kết nối với một luồng trung gian khác.io. private String lastName. public class AccountRecord implements Serializable { private int account.Serializable. Do vậy. • length( ): Trả về chiều dài của tập tin tính theo byte. String mode). // Chỉ số nắm giữ hàng hóa và dịch vụ của khách hàng. Sau đây là một ví dụ về xây dựng một lớp đối tượng khách hàng cho một ứng dụng ngân hàng sau đó ghi chúng vào file: import java. tất cả đều là đối tượng. Truy cập file ở chế độ tuần tự Khi làm việc với Java. Một class cài đặt giao diện này được gán một thông báo rằng đối tượng của lớp là một đối tượng Serializable. Nó giúp ta đọc các ký tự được người dùng gõ vào từ bàn phím. Lớp này cũng hỗ trợ các quyền cơ bản về đọc hoặc ghi tập tin. Mặc định thì tất cả các kiểu dữ liệu nguyên thủy đều là tuần tự hóa. phải kiểm tra xem định nghĩa của lớp (hoặc lớp cha) có cài đặt Serializable hay không. X.chế độ ghi và đọc. Với các kiểu không nguyên thủy. Trong đó mode là chế độ mở tập tin: mode = "r" .Lớp RandomAccessFile thực hiện cả hai việc nhập và xuất. private String firstName. số dư tài 81 . Ví dụ: RandomAccessFile file = new RandomAccessFile(“C:\\LETI\\JAVA\\Account. Điều này rất quan trọng bởi vì một đối tượng ObjectOutputStream sẽ không xuất một đối tượng trừ khi đó là một đối tượng Serializable. Lớp này hỗ trợ một số phương thức mới khác với phương thức đã thừa kế từ các lớp DataInput và DataOutput.in Là một đối tượng đặc biệt được tạo ra từ lớp InputStream.

} public void setFirstName( String first ) // Ðặt giá trị cho phần họ đệm { firstName = first. } public String getLastName()// Lấy tên { return lastName. } public void setLastName( String last ) // Ðặt giá trị cho tên { lastName = last. double bal ) // Constructor có tham số { setAccount( acct ). setFirstName( first ). } public void setBalance( double bal ) // Đặt giá trị cho balance { balance = bal. } public int getAccount()// Lấy số tài khoản { return account. "". setLastName( last ). } } 82 .khoản public AccountRecord()// constructor không tham số { this( 0. setBalance( bal ). 0. } public String getFirstName()// Lấy phần họ đệm { return firstName. String last. } public AccountRecord( int acct. String first. } public double getBalance()// Lấy số dư { return balance. "".0 ). } public void setAccount( int acct ) // Ðặt số tài khoản { account = acct.

} } // Hàm main public static void main(String[] argvs) { AccountRecord record1= new AccountRecord( 12345.out. } catch ( IOException ioException ) { System. } } public void closeFile() // Phương thức đóng file { try { output.txt") ).flush(). g.print("Loi mo file")."Nguyen Van ". output. AccountRecord record2= new AccountRecord( 12346. System.openFile().print("Loi ghi file").5. GhiFile g = new GhiFile().exit( 1 ).txt import java. public class GhiFile { ObjectOutputStream output. 83 .-5.io.12).12)."Phan Tien ".writeObject( record ).*.exit( 0 ). } catch(IOException ex) { System.close().Chương trình sau đây sẽ ghi các đối tượng vào file C:\LETI\JAVA\Account. public void openFile() { try { output = new ObjectOutputStream(new FileOutputStream( "C:\\LETI\\JAVA\\Account."Hai". } } public void addRecord(AccountRecord record) // Phương thưc thêm 1 bản ghi vào file { try { output.out. } // Nếu có lỗi đóng file catch ( IOException ioException ) { System."Minh".

io. account =String.addRecord(record1).closeFile(). System. } catch ( IOException ioException ) { System.close(). } catch(Exception p){} finally {return account. }} Chương trình sau đây đọc ra 2 bản ghi vừa được ghi ở chương trình trên và in ra màn hình: import java.exit( 0 ). g.addRecord(record2).getFirstName() + "\n " + a.} 84 .g.print("Loi mo file"). } } // Phương thức đọc 1 bản ghi public String readFile() { String account="". public class DocFile { java. try { AccountRecord a = (AccountRecord)input.valueOf( a.valueOf( a.ObjectInputStream input. } catch(IOException e) { System.getLastName() + "\n " + String.*.io.exit( 1 ). g.txt")).ObjectInputStream(new FileInputStream("C:\\LETI\\JAVA\\Account.getAccount() ) + "\n " + a.io.getBalance()). } } public void closeFile() //Đóng file { try { input.out.readObject(). public void openFile() // Mở file { try { input = new java.

// Đọc các byte ra một mảng byte out.println(d.close().io. d. out.read(data).} public static void main(String[] argvs) { DocFile d = new DocFile(). • DataInputStream: Hỗ trợ đọc file ở chế độ nhị phân.write(data).readFile()). out = new java. } catch (Exception ex) {} }} 85 .doc: import java. d.doc")).out. // Luồng vào hỗ trợ đọc file nhị phân try { in = new java. Chương trình sau đây copy dữ liệu giữa hai file dạng .out. public class BinaryAccess { public static void main(String[] argvs) { java.close(). System. // Ghi mảng byte này vào một file khác } in. in.println(d. int bytesAvailable = in.available().DataInputStream in.readFile()).closeFile(). System. // Luồng ra hỗ trợ ghi file nhị phân java.DataOutputStream(new FileOutputStream("C:\\G.io.doc")). Truy cập file nhị phân Ngoài các công cụ thao tác trên file văn bản.io.openFile().DataInputStream(new FileInputStream("C:\\P.io. // số byte của file if (bytesAvailable > 0) { byte[] data = new byte[bytesAvailable]. }} XII. Tất nhiên là các file văn bản cũng có thể đọc ghi ở chế độ nhị phân. Java hỗ trợ cả các thao tác với file nhị phân dùng các đối tượng: • DataOutputStream: Hỗ trợ ghi file ở chế độ nhị phân tức là từng byte.io.*.DataOutputStream out.

Phan Anh Thu. Cho một file có dữ liệu về thí sinh thi hoa hậu như sau: 001. 1. 2. Viết chương trình copy dữ liệu từ một file ảnh GIF sang một file ảnh GIF khác. Bùi Thị Thanh Nhàn. Ha Tay 002. Họ và tên. Viết một chương trình copy dữ liệu từ một file văn bản sang một file văn bản khác. 3. Ha Nam 009. Ha Noi 003. Viết một chương trình nhập vào một chuỗi từ bàn phím sau đó ghi chuỗi ra file. Thanh Hoa Các dữ liệu lần lượt mô tả về: Mã số.70.78. 86 . 1. chiều cao.Bài tập 1. Quê quán. 1. Tran Thi Mong Mo. 4.89. Viết một chương trình đọc dữ liệu của file ra và gán mỗi dòng cho một đối tượng HOAHAU. 1.98. Nguyen Thu Thuy.

• Ghi lại các dữ liệu hiện thời và kết thúc chương trình.Đề tài 7. đưa vào các xử lý ngoại lệ để xử lý theo một cách riêng thống nhất. ném”(throws) ra một Exception. Java cho phép người lập trình quản lý các lỗi theo cách khi nó xảy ra. Cú pháp để thực hiện điều này như sau: try { // Đoạn chương trình có thể gây ra exception } catch (<Kiểu exception> <tên biến>) { // Đoạn code chạy khi exception xảy ra } finally { // Đoạn code luôn được thực hiện bất kể exception có xảy ra hay không } Một khối try có thể không có hoặc có nhiều khối catch. Khi lỗi xảy ra. chúng ta gọi đó là một ngoại lệ (exception) – những điều xảy ra khác thường. • Xử lý các ngoại lệ từ một thành phần chương trình chưa được quản lý ngoại lệ • Trong các dự án lớn. try{ 87 . gọi là exception handling. lỗi có thể xảy ra với rất nhiều lý do. • Lỗi thiết bị. I. Cơ sở quản lý ngoại lệ trong Java Khi một phương thức không thể hoàn thành nhiệm vụ của nó. chương trình sẽ thực hiện những việc do chính lập trình viên đặt ra. Xử lý ngoại lệ Khi viết một chương trình nói chung và trong Java nói riêng. • Lỗi phần cứng như thiếu ổ cứng hay bộ nhớ. nếu có một Exception handler . Trong một đoạn chương trình mà lập trình viên không thể biết trước được liệu có chuyện gì xảy ra làm cho đoạn chương trình đó gây ra lỗi hay không. người sử dụng chương trình muốn rằng chương trình có thể: • Quay lại trạng thái an toàn trước đó và cho phép người dùng thực hiện các công việc khác. Tuy nhiên điều này là rất khó khăn bởi lỗi có thể đến do một trong các nguyên nhân: • Người dùng nhập dữ liệu sai. Các tình huống sử dụng ngoại lệ Việc quản lý các ngoại lệ nên được sử dụng khi: • Một phương thức không thể hoàn thành nhiệm vụ của nó vì một lý do rằng nó không thể điều khiển được mọi chuyện.đoạn code xử lý khi lỗi xảy ra – thì Exception này sẽ bị “bắt” (catch) và “được quản lý”(handled). II. Mỗi khối catch xác định một kiểu exception mà nó có thể bắt và chứa đoạn code xử lý trong trường hợp tương ứng. nó có thể “quăng.

Mỗi khối try bắt buộc phải có một khối catch hoặc finally. Khi lỗi xảy ra.. Để lấy được thông báo từ hệ thống về lỗi.//code có thể throw exceptions } catch (MalformedURLException e1) { //code xử lý } catch (UnknownHostException e2) { //code xử lý } catch (IOException e3) { //code xử lý } Sau khối catch cuối cùng. Cấu trúc cây kế thừa các xử lý ngoại lệ Trong Java có hàng trăm lớp ngoại lệ để “bắt” các lỗi tương ứng như lỗi vào/ra file. có thể có hoặc không một khối finally chứa code xử lý bất kể exception có xảy ra hay không. sử dụng phương thức getMessage() của các lớp Exception. Trong một phương thức ta có thể khai báo một mệnh đề throws để phương thức “quăng” ra các ngoại lệ. ExceptionType2. { // Thân phương thức } III. Java sử dụng cơ chế kết thúc chương trình thay vì cơ chế quay trở lại điểm xảy ra ngoại lệ và tiếp tục.. ví dụ: e3. ExceptionType3. lỗi truy cập CSDL SQL.getMessage(). chương trình sẽ tìm đến khối catch có kiểu đối tượng Exception phù hợp để thực hiện. Các ngoại lệ này được quăng ra bởi các lệnh throw hoặc việc gọi một phương thức khác trong phương thức này. Tại điểm quăng ra ngoại lệ (throw point). Ví dụ: int functionName( parameterList ) throws ExceptionType1.…Các ngoại lệ trong Java đều kế thừa từ lớp Throwable theo cấu trúc như sau: 88 .

Cơ chế bảo mật không cho phép thực hiện. IV. tuy nhiên rất có thể file không tồn tại hoặc là một file rỗng và không có gì để đọc. Phương thức yêu cầu không tồn tại. Việc chuyển đối từ chuỗi sang số thực không thành công.lang Lỗi về số học. 89 . chương trình sẽ tìm tới vị trí định nghĩa exception handler để quản lý lỗi này. ví dụ như ‘chia cho 0’. chẳng hạn như FileInputStream.Danh sách các ngoại lệ thường dùng trong Java Ngoại lệ RuntimeException ArthmeticException IllegalAccessException IllegalArgumentException ArrayIndexOutOfBoundsExeption NullPointerException SecurityException ClassNotFoundException NumberFormatException AWTException IOException FileNotFoundException EOFException NoSuchMethodException InterruptedException Ý nghĩa Lớp cơ sở cho nhiều ngoại lệ java. Trong phần này chúng ta sẽ xem cách sử dụng ngoại lệ để quản lý các tình huống có thể kiểm soát được. Đối số không hợp lệ. Một vấn đề là lập trình viên không biết throws ra ngoại lệ nào hoặc không thể khai báo hết tất cả các ngoại lệ. có 4 tình huống để đưa ra ngoại lệ: • Khi gọi một phương thức có throw một ngoại lệ. Các ngoại lệ dạng này được khai báo ở phần đầu các phương thức. Lớp không thể truy cập. Sử dụng ngoại lệ được kiểm soát Trong phần trên đã bàn về cách sử dụng các exception để bắt các lỗi không được kiểm soát. Khi truy cập đối tượng null. Khi gặp lỗi như vậy. Không thể nạp lớp yêu cầu. • Khi ta xác định được một lỗi và throws một exception bằng một lệnh throw. Tuy nhiên. Ngoại lệ về AWT Lớp cha của các lớp ngoại lệ I/O Không thể định vị tập tin Kết thúc một tập tin. Ví dụ trong phương thức khởi tạo sau: public FileInputStream(String name) throws FileNotFoundException Ở đây phương thức nhận một tham số kiểu String như là tên file. Khi một luồng bị ngắt. Lỗi tràn mảng.

• V. } } Đối với các ngoại lệ dạng RuntimeException... 90 . MalformedURLException { . Ví dụ: class MyAnimation { . Ví dụ: class FileFormatException extends IOException { public FileFormatException() {} public FileFormatException(String gripe) { super(gripe). void drawImage(int i) throws ArrayIndexOutOfBoundsException // Không phù hợp { . } } Phương thức có thể throws nhiều ngoại lệ nếu cần: class MyAnimation { . public Image loadImage(String s) throws EOFException. nếu chúng ta có kế hoạch để khai báo nó thì tốt nhất là tìm cách để khắc phục không cho chúng xảy ra..Khi viết một chương trình bị lỗi.. • Khi một lỗi bên trong hệ thống như trong JVM hoặc các thư viện động. Đối với các ngoại lệ không được kiểm soát... Một phương thức cần khai báo ngoại lệ phù hợp: class MyAnimation { . Các class ngoại lệ này được kế thừa từ lớp Exception hoặc lớp con của nó như IOException chẳng hạn... sẽ dẫn đến việc kích hoạt một ngoại lệ. đó là các ngoại lệ kế thừa từ lớp Error vì chúng vượt khỏi tầm kiểm soát của chúng ta. chẳng hạn a[-1] = 0. Xây dựng một ngoại lệ Chúng ta có thể tự xây dựng một ngoại lệ để throws trong những trường hợp cụ thể... public Image loadImage(String s) throws IOException { .. chúng kế thừa từ lớp RuntimeException cũng vậy. ta không nên khai báo chúng.. } } Các ngoại lệ bắt lỗi nội bộ của Java thường không nên được khai báo. chẳng hạn ở đây là ArrayIndexOutOfBoundsException.

Bài tập 1. Viết chương trình đọc một file trên ổ đĩa và in ra màn hình.. 2. Viết chương trình nhập một số nguyên từ bàn phím. Chú ý dùng các ngoại lệ để kiểm soát tất cả các tình huống có thể. . } . .} } Sau đó. Bắt ngoại lệ khi người dùng nhập vào ký tự hoặc số thực có phần thập phân. } return s.. ta có thể sử dụng ngoại lệ này trong chương trình: String readData(BufferedReader in) throws FileFormatException { . 3.. } VI. 91 .. Khai báo một lớp ngoại lệ để kiểm soát tình huống điểm một sinh viên vượt quá 10 hay tuổi của sinh viên vượt quá 100 trong ứng dụng quản lý sinh viên ở đề tài “Lập trình hướng đối tượng trong Java”.) { if (ch = = -1) // Điểm cuối file { if (n < len) throw new FileFormatException(). while (.

Môi trường điều hành sẽ gửi các sự kiện này tới chương trình đang chạy. chẳng hạn như ActionEvent và WindowEvent. Xử lý các sự kiện trong Java I. Trong Java sử dụng một cách tiếp cận dựa trên các khái niệm: .Các bộ lắng nghe sự kiện (event listener). Khái niệm và cơ sở xử lý sự kiện Bất kỳ chương trình có giao diện đồ họa nào thường hỗ trợ việc kích hoạt các sự kiện từ con chuột hoặc bàn phím.Các nguồn của sự kiện (event source). Các nguồn sự kiện chính là các đối tượng điều khiển. . Tất cả các lớp event đều dẫn xuất từ lớp java. Sau đây là cây phân cấp chỉ sự kế thừa giữa các lớp sự kiện trong Java: 92 . Đối với một ngôn ngữ OOP như Java thì toàn bộ thông tin về sự kiện được đóng gói trong một lớp event. Khi một sự kiện xảy ra đối với một nguồn sự kiện. nó sẽ gửi thông báo này tới tất cả các bộ lắng nghe sự kiện được đăng ký cho sự kiện đó. Mỗi loại sự kiện tương ứng với một lớp dẫn xuất.util.EventObject. Lập trình viên được hoàn toàn quyết định điều gì sẽ xảy ra khi các sự kiện này được kích hoạt.Đề tài 8. chúng có các phương thức để lập trình viên đăng ký các bộ lắng nghe cho chúng.

Một nguồn sự kiện là một đối tượng mà có thể đăng ký các đối tượng lắng nghe và gửi cho chúng các đối tượng sự kiện..addActionListener(listener). v. Một đối tượng lắng nghe là một biểu hiện của một lớp có cài đặt giao diện lắng nghe sự kiện 2. // Nguồn sự kiện button. Đối tượng này có cài đặt một phương thức để xử lý sự kiện là actionPerformed.. Ví dụ một button (nút bấm) thì phát sinh sự kiện ActionEvent trong khi một cửa sổ lại phát sinh sự kiện WindowEvent. Đối tượng lắng nghe sẽ sử dụng thông tin trong các đối tượng sự kiện để phản ứng với các sự kiện đó. một sự kiện được quản lý dựa trên các khái niệm: 1. khi đó sự kiện cũng được gửi tới tất cả các bộ lắng nghe và tới phương thức actionPerformed của chúng.Các giao diện lắng nghe sự kiện bao gồm: AdjustmentListener MouseWheelListener FocusListener WindowListener ItemListener WindowFocusListener KeyListener WindowStateListener MouseListener Các nguồn sự kiện khác nhau có thể phát sinh các sự kiện khác nhau.v. Sơ đồ sequence cho đoạn code trên như sau: 93 .. Tóm lại.. Nguồn sự kiện gửi đối tượng sự kiện tới tất cả các đối tượng lắng nghe được đăng ký cho sự kiện đó. } } Bất cứ khi nào người dùng click chuột vào đối tượng JButton trên màn hình. Trong giao diện này có khai báo một phương thức actionPerformed để nhận về một sự kiện ActionEvent: class MyListener implements ActionListener { . vấn đề còn lại là đối tượng lắng nghe sự kiện phải có một phương thức để nhận về sự kiện từ nguồn sự kiện đăng ký nó và xử lý.add<sự kiện>Listener(<đối tượng lắng nghe sự kiện>) Ví dụ: ActionListener listener = . đối tượng listener phải thuộc một lớp có cài đặt giao diện ActionListener.. 3. .. // đối tượng lắng nghe JButton button = new JButton("Ok"). Cú pháp để đăng ký các đối tượng lắng nghe cho các nguồn sự kiện theo cú pháp sau: <nguồn sự kiện>. Có thể có nhiều bộ lắng nghe được đăng ký cho một nguồn sự kiện. một sự kiện ActionEvent được phát sinh và gửi cho đối tượng lắng nghe listener. Ở đây. . Mỗi loại sự kiện cũng có giao diện lắng nghe tương ứng. // đăng ký đối tượng lắng nghe sự kiện Trong đoạn code trên..Các sự kiện trên được gửi cho các đối tượng lắng nghe tương ứng như: ActionListener MouseMotionListener. 4. public void actionPerformed(ActionEvent event) { // Đoạn mã xử ký sự kiện đặt ở đây . lấy đối số là đối tượng ActionEvent nhận được.

gif")). add(blueButton). JButton blueButton = new JButton(new ImageIcon("blue-ball.Sau đây là một ví dụ về xử lý sự kiện click cho 3 đối tượng Jbutton: Một Button được tạo ra như sau bằng cách gọi constructor của JButton với một chuỗi nhãn hoặc một ảnh hay cả hai: JButton yellowButton = new JButton("Yellow"). } } 94 . add(yellowButton). JButton redButton = new JButton("Red"). add(redButton). Thêm 3 Button vào 1 panel như sau: Class ButtonPanel extends JPanel { public ButtonPanel() { JButton yellowButton = new JButton("Yellow"). JButton blueButton = new JButton("Blue").

} Mỗi đối tượng Button được đăng ký cho bộ lắng nghe này: Class ButtonPanel extends JPanel { public ButtonPanel() { JButton yellowButton = new JButton("Yellow"). JButton blueButton = new JButton("Blue"). Class ButtonPanel extends JPanel { public ButtonPanel() { JButton yellowButton = new JButton("Yellow"). 95 .Red). add(blueButton). // Thay đổi màu nền của panel khi Button được click } private Color backgroundColor. ColorAction yellowAction = new ColorAction(Color. add(redButton). redButton. Giải pháp ở đây là đưa lớp ColorAction thành lớp nội của lớp ButtonPanel. ColorAction blueAction = new ColorAction(Color. JButton blueButton = new JButton("Blue"). JButton redButton = new JButton("Red"). } } Một vấn đề đặt ra là phương thức setBackground() không được định nghĩa trong lớp ColorAction mà chỉ được định nghĩa cho lớp Panel. khi đó trong lớp ColorAction.addActionListener(redAction). } public void actionPerformed(ActionEvent e) { setBackground(backgroundColor). ta có thể truy cập các phương thức của lớp Panel (được ButtonPanel kế thừa) như setBackground chẳng hạn.Bây giờ chúng ta định nghĩacác bộ lắng nghe cho các Button này gọi là ColorAction như sau: public class ColorAction implements ActionListener { public ColorAction(Color c) { backgroundColor =c. yellowButton.addActionListener(yellowAction). add(yellowButton).addActionListener(blueAction).Blue). blueButton.Yellow). ColorAction redAction = new ColorAction(Color.

} public void actionPerformed(ActionEvent e) { setBackground(backgroundColor).Yellow).JButton redButton = new JButton("Red"). ColorAction yellowAction = new ColorAction(Color. } public static void main(String[] argvs) { testPanel p = new testPanel(). // Thay đổi màu nền của panel khi Button được click } private Color backgroundColor. } } 96 .addActionListener(redAction). // Đăng ký bộ lắng nghe sự kiện blueButton.add(pn). yellowButton.setSize(300. this. add(redButton).addActionListener(yellowAction). ColorAction blueAction = new ColorAction(Color. } } Chương trình sau đây kiểm tra sự thực hiện đáp ứng các sự kiện vừa thiết kế ở trên: import javax. redButton. add(blueButton).swing.setVisible(true).Red). } private class ColorAction implements ActionListener { public ColorAction(Color c) { backgroundColor =c. add(yellowButton). public class testPanel extends JFrame { public testPanel() { ButtonPanel pn = new ButtonPanel().JFrame.addActionListener(blueAction). p. ColorAction redAction = new ColorAction(Color. p.400).Blue).

lớp chứa các nguồn sự kiện phải cài đặt giao diện ActionListener. Truy cập thông tin sự kiện Một phương pháp khác để lập trình sự kiện đó là gán cho tất cả các đối tượng nguồn sự kiện chung một đối tượng lắng nghe. redButton. Các đối tượng Button bây giờ cũng phải khai báo là biến thành phần của lớp vì 97 .getSource()==redButton) setBackground(Color. JButton blueButton. Làm như vậy ta không cần thiết kế riêng một lớp ColorAction. Muốn vậy.*. yellowButton. các lớp lắng nghe sự kiện có thể được cài đặt ngay trong phương thức addActionListener như sau: yellowButton.addActionListener(this). Tùy theo thông tin về sự kiện nhận được. blueButton = new JButton("Blue").BLUE). phương thức actionPerformed sẽ có sự hành xử khác nhau.RED). import java. if (event. JButton redButton.addActionListener(this). blueButton. import javax.Thông thường.*. add(redButton). add(blueButton). khi đăng ký đối tượng lắng nghe cho các Button. } public void actionPerformed(ActionEvent event) { if (event. redButton = new JButton("Red").swing. } }).awt.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { setBackground(Color.YELLOW). II. bản thân lớp component ButtonPanel đóng vai trò là lớp lắng nghe sự kiện vì nó có cài đặt giao diện ActionListener. if (event.YELLOW).getSource()==yellowButton) setBackground(Color. public ButtonPanel() { yellowButton = new JButton("Yellow"). add(yellowButton). } } Trong ví dụ trên. Do đó. ta chỉ việc sử dụng biến this.addActionListener(this).event. public class ButtonPanel extends JPanel implements ActionListener { JButton yellowButton.getSource()==blueButton) setBackground(Color. đại diện cho đối tượng ngầm định của chính lớp ButtonPanel.

void windowActivated(WindowEvent e). ta cũng qua các bước căn bản sau: WindowListener listener = new . là đối tượng nguồn sự kiện phát sinh các sự kiện WindowEvent. Phần này ta sẽ xem xét các sự kiện xảy ra đối với bản thân một window. ta chỉ viết code cho phương thức nào ta xử lý mà thôi.chúng được truy cập trong 2 phương thức khác nhau. Đối tượng listener bắt buộc phải thuộc một lớp có cài đặt giao diện WindowListener.exit(0)..addWindowListener(listener).. void windowIconified(WindowEvent e). } public void windowOpened(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} } IV. Giải pháp ở đây sẽ là định nghĩa một lớp trung gian. có những phương thức không xử lý gì cả làm cho chương trình không được tối ưu. Trong đó frame là một đối tượng của lớp JFrame. void windowDeactivated(WindowEvent e).. Tuy nhiên phương pháp này sẽ trở nên khó dùng khi trên panel có nhiều đối tượng nguồn sự kiện. void windowClosing(WindowEvent e). III. Tuy nhiên. } Do đó các lớp cài đặt giao diện này phải khai báo định nghĩa tất cả các phương thức trên. ví dụ: class Terminator implements WindowListener { public void windowClosing(WindowEvent e) { System. // thu nhỏ của sổ void windowDeiconified(WindowEvent e). khai báo cài đặt giao diện WindowListener với đầy đủ 7 phương thức nhưng các phương thức này cũng không làm gì cả. Các lớp muốn cài đặt nội dung cho một sự kiện chỉ việc khai báo kế thừa lớp này và định nghĩa chồng phương thức cần thiết. Cấu trúc của giao diện này như sau: public interface WindowListener { void windowOpened(WindowEvent e). Các lớp thích nghi Ta thấy rằng việc khai báo đầy đủ 7 phương thức. Xử lý các sự kiện trên window Phần trên đã cho thấy cách thức chúng ta làm việc với các nguồn sự kiện là các đối tượng nằm trong một window.. frame. Các lớp có vai trò trung gian như vậy 98 . Muốn bắt các sự kiện của window. void windowClosed(WindowEvent e).

Ta có thể định nghĩa chồng nhiều hơn một phương thức của WindowAdapter. MouseListener có MouseAdapter. Tạo ra một đối tượng của lớp đó. 2. Thêm 2 phương thức windowClosing và windowIconified cho lớp nặc danh đó. Kế thừa 5 phương thức còn lại từ WindowAdapter. Để kết thúc đề tài này ta liệt kê các phương thức xử lý cho các loại sự kiện như bảng sau: Interface ActionListener Methods actionPerformed Parameter/Accessors ActionEvent • Nguồn sự kiện AbstractButton JComboBox JTextField Timer getActionCommand 99 . Lúc này. Định nghĩa một class nặc danh kế thừa lớp WindowAdapter.exit(0). Đoạn code này thực hiện các công việc sau: 1. ta có một lớp thích nghi tương ứng.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { System. Với mỗi giao diện lắng nghe. 4. Các lớp thích nghi thường dùng là: FocusAdapter MouseMotionAdapter KeyAdapter WindowAdapter MouseAdapter class Terminator extends WindowAdapter { public void windowClosing(WindowEvent e) { System. sau đó đăng ký lắng nghe sự kiện cho frame mà không cần một đối tượng có tên rõ ràng của Terminator: frame. Gửi đối tượng này cho phương thức addWindowListener.addWindowListener(new Terminator()).exit(0). 3. } public void windowIconified(WindowEvent e) {System. Một cách làm khác là khai báo một lớp (thường là lớp nội) dạng như class Terminator ở trên. đối tượng cũng không có tên. Tất nhiên là không phải khi nào ta cũng phải sử dụng lớp nội nặc danh. 5. Ví dụ: WindowListener có lớp thích nghi WindowAdapter.gọi là các lớp thích nghi. kỹ thuật định nghĩa lớp nội nặc danh được phát huy: frame.} } ). } } Vấn đề là các lớp window thường phải khai báo kế thừa từ JFrame rồi nên không thể khai báo kế thừa thêm lớp WindowAdapter.exit(0).

Interface

Methods

Parameter/Accessors

Nguồn sự kiện

getModifiers

AdjustmentListener

adjustmentvalueChanged AdjustmentEvent
• • •

JScrollbar

getAdjustable getAdjustmentType getValue AbstractButton JComboBox

ItemListener

ItemstateChanged

ItemEvent
• • •

getItem getItemSelectable getStateChange Component

FocusListener

FocusGained focusLost keyPressed keyReleased keyTyped

FocusEvent

isTemporary Component

KeyListener

KeyEvent
• • • • •

getKeyChar getKeyCode getKeyModifiersText getKeyText isActionKey Component

MouseListener

mousePressed mouseReleased mouseEntered mouseExited mouseClicked

MouseEvent
• • • • •

getClickCount getX getY getPoint TRanslatePoint Component

MouseMotionListener

mouseDragged mouseMoved mousewheelMoved

MouseEvent

MouseWheelListener

MouseWheelEvent

Component

100

Interface

Methods

Parameter/Accessors
• •

Nguồn sự kiện

getWheelRotation getScrollAmount Window

WindowListener

windowClosing windowOpened windowIconified windowDeiconified windowClosed windowActivated windowDeactivated

WindowEvent

getWindow

WindowFocusListener windowGainedfocus windowlostFocus WindowStateListener WindowStateChanged

WindowEvent

Window

getOppositeWindow Window

WindowEvent
• •

getOldState getNewState

V. Xử lý các sự kiện chuột
Các sự kiện với chuột được xử lý bởi giao diện MouseListener. Khi một nguồn sự kiện được kích hoạt bởi việc click chuột, các phương thức xử lý cho các sự kiện tương ứng được liệt kê trong bảng trên, đặc biệt hay dùng là mouseClicked(). Thông thương ta cũng không cài đặt xử lý cho tất cả các sự kiện này nên ta không cài đặt giao diện MouseListener mà khai báo một lớp nội nặc danh kế thừa từ lớp thích nghi MouseAdapter. Giả sử có một đối tượng JFrame tên là frame, sau đây là một ví dụ quản lý sự kiện click chuột trên nó: frame. addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent e) // Mac dinh la chuot trai { // Kiem tra neu la chuot phai duoc click if( (e.getModifiers() & InputEvent.BUTTON3_MASK)== InputEvent.BUTTON3_MASK) // hien thi mot popup menu tai vi tri click jp.show(getContentPane(),e.getX(),e.getY()); } } ); Tham khảo thêm tại: http://java.sun.com/docs/books/tutorial/uiswing/events/handling.html và http://java.sun.com/docs/books/tutorial/uiswing/events/mouselistener.html

101

Bài tập
1. Viết chương trình xử lý sự kiện chuột click trên các Botton, nếu là chuột trái thì thông báo là “Bạn vừa click chuột trai”, nếu là chuột phải thì thông báo “Bạn vừa click chuột phải”. 2. Viết chương trình sau khi chọn một Button trên màn hình, nhấn phím x thì chương trình kết thúc.

102

Đề tài 9. Applet
Applet là một trong những kỹ thuật vượt trội của Java so với các ngôn ngữ khác. Một Applet là một chương trình Java được nhúng vào trong các trang web, nó đứng một vị trí độc lập bên cạnh các phần khác của trang web.

I. Xây dựng một Applet đơn giản
1. Soạn thảo một tệp có tên “Hello.java” như sau: import java.applet.Applet; //khai báo thư viện import java.awt.Graphics; //Khai báo đồ hoạ public class Hello extends Applet { //cài đặt phương thức cho Applet public void paint(Graphics g){ g.drawString("Hello!", 50, 25); } 2. Biên dịch tệp Hello.java 3. Soạn thảo một trang HTML có tên hello.htm <html><body> <applet> <applet code="Hello.class" width=150 height=25> </applet> </body></html> 4. Đặt file Hello.class và hello.htm vào trong cùng một thư mục 5. Mở file hello.htm. Tuy nhiên để các applet có thể chạy được, nó cần một JVM trên máy cục bộ. Để có được JVM cho các trình duyệt ta cần cài phiên bản Java lên máy tính cục bộ và tích hợp vào trình duyệt như một plug-in. Trong các phiên bản Java gần đây, người lập trình có thể sử dụng thư viện swing nằm trong gói javax.swing để có được giao diện GUI thống nhất trên mọi hệ thống. Các lớp trong swing có tên gọi khác so với các lớp trong awt bởi thêm ký tự đầu tiên “J”.

II. Cấu trúc cơ bản và vòng đời của một Applet
Một chương trình Applet đầy đủ sẽ bao gồm các thành phần như sau: import java.applet.Applet; public class myApplet extends Applet{ public void init(){ ...... } public void start(){ ...... } public void stop() { ...... } public void destroy() { ...... } .... //Các phương thức khác } Nếu dùng JApplet thì ta có khai báo phần đầu như sau: import javax.swing.JApplet; public class myApplet extends JApplet{…}

103

Vòng đời của một Applet được đánh dấu bởi các sự kiện diễn ra ở mỗi giai đoạn, lập trình viên cần nắm được ý nghĩa của từng giai đoạn để có thể viết code điều khiển Applet: 1. Giai đoạn init: Thực hiện các công việc khởi tạo một Applet. Giai đoạn này được bắt đầu ngay sau khi thẻ <param> nằm trong thẻ <applet> được xử lý. Các hành động như thêm các thành phần giao diện người dùng GUI được thực hiện ở đây. 2. Giai đoạn start: Được thực hiện ngay sau khi giai đoạn init được thực hiện xong. Nó cũng được gọi bất cứ khi nào người dùng chuyển sang một trang web khác rồi quay lại trang có applet. Do đó, code nằm trong start có thể được thực hiện nhiều lần trong khi code trong init chỉ được thực hiện 1 lần. 3. Giai đoạn stop: Được thực hiện khi người dùng rời khỏi trang web chứa applet. Do đó, code nằm trong stop cũng có thể được thực hiện nhiều lần. 4. Giai đoạn destroy: Được thực hiện khi người sử dụng tắt trình duyệt. Khi viết một applet, chúng ta không phải khi nào cũng cài đặt đầy đủ 4 phương thức mà tùy theo nhu cầu. Ví dụ sau xây dựng một applet cho phép vẽ liên tiếp bắt đầu từ vị trí giữa applet. import java.applet.*; import java.awt.*; import java.awt.event.*; public class AppletSample extends Applet { Point curentPoint; // Lưu tọa độ điểm hiện tại public void init() { curentPoint = new Point(this.getWidth()/2,this.getHeight()/2); this.setBackground(Color.CYAN); // đặt màu nền của applet } public void start() { this.addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent e) { drawOnApplet(curentPoint,e.getPoint()); curentPoint = e.getPoint(); } } ); } public void drawOnApplet(Point p1, Point p2) { Graphics g = this.getGraphics(); g.drawLine(p1.x,p1.y,p2.x,p2.y); } }

104

addActionListener(new ActionListener() { 105 .awt.III. Applet cũng có những khả năng như: • Tạo kết nối đến máy đang chạy nó.setSize(200.setTitle("Calculator"). import java. • Applet dễ dàng dùng các siêu văn bản hiển thị.*. add(calcButton). • Có thể gọi đến các phương thức toàn cục của các applet khác trên cùng trang web. frame. import javax. An ninh và khả năng của Applet Vì applet được download từ xa và thực hiện trên máy tính cụ bộ nên vấn đề về an ninh được quan tâm đặc biệt. Applet có thẻ giao tiếp với các applet khác trên trang web cũng như với các đối tượng khác trên trang web thông qua cơ chế riêng. 200).*. // Thêm một Button để ẩn/ hiện frame pop-up JButton calcButton = new JButton("Calculator"). • Không nhất thiết là các applet sẽ ngừng lại khi ta thoát khỏi các trang web chứa nó. ký tự phân tách file. Trong một số trường hợp ta có thể cấu hình để applet được tin cậy và có thể truy cập vào máy tính cục bộ giống như một chương trình đang chạy trên máy tính đó. Ứng dụng Applet với của sổ Popup Với Applet chúng ta hoàn toàn có thể có thêm các cửa sổ pop-up để mở rộng không gian làm việc. IV.… • Tất cả các cửa sổ trình duyệt có applet được tải về đều có thông báo.*. public class PopupCalculatorApplet extends JApplet { public void init() { // Tạo một frame với một cửa sổ panel final JFrame frame = new JFrame(). Sau đây là một Japplet có thể mở một Frame mới. password. import java. tên và phiên bản hệ điều hành. • Applet không thể giao tiếp với các máy tính khác trên mạng trừ máy tính mà nó được download về.swing. calcButton.awt. frame. trừ các thông tin như phiên bản Java. • Applet không thể đọc và ghi dữ liệu lên máy tính cục bộ • Applet không thể tìm thấy thông tin gì về máy tính cuc bộ. Các nguyên tắc về an ninh của một applet là: • Applet không bao giờ thực hiện một chương trình của máy cục bộ. đường dẫn.event. • Các applet được nạp từ hệ thống tập tin cục bộ sẽ không bị các giới hạn của các applet được nạp từ mạng xuống. Những yêu cầu về an ninh của applet là rất quan trọng. Applet không thể tìm thấy các thông tin cá nhân như email.

public void actionPerformed(ActionEvent event) { frame. Trong các trình duyệt của Netscape hoặt Windows đều cho phép applet giao tiếp với các đối tượng javascript khác trên trang web. } } V. right.isVisible()).class" width="200" height="200"> <param name="font" value="Helvetica"/> <param name="size" value="24"/> 106 .mycompany.setVisible(!frame. • width: Chiều rộng của applet • align: Xác định vị trí của applet so với các văn bản xung quanh nó. bottom.jar.class được đặt trong gói com.corejava/CoreJavaClasses. Các applet không thể thay đổi kích thước khi đã chạy. vspace và hspace. Ví dụ: nếu applet có tên MyApplet.code: code : Thuộc tính này cho biết tên của class chứa chương trình applet..class". Các thuộc tính về chương trình nguồn.codebase: Là một thuộc tính tùy chọn để xác định đường dẫn tuyệt đối nơi chứa class ở giá trị code. absmiddle. } }). Khi đó applet cần có tên để truy cập. Các gói chương trình được nén ở dạng file JAR và được đặt cách nhau bởi dấu . Ví dụ: <applet code="CalculatorApplet. Đường dẫn phải phù hợp với đường dẫn gói của class applet. middle. baseline. archive: Chứa tên các gói chương trình hoặc tài nguyên khác được tải về kèm theo applet. Các giá trị của align có thể là: left. Các thẻ HTML của Applet Một khai báo applet trong trang HTML thường có dạng: <applet code="NotHelloWorldApplet.class" cũng được chấp nhận.MyApplet.class" archive="CalculatorClasses. absbottom. hoặc: code="com. texttop. Ngoài ra Java cho phép ta định nghĩa các tham số cho applet thông qua các thẻ <param> Ví dụ: <applet code="FontParamApplet. name: Tên của applet.jar" width="100" height="150"> object: Chứa tên file đã được tuần tự hóa của một applet. . Tên này là tương đối so với giá trị codebase hoặc với thư mục hiện hành nếu không có codebase. top.mycompany thì đường dẫn phải là: code="com/mycompany/MyApplet.class" width="300" height="100"> Thong tin duoc hien thi khi applet khong hien thi </applet> Sau đây ta sẽ tìm hiểu các thuộc tính của applet: Các thuộc tính về vị trí: • height: Chiều cao của applet.

. Chú thích các tham số: array: Mảng các ký tự. int offset. length: Số các ký tự cần được vẽ. • 107 . • getCodeBase(): Cho biết địa chỉ dạng URL của thư mục chứa tập tin . int archeight): Vẽ hình chữ nhật có bo góc. int x2. • drawLine(int x1. int xCoor. String name): trả về một đối tượng ảnh hiển thị trên nền. xCoor: Toạ độ X.. thường các applet dùng paint() để biểu diễn các hoạt động của mình trên trang web. int height): Vẽ hình chữ nhật. int height): Vẽ hình oval đặc.. int fontSize = Integer. int y2): Vẽ đường thẳng từ A(x1.}: Là phương thức hiển thị cơ bản. int offset.Trong đó array: Mảng các byte. int yCoor): xuất các byte ra.. int yCoor): xuất các ký tự.</applet> Khi đó trong chương trinh applet. int height. int width.CLASS của applet. • fillRect(int xCoor.Trong đó: width là Chiều rộng của hình. xCoor: Toạ độ X. int width. nơi các ký tự cần được vẽ.. offset: Vị trí bắt đầu. • drawOval(int xCoor. int width. • getDocumentBase(): cho biết địa chỉ dạng URL của thư mục chứa tập tin HTML chứa applet. • drawRect(int xCoor. int yCoor. ta có thể lấy ra để sử dụng: public class FontParamApplet extends JApplet { public void init() { String fontName = getParameter("font").. } } VI. • fillOval(int xCoor.Vị trí offset hay vị trí bắt đầu. lập trình đồ họa và bắt sự kiện của applet public void paint(Graphics g) {.parseInt(getParameter("size")). int length. • getAudioClip(URL url. • getLocale(): Xác định vị trí applet. • drawRoundRect(int xCoor. • drawBytes(byte array[ ]. nơi các ký tự được vẽ.. int length. • getImage(URL url. int height): Vẽ hình chữ nhật đặc. int yCoor. int arcwidth. y2). • Phương thức repaint() được dùng khi cửa sổ cần cập nhật lại.. Phương thức này chỉ cần một tham số là đối tượng của lớp Graphics. height là Chiều cao của hình. nơi các ký tự cần được vẽ. y1) đến B(x2. int yCoor. yCoor: Toạ độ Y. Ngoài ra Applet còn thừa hưởng các phương thức từ lớp AWT. int xCoor. int yCoor. • showStatus(String st): hiển thị xâu st trên thanh trang thái. int height): Vẽ đường oval. Các phương thức. int yCoor. • drawChars(char array[ ]. • public void update(Graphics g) {. int width. int y1.}: là phương thức ta dùng sau khi thực hiện pain() nhằm làm tăng hiệu quả vẽ. yCoor: Toạ độ Y. int width.. String name): cho đối tuợng audio. length: Số byte cần vẽ.

int height. int y[ ]. • draw3Drect(int xCoord. int width. (Font. int height. totalPoints: Tổng số điểm cần vẽ. int yCoord. int numPoints): Vẽ đa giác đặc. • setFont(new Font(“Times Roman”. int archeight): Vẽ hình cung đặc.white Color. int totalPoints): Vẽ nhiều đường thẳng Trong đó: xArray: Mảng lưu trữ toạ độ x của các điểm. archeight: Độ rộng của cung (góc của cung) so với góc ban đầu. arcwidth: Góc bắt đầu.fillRoundRect(int xCoor. Trong đó: x[ ]: Mảng lưu trữ toạ độ x của các điểm. int width. Font.yellow Color. Trong đó: arcwidth: làm tròn góc trái và góc phải của hình chữ nhật. • fillPolygon(int x[ ].black Color. archeight: làm tròn góc trên đỉnh và góc đáy của hình chữ nhật. setColor(Color c): Đặt màu vẽ. • fillArc(int xCoord. Font. int arcwidth.BOLD. Trong đó: xCoord: Toạ độ x.blue Color.pink Color. Font.orange Color. Ví dụ.cyan Color.magenta • 108 . height: Chiều cao của cung được vẽ. yCoord: Toạ độ y. int width. Bảng một số màu cơ bản: Color.ITALIC) • drawPolygon(int x[ ]. int arcwidth. numPoints: Tổng số điểm cần vẽ. int height. • drawArc(int xCoord.green Color. int width. int y[ ]. int yCoord. width: Chiều rộng của cung được vẽ. int yArray[ ]. arcwidth = 20 có nghĩa là hình chữ nhật được làm tròn cạnh trái và cạnh phải mỗi cạnh 10 pixel. int yCoor. int archeight): Vẽ hình cung.gray Color.darkgray Color. • drawPolyline(int xArray[ ]. yArray: Mảng lưu trữ toạ độ y của các điểm. y[ ]: Mảng lưu trữ toạ độ y của các điểm. boolean raised): Vẽ hình chữ nhật 3D. int height. 15)): Đặt Font cho chữ. int numPoints):Vẽ đa giác.PLAIN.lightgray Color. int yCoord.red Color. int arcwidth. int archeight): vẽ hình chữ nhật bo góc đặc.BOLD.

Một giao diện người dùng được hình thành từ các phần tử của GUI. • Trình quản lý cách trình bày (Layout manager). Một phần tử GUI được thiết lập bằng cách sử dụng các thủ tục: 1. • Sự kiện (Event). Để làm việc với các đối tượng GUI chúng ta cần nhập gói java. Từ phiên bản 1. 4. Tạo đối tượng.*. AWT cung cấp các thành phần khác nhau để tạo GUI hiệu quả. • Thành phần (Component). các thành phần này có thể là: • Vật chứa (Container). 3.4.Đề tài 10. Java phát triển một thư viện mở rộng swing mới với đa số các lớp GUI kế thừa từ AWT nhưng có khả năng di động tốt hơn. Giới thiệu AWT Abstract Windows Toolkit – AWT: Là thư viện của Java cung cấp cho lập trình viên các giải pháp giao diện người dùng đồ hoạ (Graphical User Interface .awt. • Đồ hoạ (Graphics) và các tính năng vẽ (draw). Các lớp GUI trong swing có thêm tiền tố “J” so với các lớp trong AWT. Sau đây. Chỉ ra nó nằm ở đâu. Lập trình giao diện đồ họa GUI I. Xác định sự xuất hiện ban đầu của đối tượng. 2.GUI) thân thiện. Thêm phần tử vào giao diện trên màn hình. chúng ta sẽ xét các thành phần GUI trong swing. • Phông chữ (Font). Sơ đồ phân cấp thừa kế các đối tượng GUI trong swing như sau: 109 .

nó là cửa sổ hộp thoại đưa ra những lời thông báo. JApplet. • Lấy tiêu đề của JFrame: public String getTitle(). . Do đó chúng ta cần gắn JPanel vào đối tượng nào đó như: JFrame. import javax. • Thay đổi biểu tượng JFrame: public setIconImage(Image img).khung chứa đơn giản nhất.setSize(400. Một vật chứa có thể chứa nhiều phần tử. frame1. b = false thì không đổi. JFrame frame2 = new JFrame("Cua so Frame").1 JFrame Tạo đối tượng khung chứa JFrame bằng phương thức khởi tạo: void JFrame().2 JPanel JPanel không thể nhìn thấy trực tiếp. f. để tạo các ứng dụng windows. • Bỏ hoàn toàn đối tượng JFrame: frame1..*.setTitle(String newTitle).swing. f. • Đưa cửa sổ hiện ra màn hình: frame1. • JScrollPanel . trong đó: b = true cho hiển thị. để nhóm các đối tượng con lại và sắp xếp theo cách thích hợp. import javax.dispose(). Tạo Frame với tiêu đề bên trên: void JFrame(String FrameTitle).là cửa sổ nhưng không đầy đủ chức năng như Frame.*. • Co dãn JFrame: public void setResizable(boolean b). 110 . II.setSize(int width. nó là đối tượng dùng để chứa các thành phần GUI trên màn hình. Ví dụ: JFrame frame1 = new JFrame().khung chứa như Panel nhưng có hai thanh trượt.swing.show(). Ví dụ sau tạo một đối tượng JPanel và đặt vào nó một đối tượng nút bấm JButton.II. } } Một số phương thức hay sử dụng: • Đặt lại kích thước cho JFrame: frame1. public class FrameSample { public static void main(String[] argvs) { JFrame f = new JFrame(). • Thay đổi tiêu đề cho JFrame: frame1.là một cửa sổ như mọi ứng dụng của windows. trong đó: b = true thì Frame có thể thay đổi kích thước. b = false cho ẩn. • Xác định JFrame đang ở tình trạng nào: public boolean isResizable(). • JFrame .. int height). Tạo khung chứa JPanel bằng phương thức khởi tạo: JPanel panel1 = new JPanel().400).setVisible(boolean b). II. Vật chứa (Container) Là vùng mà ta có thể đặt các thành phần (component) của giao diện.setVisible(true). • JDialogs . Vật chứa thường được sử dụng là: • JPanel .

add(new JButton("OK")).setSize(400.setVisible(true).public class FrameSample { public static void main(String[] argvs) { JFrame f = new JFrame(). p. f.add(p). JPanel p = new JPanel().400). f. // gắn JPanel vào JFrame f. } } 111 .

b. Đưa đối tượng JDialog ra màn hình bằng phương thức show().100).*.setVisible(!d. } } ).II.awt. import java. boolean isResizable() Đặt và lấy tiêu đề của JDialog: void setTitle(String).*. cửa sổ này thích ứng với các thao tác mang tính tuỳ biến.swing. Ta có thể tạo JDialog dưới hai hình thức: • modal: là cửa sổ JDialog khi thực hiện sẽ khoá chặt các cửa sổ khác.3 JDialog Như JFrame.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { d. Lấy và thay đổi kích thước JDialog: public setResizable(boolean). Cửa sổ này thường yêu cầu một tác vụ nào đó cần phải hoàn thành ngay.isVisible()). public class FrameSample extends JFrame { private JDialog d. trong đó: isModal . còn được gọi là popup-window. Các đặc điểm thường sử dụng với đối tượng JDialog thể hiện tương tự với JFrame.*. public FrameSample() // Constroctor { d = new JDialog(this. nhưng ít chức năng hơn. d. Cách tạo khung chứa JDialog từ phương thức khởi tạo: public JDialog(JFrame parentWindow. JButton b = new JButton("Xem/Tat mot JDialog"). true) Tạo JDialog có tiêu đề định trước: public JDialog(Frame parentWindow.event. Xác minh một JDialog đang thuộc dạng nào ta gọi phương thức: public boolean isModal() Chương trình sau đây sẽ ẩn hoặc hiện một JDialog mỗi khi nhấn vào một nút bấm: import javax. JPanel p = new JPanel().setSize(100. String title. 112 . Ẩn hiện JDialog ta còn có phương thức: setVisible(boolean). import java. muốn đưa ra một JDialog từ JApplet ta phải tạo ra một JFrame giả tạo. Giấu cửa sổ JDialog ta dùng phương thức: hide(). boolean isModal). boolean isModal) JDialog không thể gắn với Applet.quyết định xem JDialog được tạo ra ở dạng nào: isModal = true cho modal còn isModal = false cho non-modal.awt."Day la Jdialog". String getTitle().false). • non-modal: ngược lại với modal. Ví dụ: JDialog myDialog = new JDialog(myWindow.

JScrollPane được ứng dụng trong các danh sách chọn hay các vùng nhập văn bản.1 Nút nhấn Cách tạo nút nhấn Ta gọi phương thức khởi dựng: public Button(String label) label là tên nhãn của nút nhấn Ví dụ: Button nutOK = new Button("OK").setLabel("OK").2 Nhãn (Label) Tạo nhãn không có nội dung gì: public Label() hoặc tạo nhãn có nội dung: public Label(String nameLabel). Để đổi tên nhãn cho nút nhấn ta gọi phương thức public void setLabel(String newLabel). III.400). add(p). Giới thiệu về các thành phần GUI cơ bản • • • • • • • Jlabel: Chỉ một vùng hiển thị văn bản hoặc các icon.RIGHT: những giá trị căn lề. int align) Một số phương thức hay sử dụng: setText(String nameLabel): Đặt lại nội dung mới cho nhãn.LEFT. } public static void main(String[] argvs) { FrameSample fs = new FrameSample(). JButton: Đối tượng nút bấm JcheckBox: Đối tượng nút chọn. Để xem tên nhãn hiện tại của nút nhấn. } } II. hoặc thêm chế độ căn lề: pubic Label(String name. Label.4 JScrollPane Đây không phải là một cửa sổ nhưng có tính chất như khung chứa JPanel dùng để chứa các đối tượng. 113 . ta gọi phương thức public String getLabel() Ví dụ: Button nutOK = new Button(). JtextField: Chỉ một đối tượng cho phép nhập dữ liệu từ bàn phím.setSize(400.CENTER. III.p.add(b).setVisible(true). Sử dụng nút nhấn Khi kích chuột vào nút nhấn sẽ thực hiện một công việc nào đó. Label. JcomboBox: Đối tượng ComboBox Jlist: Danh sách JPanel: Nơi đặt các thành phần GUI nói trên. Đư nút nhấn vào Applet hay cửa sổ chương trình bằng lệnh: add(nutOK). fs. nutOK. Vấn đề này chúng ta đã xem xét trong phần xử lý các sự kiện III. Label. Tính chất khác là khi đối tượng nó chứa quá lớn thì JScrollPane sẽ xuất hiện thanh trượt đứng và ngang ở hai bên viền để ta có thể xem được toàn bộ. fs.

public class LabelTest extends JFrame { private JLabel label1.swing. // Gói Java mở rộng import javax. container. container.add( label3 ).setLayout( new FlowLayout() ). // Contructor của JFrame // Lấy đối tượng pane của một JFrame Container container = getContentPane(). label3. label2.LEFT ). label1.setToolTipText( "This is label3" ).BOTTOM ).*. bug.awt.setToolTipText( "This is label1" ). import java. label3.setVerticalTextPosition( SwingConstants. 170 ). setVisible( true ).setIcon( bug ).CENTER ).gif" ). Xem nhãn đang được căn lề ở chế độ nào: public int getAlignment(). label2.setToolTipText( "This is label2" ).Lấy nội dung hiện hành của nhãn: public String getText().setText( "Label with icon and text at bottom" ).awt.*. container. label3. label3. // hiển thị khi di chuột đến container. // JLabel không tham số label3 = new JLabel(). label3. } 114 .setHorizontalTextPosition( SwingConstants. // thêm vào container align) throws // Tạo Jlabel với icon hoặc text Icon bug = new ImageIcon( "bug1. label3. // constructor của JLabel label1 = new JLabel( "Label with text" ). SwingConstants. label2 = new JLabel( "Label with text and icon".event.add( label2 ).add( label1 ). // Tạo giao diện GUI public LabelTest() { super( "Testing JLabel" ).*. Thiết lập lại chế độ căn lề: public void setAlignment(int IlligalArgumentException Sau đây là ví dụ sử dụng JLabel: // Minh họa về JLabel // Nhập các gói thư viện import java. setSize( 275.

Ta có thể tạo nút đánh dấu theo 5 phương thức khởi dựng: • public Checkbox(): tạo ô đánh dấu không có nhãn. • public Checkbox(String cbLabel. boolean state. • public Checkbox(String cbLabel . } } III. boolean state): dùng để tạo ô đánh dấu có nhãn với trạng thái đánh dấu ban đầu. • public Checkbox(String cbLabel. CheckboxGroup g). Nhóm các ô đánh dấu trở thành nút chọn.3 Nút đánh dấu (checkbox) Một nút đánh dấu có hai phần: nhãn và dấu biểu hiện trạng thái.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ). boolean state): Tạo ô đánh dấu với một nhãn cbLabel gắn kèm với trạng thái ban đầu của ô đó. Nếu muốn thiết lập trạng thái. Xử lý tình huống khi ô đánh dấu thay đổi trạng thái: Để lắng nghe ô đánh dấu. nút tạo ra được nhóm trong nhóm g. CheckboxGroup g. • public Checkbox(String cbLabel): tạo ô đánh dấu với một nhãn cbLabel gắn kèm. application. Kiểm tra và thiết lập trạng thái: Để kiểm tra một ô có được đánh dấu không ta dùng phương thức: public boolean getState(). ta dùng phương thức: addItemListener(ItemListener L) Để loại bỏ lắng nghe đó ta dùng phương thức: removeItemListener(ItemListener L) 115 .// hàm main public static void main( String args[] ) { LabelTest application = new LabelTest(). ta dùng phương thức: setState(boolean state).

container. Font. container. 14 ) ).setLayout( new FlowLayout() ).getStateChange() = = ItemEvent.setFont( new Font( "Serif".PLAIN.add( bold ). // Đặt ô nhập và font chữ field = new JTextField( "Theo dõi font chữ thay đổi".BOLD.add( italic ). 116 // Chọn ô chứ nghiêng if ( event.addItemListener( handler ). else valBold = Font. bold. application.*. private JCheckBox bold. // Đăng ký đối tượng lắng nghe CheckBoxHandler handler = new CheckBoxHandler(). field.*. // Java extension packages import javax.event.awt.PLAIN. // lấy pane Container container = getContentPane(). italic. } // Lớp nội lắng nghe sự kiện private class CheckBoxHandler implements ItemListener { private int valBold = Font.addItemListener( handler ). import java. } // execute application public static void main( String args[] ) { CheckBoxTest application = new CheckBoxTest(). // Thiết lập GUI public CheckBoxTest() { super( "JCheckBox Test" ). setSize( 275.PLAIN.awt. 100 ). italic. container.PLAIN.swing.// Java core packages import java. // tạo đối tượng checkbox bold = new JCheckBox( "Bold" ). italic = new JCheckBox( "Italic" ).SELECTED ) valBold = Font.setDefaultCloseOperation( JFrame. // Đáp ứng sự kiện chọn ô public void itemStateChanged( ItemEvent event ) { // xử lý chọn ô chữ đậm if ( event.getSource() == italic ) . 20 ).*. public class CheckBoxTest extends JFrame { private JTextField field. private int valItalic = Font.EXIT_ON_CLOSE ). setVisible( true ).add( field ).getSource() == bold ) if ( event. container.

boldItalicButton.*. Về bắt các sự kiện cũng tương tự ô đánh dấu.swing. // Java extension packages import javax. "travelbug.gif" }.addItemListener( handler ).5 Hộp thoại Combo Java hỗ trợ hộp thoại Combo thông qua đối tượng của class JComboBox. private String names[] = { "bug1. plainButton.gif".add( plainButton ). radioGroup. Đặt lựa chọn ta dùng: setSelectedCheckbox(). đưa ra một danh sách các mục và ta chỉ được chọn 1 mục trong đó.addItemListener( handler ). "buganim.III. "bug2.addItemListener( handler ). public class ComboBoxTest extends JFrame { private JComboBox imagesComboBox.add( boldItalicButton ). III. radioGroup.addItemListener( handler ). 117 . ta có phương thức sau: public CheckboxGroup().add( boldButton ). // Java core packages import java.*. JComboBox cũng phát sinh sự kiện ItemEvent giống như JRadioButton và JCheckBox. radioGroup. radioGroup. // Nhóm các ô lại radioGroup = new ButtonGroup().*.gif". Ta tạo ra ô đánh dấu và đặt nó vào một nhóm. boldButton.awt. Với một nhóm các nút ta có thể lấy ra đối tượng hiện tại đang được chọn bằng cách gọi phương thức getSelectedCheckbox(). Sau đây là ví dụ về sử dụng ô chọn: // Đăng ký đối tượng lắng nghe cho mỗi ô chọn radio RadioButtonHandler handler = new RadioButtonHandler(). italicButton. Đây là một danh sách xổ xuống. Phương thức getItemSelectable sẽ trả về đối tượng nơi mà tình huống phát sinh: public ItemSelectable getItemSelectable(). Phương thức getItem của đối tượng ItemEvent sẽ cho ta biết giá trị nút chọn: public Object getItem(). Cách sử dụng nút chọn: Ta tạo một đối tượng giao tiếp ItemListener để lắng nghe tình huống. import java. private JLabel label.4 Nút chọn (radio button) Tạo nút chọn: Đây là trường hợp đặc biệt của ô đánh dấu.gif".event.awt.add( italicButton ). Chương trình sau đây minh họa việc sử dụng JComboBox với các phần tử là các ảnh GIF.

container.setDefaultCloseOperation( JFrame. } // hàm main public static void main( String args[] ) { ComboBoxTest application = new ComboBoxTest(). 100 ).EXIT_ON_CLOSE ). // Thiết lập GUI public ComboBoxTest() { super( "Testing JComboBox" ). setVisible( true ). // đặt một JLabel hiển thi ImageIcons tương ứng label = new JLabel( icons[ 0 ] ). new ImageIcon(names[2]). imagesComboBox. // Đặt layout Container container = getContentPane().addItemListener( new ItemListener() { // bắt sự kiện public void itemStateChanged( ItemEvent event ) { // liệu có phần tử được chọn if ( event.private Icon icons[] = { new ImageIcon(names[0]).setLayout( new FlowLayout() ).6 Danh sách (Lists) Lớp List cho phép ta tạo một danh sách các phần tử cho ta lựa chọn Tạo một danh sách: 118 . new ImageIcon(names[1]).add( imagesComboBox ). } } ).setIcon( icons[imagesComboBox.setMaximumRowCount( 3 ).getSelectedIndex() ] ). // khởi tạo combo imagesComboBox = new JComboBox( names ). aplication. new ImageIcon(names[3])}.getStateChange() == ItemEvent. container. }} III. imagesComboBox. container.add( label ). setSize( 350.SELECTED ) label.

Chèn một phần tử vào danh sách bằng phương thức add(String item. Color.cyan.lightGray.swing.*.green. "Magenta". "Pink".gray.awt. Color. private String colorNames[] = { "Black". public class ListTest extends JFrame { private JList colorList. "Yellow" }. "Gray". ta cài đặt giao tiếp ActionListener và gắn nó vào danh sách. import javax. int pos) vd: list.orange. Color. Để chọn một phần tử mà ta biết vị trí: select(int index) Nếu phần tử đang ở trạng thái chọn chuyển sang trạng thái bình thường: deselect(int index) Trạng thái của một phần tử: isSelected(int index) Chuyển chế độ đơn chọn sang đa chọn: setMultiplesSelections(boolean bl) Cho biết một danh sách là đơn chọn hay đa chọn: boolean isMultipleMode(). "Red". 4). index là vị trí phần tử mà ta muốn chèn. Color. private Color colors[] = { Color. Color.add("Mau do"). Color. Color. Trả về vị trí của phần tử được chọn.magenta. "White". "Light Gray".swing. Color. 119 .black.*.*. int index). "Green". Color. Thay thế một phần tử ở vị trí pos bằng phần tử mới: replaceItem(String newItem. Loại bỏ một phần tử trong danh sách ta dùng phương thức remove(int pos).pink. "Orange".vd: list.replaceItem("Xanh". "Blue". Nếu được chọn nhiều thì dùng: int[] getSelectedIndex() Lấy ra phần tử được chọn: getSelectedItem(). // Java extension packages import javax. Để xử lý được tình huống nhấp đôi chuột. Color. // Java core packages import java. "Cyan". hoặc để chỉ định bao nhiêu phần tử sẽ được hiển thị cùng một lúc trong danh sách: public List(int rows) hoặc tạo một danh sách cho phép lựa chọn nhiều phần tử cùng một lúc: public List(int rows. nếu không có phần tử nào được chọn thì giá trị sẽ là -1: getSelectedIndex(). Loại bỏ hết danh sách: removeAll(). boolean multiMode) Sử dụng danh sách chọn: Đưa từng phần vào danh sách bằng lệnh add(String item).red. private Container container. Sử dụng đối tượng danh sách: Cài đặt giao tiếp ItemListener để tạo đối tượng biết lắng nghe sự thay đổi trạng thái của các phần tử trong danh sách.darkGray.blue. Color. Chọn nhiều thì dùng: String[] getSelectedItem(). vd: List list = new List(). "Dark Gray".Phương thức khởi dựng mặc định: public List().yellow }. Phương thức getActionCommand() trong ActionEvent sẽ trả về tên của phần tử bị nhấp. Color.white. Sử dụng đối số ItemEvent trong phương thức itemStateChange để biết được chỉ số của phần tử đang thay đổi trạng thái.event.

• Tạo một ô văn bản hiển thị tối thiểu numCols ký tự: public TextField(int numCols). setSize( 350.SINGLE_SELECTION ). } // hàm main public static void main( String args[] ) { ListTest application = new ListTest().EXIT_ON_CLOSE ). setVisible( true ). 150 ). application. container.addListSelectionListener( new ListSelectionListener() { public void valueChanged( ListSelectionEvent event ) { container. // Tạo danh sách colorList = new JList( colorNames ). • Tạo một ô văn bản với nội dung là một chuỗi cho trước: public TextFiled(String initText). } } ).// Thiết lập GUI public ListTest() { super( "List Test" ). // lấy layout container = getContentPane(). // thêm một JScrollPane chứa danh sách container.setLayout( new FlowLayout() ). }} III. colorList. // Không cho chọn nhiều colorList.setSelectionMode(ListSelectionModel.setDefaultCloseOperation( JFrame. // đặt lắng nghe sự kiện colorList.getSelectedIndex() ] ).add( new JScrollPane( colorList ) ).setVisibleRowCount( 5 ). int numCols). • Tạo ô văn bản kết hợp: public TextField(String initText.7 Ô văn bản (text field) và vùng văn bản (text areas) Tạo ô văn bản: • Khởi tạo một ô văn bản không xác định kích thước: public TextField(). 120 .setBackground( colors[ colorList.

setEchoChar('*'). Tạo một vùng văn bản với số cột và số dòng định trước: public TextArea(int rows. Để xác định xem vị trí đánh dấu khối văn bản bắt đầu và kết thúc ở đâu: public int getSelectionStart(). int pos).*. canEdited = true: thêm.Tạo vùng văn bản: Tạo vùng văn bản rỗng. textField3. textField2. Xác định kích thước hiển thị: public int getRows(). • • • • 121 . private JPasswordField passwordField. public int getColums(). Khi người dung nhấn Enter thì tình huống được gọi. //cuối Đánh dấu toàn bộ văn bản: public void selectAll(). // constructor của JFrame Container container = getContentPane(). int rows. sử được. kích thước bất kỳ: public TextArea(). ta thiết lập ActionListener để gắn đối tượng xử lý sự kiện vào văn bản TextField. Cho phép soạn thảo được: public void setEditable(boolean canEdited). Tạo một vùng văn bản với nội dung cho trước: public TextArea(String initiaText). import javax. ví dụ: myTextField.awt. // Thiết lập giao diện GUI public TextFieldTest() { super( "Testing JTextField and JPasswordField" ). Xác định đối tượng đang ở trang thái nào: public boolean isEditable(). canEdited = false: chỉ đọc.*. //mã mKhẩu Xác định xem ký tự làm ký tự hiển thị: public char getEchoChar(). import java. Đặc điểm riêng của đối tượng TextArea: Đưa thêm một dòng văn bản vào đối tượng: public void appendText(String newText).awt. Chèn một chuỗi văn bản vào vị trí bất kỳ: public void insertText(String newText. • Tạo một vùng văn bản với số dòng số cột và nội dung cho trước: public TextArea(String st.swing. Xác định chiều dài của ô văn bản theo ký tự: public int getColums(). public class TextFieldTest extends JFrame { private JTextField textField1.setLayout( new FlowLayout() ). int cols).event. int cols) Đặc điểm chung của các thành phần văn bản: Hai lớp này được dẫn xuất từ lớp TextComponent Muốn đưa nội dung văn bản vào các đối tượng này ta sử dụng phương thức setText: public void setText(String newText). Lấy nội dung văn bản trong các đối tượng: public String getText(). import java. Lấy nội dung văn bản được đánh dấu: public String getSelectedText(). Sử dụng đối tượng TextField và TextArea: Muốn lấy nội dung văn bản của đối tượng. Đặc điểm riêng của TextField: Đặt ký tự hiển thị cho ký tự nhập vào: public void setEchoChar(Char ch). container. //đầu public int getSelectionEnd().*.

getSource() == textField2 ) string = "textField2: " + event.setEditable( false ). textField1. passwordField. textField3. 100 ).getActionCommand().// ô nhập với kích thước mặc định textField1 = new JTextField( 10 ). } // hàm main public static void main( String args[] ) { TextFieldTest application = new TextFieldTest().add( textField1 ). 122 .addActionListener( handler ). chỉ hiên thị thông tin textField3 = new JTextField( "Uneditable text field".getActionCommand().add( passwordField ). textField2. 20 ).addActionListener( handler ).getSource() == textField1 ) string = "textField1: " + event. } // Lớp nội cho bộ lắng nghe sự kiện private class TextFieldHandler implements ActionListener { // phương thức xử lý sự kiện public void actionPerformed( ActionEvent event ) { String string = "".add( textField2 ). textField3.addActionListener( handler ).addActionListener( handler ). application. // khi người dùng ấn enter if ( event. // ô nhập password passwordField = new JPasswordField( "Hidden text" ). // ô nhập không cho phép nhập. container. container. // ô nhập với văn bản có sẵn textField2 = new JTextField( "Enter text here" ). container.add( textField3 ). // user pressed Enter in JTextField textField2 else if ( event.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ). setSize( 325. container. setVisible( true ). // Đăng ký bộ lắng nghe sự kiện TextFieldHandler handler = new TextFieldHandler().

Muốn biết hiện thời đơn vị thay đổi là bao nhiêu: public int getBlockIncrement().HORIZONTAL. int pos. Đối tượng Scrollbar chỉ chịu trách nhiệm di chuyển và cung cấp cho ta giá trị thay đổi. //bước nhảy int minValue. //vị trí khởi đầu int pageUnit. Scrollbar.getActionCommand(). Đặt lại vị trí hiện hành cho thanh trượt: public void setValue(int newPos). Muốn biết hiện thời tăng giảm bao nhiêu: public int getUnitIncrement() Chỉ định con số khi tình huống page xảy ra: pubic void setBlockIncrement(int b). 123 .getSource() == passwordField ) { JPasswordField pwd = ( JPasswordField ) event. vị trí hiện hành sẽ thay đổi. Tạo thanh trượt: Phương thức khởi tạo: public Scrollbar().cho đứng. //giá trị min int maxValue). Cho ta vị trí hiện hành: public int getValue(). string = "passwordField: " + new String( passwordField. Khi người dùng kích chuột vào mũi tên ở hai đầu thì tình huống line nảy sinh. //giá trị max Một số phương thức hay dùng: Thay đổi giá trị tăng giảm (mặc định là 1): public void setUnitIncrement(int increment).VERTICAL . Lấy giá trị lớn nhất và nhỏ nhất: public int getMaximum(). Muốn biết thanh trượt đứng hay ngang: public int getOrientation() trả về giá trị là một trong hai hằng số Scrollbar. Tình huống page nảy sinh khi người dùng kích chuột vào khoảng giữa thanh trượt. thanh trượt sẽ tự động cộng thêm hay trừ đi một đơn vị.getSource(). } JOptionPane. // user pressed Enter in JTextField passwordField else if ( event.VERTICAL và Scrollbar. // Hiên thị cửa sổ thông báo } } } III.getPassword() ). Tình huống absolute nảy sinh khi người dùng nắm vào vị trí hiện hành của thanh trượt và kéo nó đi.getSource() == textField3 ) string = "textField3: " + event.8 Thanh trượt (Scrollbar) Ta có thể đặt thanh trượt các giá trị giới hạn tối thiểu (min) và tối đa (max) cùng với vị trí hiện tại trên thanh trượt. Tạo thanh trượt có đầy đủ thông số ban đầu: public Scrollbar(int orienttation. Tạo thanh trượt đứng hay ngang ta dùng: public Scrollbar(int orienttation).// user pressed Enter in JTextField textField3 else if ( event. string ).HORIZONTAL cho nằm ngang. public int getMinimum().showMessageDialog( null. orienttation nhận giá trị Scrollbat.

enable().setMnemonic('F'). ví dụ: myScrollbar. vị trí hiện hành tăng 1 đv. • AdjustmentEvent.setJMenuBar(menuBar).disable(). Java dùng lớp JMenuItem định nghĩa từng mục của thực đơn. int minimum. Ở đây ta đã gọi một constructor với một tham số là nhãn của mục chọn. ta cần thêm vào đó các JMenu là các mục trên thanh Menu. 10.addSeparator(). page và absolute. khi người dùng chọn vào đó sẽ sổ xuống danh sách các mục chọn khác. Ta sử dụng hàm getAdjustmentType() để xác định xem tình huống nào đang xảy ra. Sử dụng thanh trượt: Ta nhờ đối tượng xử lý tình huống xử lý: public void adjustmentValueChanged(AdjustmentEvent evt). Các JMenuBar được tạo ra để gắn vào một của sổ JFrame bằng một lệnh gọi: JMenuBar menuBar = new JMenuBar(). Bây gời là lúc ta cài đặt các mục chọn trong một JMenu. Lớp JCheckBoxMenuItem chứa các mục được chọn để kiểm tra trong các mục thực đơn.add(file). //mờ mục chọn Ta có thể dùng đường phân cách để tách các mục chọn: 124 .’O’).UNIT_INCREMENT: tình huống line xảy ra. // MenuBar này chưa có phần tử nào Sau khi có MenuBar. Có 3 trạng thái: line. ví dụ là ‘F’ để khi ấn Alt + F thì JMenu này được kích hoạt: file. JFrame frm = new JFrame(“Day la mot Frame”).Track: tình huống absolute xảy ra. 500).setValues(75.add(open). 0. frm. Những thực đơn này có thể xuất hiện bất cứ vị trí nào trong cửa sổ hiện tại. vị trí thanh trượt giảm 1 đơn vị. Tạo thanh trình đơn: JMenuBar myMenubar = new JMenuBar(). Sau đó thì thêm nó vào JMenuBar: menuBar. JMenuItem open = new JMenuItem(“Open”. Đặt trạng thái cho mỗi mục chọn sử dụng enable() hoặc disable(): Vi dụ: openItem. Ta đặt cho nó một phím tắt. JMenu file = new JMenu(“File”). int maximum). Sau đó ta add vào JMenu: file. Nếu ta cần biểu diễn các dòng kẻ ngang để phân tách các mục chọn thì ta có thể gọi phương thức addSeparator() của một đối tượng JMenu: file. Lớp JPopUpMenu biểu diễn cho thực đơn pop-up. IV. AdjustmentEvent. //được chọn openItem. • AdjustmentEvent. Thành phần Menu Lớp JMenuBar cài đặt thanh thực đơn và trong đó có thể chứa các thực đơn pull-down.BLOCK_INCREMENT: tình huống page xảy ra.UNIT_DECREMENT: tình huống line xảy ra. vị trí thanh trượt tăng 1 đơn vị. một tham số là ký tự phím tắt.Thiết lập lại các thông số cho thanh trượt: public void setValues(int position. ta lấy vị trí thanh trượt bằng hàm getValue(). int pageUnit. • AdjustmentEvent.

Xác định xem mục chọn Autosave đang ở trạng thái nào. import javax. ta dùng: Autosave.'O'). Khi sử dụng. // Them muc chon vao muc File menuFile. import java.setLayout(new FlowLayout(FlowLayout. // Khai bao muc File trong thanh menu JMenu menuFile= new JMenu("File").getContentPane(). một dấu kiểm tra (check mark) sẽ hiện bên trái mục chọn: Mục đánh dấu: CheckboxMenuItem Autosave = new CheckboxMenuItem("Auto save").add(Autosave). // Khai bao mot thanh menu JMenuBar menuBar= new JMenuBar(). Ví dụ: //tạo mục chọn có menu con JMenu printItem = new JMenu("Print").awt. //đưa mục chọn có menu con vào menu chính FileMenu.add(new JMenuItem("New". //tạo các mục chọn cho menu con printItem. // Khai bao mot thuc don pop-up JPopupMenu jp. ta tạo một menu bình thường rồi đưa vào menu đã có. // Khai bao mot muc chon voi phim tat O JMenuItem fileOpen = new JMenuItem("Open". // Them mot muc chon khac voi phim tat N menuFile.*.add(fileOpen).addSeparator(). // Dat ky tu kich hoat tat cung Alt menuFile. để mục chọn tương tác và nhận được sự kiện ta cần cài đặt giao diện ActionListener và gắn vào từng mục chọn. // Them dong ngan cach 125 . printItem.setMnemonic('F').menuBar.swing.awt. Tạo một mục chọn có khả năng đánh dấu (check Item). Sau đây là một ví dụ xây dựng một JFrame với thanh menu và các mục chọn trong đó có cài đặt xử lý các sự kiện.getState().add("Print preview"). Tạo mục chọn có chứa menu con khác.*.event. // Dat kieu trinh bay pane.LEADING)). import java.add("to preview"). FileMenu.*.FileMenu.add(menuFile).add(printItem). public MenuBarSample() { // Lay ve doi tuong chua cua Frame hien tai Container pane = this.'N')). class MenuBarSample extends JFrame { //Khai bao mot hop thoai JOptionPane op = new JOptionPane().

if (ck.showMessageDialog(getContentPane().getItem(1).addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { // Lay ve doi tuong nguon su kien va ep kieu JCheckBoxMenuItem ck = (JCheckBoxMenuItem)e. } } ).addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { op. // Them phan xu ly su kien chon hay khong chon cho no chk."Ban vua chon Save")."Ban vua chon is editting"). } } ).addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { op. // Xu ly su kien chon Save menuFile.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { // Hien thi thong bao.showMessageDialog(getContentPane().getSource().isSelected()) //Neu duoc chon op. else // Neu khong duoc chon op.add(chk).showMessageDialog(getContentPane()."Ban vua bo chon is editting").getItem(3)."Ban vua chon Open").addSeparator().showMessageDialog(getContentPane(). 126 .showMessageDialog(getContentPane(). // Them mot muc chon co ten Save menuFile. // Xu ly su kien chon muc Open fileOpen. } } ).menuFile.add("Save"). getContentPane() de lay Container cua Frame op. // Khai bao mot muc chon kieu checkbox JCheckBoxMenuItem chk = new JCheckBoxMenuItem("is editting"). } } ). // Xu ly su kien chon New menuFile. // Them muc chon checkbox vao menu File menuFile."Ban vua chon New").

show(getContentPane(). m. } public static void main(String[] argvs) { MenuBarSample m = new MenuBarSample(). Bộ quản lý cách trình bày (Layout Manager) Dùng để sắp xếp chỗ và định vị cho các đối tượng GUI. 127 . this. m.setLayout(objectsLayout). // Cap phat bo nho cho popup menu jp = new JPopupMenu("Popup"). jp. myWindow. • GridBadLayout: các đối tượng trong khung chứa cũng được đưa vào các ô của một khung lưới vô hình.getModifiers() & InputEvent. East. } } ). kích thước các đối tượng không nhất thiết phải vừa một ô.setJMenuBar(menuBar). Ví du: FlowLayout objectsLayout = new FlowLayout().setLayout(new FlowLayout()).add("New Document").addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent e) { if( (e. • BorderLayout: Các đối tượng được đặt theo đường viền của khung chứa theo các cạnh West.addSeparator(). Nort và Center.e. jp.getX(). South.setSize(300.add("Create"). Các đối tượng giữ nguyên kích thước. Muốn áp dụng ta tạo ra đối tượng trên rồi chuyển nó cho khung chứa. • GridLayout: tạo một khung lưới vô hình với các ô bằng nhau. } } V.400).BUTTON3_MASK)== InputEvent.getY()). Có 5 cách trình bày: • FlowLayout: sắp xếp các đối tượng từ trái qua phải và từ trên xuống dưới.BUTTON3_MASK) jp. • CardLayout: Các đối tượng được đặt vừa vặn với khung chứa và nằm chồng lên nhau như các lá bài.setVisible(true).e. jp.// Dat thanh Menu cho Frame la doi tuong menuBar this. hay có thể viết gọn hơn: myWindow. các đối tượng sẽ đặt vừa kích thước với các ô đó.

Tạo bộ quản lý kiểu BorderLayout: public BorderLayout(). int hgap. int vgap). int vgap). Java hỗ trợ lớp JOptionPane để ta thực hiện công việc này. "South".2 Cách trình bày GridLayout: Phương thức khởi tạo: public GridLayout(int Rows. Xác định khoảng cách giữa các đối tượng quản lý: public GridLayout(int Rows. VI. FlowLayout.1 Cách trình bày FlowLayout: Tạo đối tượng FlowLayout. "East".1 Hộp thoại thông báo Khi cần đưa ra thông báo hay hỏi người dùng một vấn đề gì đó và nhận về câu trả lời. FlowLayout.setLayout(new BorderLayout()). Khi đưa đối tượng vào khung chứa. ta dùng hộp thoại thông báo. 2). ta phải định hình trước đối tượng đó đặt ở đâu: myWindow. align là FlowLayout. hoặc chỉ định luôn cách căn lề bằng phương thức khởi tạo: public FlowLayout(int align).RIGHT. V. Lớp JOptionPane có 4 phương thức tĩnh sau: Tên phương thức Giá trị trả về Ý nghĩa showMessageDialog Không có showConfirmDialog Số int showOptionDialog showInputDialog Số int Chuỗi Hiển thị một thông báo và đợi ấn OK Hiển thị thông báo và đợi xác nhận Ok hay Cancel Hiển thị thông báo và nhận về trả lời từ một danh sách chọn Hiển thị thông báo và nhận về một dòng do user nhập vào icon hiển thị phụ thuộc vào loại thông báo: ERROR_MESSAGE : Thông báo lỗi INFORMATION_MESSAGE : Thông tin WARNING_MESSAGE :Cảnh báo QUESTION_MESSAGE: Hỏi 128 . int Cols. Ví dụ: myWindow. theo các cạnh của khung. ta sử dụng phương thức: public FlowLayout().V.3 Cách trình bày BorderLayout Đối tượng được đặt theo đường viền khung chứa.add("North". int Cols). Các hộp thoại VI. "Center". có 5 kiểu: "North". int hgap. Ví dụ: GridLayout layout = new GridLayout(3. "West".CENTER hoặc chỉ ra khoảng các giữa các đối tượng trên cùng một hàng: public FlowLayout(int align. new Button("on Top")).LEFT. V.

FileFilter. JOptionPane. or JFileChooser.WARNING_MESSAGE).2 Hộp thoại chọn File Khi viết ứng dụng ta gặp các tình huống mở file để đọc hoặc ghi. Swing hỗ trợ một lớp JFileChooser để ta thực hiện công việc này.showSaveDialog: Để hiện thị hộp thoại chọn ghi file Sau đây là các bước để làm việc với hộp thoại chọn file: 1. if (selection == JOptionPane.Tạo một đối tượng JFileChooser: JFileChooser chooser = new JFileChooser().APPROVE_OPTION. JOptionPane.Nếu định chọn trước một file. "Title". hoặc int result = chooser.OK_OPTION) .getSelectedFile().Hiển thị hộp thoại bằng lệnh gọi: int result = chooser. String filename = chooser.")). 2.showOpenDialog(parent).getName().setSelectedFile(new File(filename)). . .setCurrentDirectory(new File(". Ví dụ: int selection = JOptionPane. Các giá trị trả về là JFileChooser.Đặt thư mục cho hộp thoại: chooser.Để cho phép chọn nhiều file: chooser.Lấy vè file hoặc các file được chọn dùng: getSelectedFile() hoặc getSelectedFiles(). } } Sau đó gán cho hộp thoại: chooser. JFileChooser.Mặc định thì chỉ cho phép chọn file. Hai phương thức quan trọng là: . 3.DIRECTORIES_ONLY hoặc JFileChooser. "Message". 6. 7. Neus chỉ muốn lấy tên file thì ta dùng phương thức getPath().showOpenDialog: Để hiện thị hộp thoại chọn mở file .setFileFilter(new GifFilter()).showConfirmDialog(parent.toLowerCase().Nếu muốn giới hạn kiểu file.swing.CANCEL_OPTION.PLAIN_MESSAGE: Giải thích Các hằng số này được truy cập qua JOptionPane. 4.ERROR_OPTION 8.gif") || f. Để dùng được bộ lọc file ta phải thiết kế một lớp kế thừa từ lớp javax.FILES_AND_DIRECTORIES. VI.isDirectory(). Ví dụ bộ lọc file Gif: public class GifFilter extends FileFilter { public boolean accept(File f) { return f.setMultiSelectionEnabled(true).OK_CANCEL_OPTION.endsWith(". 5. nếu muốn cho phép chọn thư mục dùng phương thức: setFileSelectionMode() với các tham số: JFileChooser. 129 .getPath(). có thể đặt: chooser.filechooser.showSaveDialog(parent). dùng bộ lọc file. } public String getDescription() { return "GIF Image".

3 Hộp thoại chọn màu Swing hỗ trợ lớp JColorChooser để người dùng chọn màu. chooser = new JColorChooser().một đối tượng chọn màu .showDialog(parent. Hãy lập trình để xử lý sự kiện click chuột phải lên nền của sổ sẽ hiện một menu Popup. . Viết chương trình trình bày một màn hình như sau: 130 .parent: một companent cha. 4. . Viết chương trình giải phương trình bậc 2 với giao diện GUI. b. false /* not modal */.bộ lắng nghe cho nút bấm Ok và Cancel. . Trường hợp không có nghiệm sẽ hiển thị một hộp thoại thông báo “chương trình vô nghiệm”. Cú pháp sử dụng như sau: Color selectedColor = JColorChooser.chế độ hộp thoại modal hay modeless. } }.title: Tiêu đề hộp thoại. Bài tập 1.title. Yêu cầu chương trình có các ô nhập các hệ số a. Khi làm việc với hộp thoại chọn màu ta cần cung câp: . null /* Không có lắng nghe cho Cancel */). c và cho phép xem kết quả. new ActionListener() // Lắng nghe cho OK { public void actionPerformed(ActionEvent event) { setBackground(chooser. 3. chooser."Background Color". initialColor).createDialog(parent.VI.getColor()). dialog = JColorChooser. Hãy thiết kế một giao diện có nội dung như sau: 2.

131 .

Các câu lệnh trong hàm main() nếu không được đưa vào một luồng riêng thì sẽ được thực hiện tuần tự. Do đó. Phương thức này trả về true nếu ngắt thành công. I. Người lập trình bắt đầu một thread bằng các gọi phương thức start(). • Phương thức setName() đặt tên cho một thread. • Phương thức tĩnh sleep của Thread được gọi với một tham số xác định rằng một thread đang chạy sẽ dừng lại trong bao lâu theo đơn vị phần nghìn giây. Khả năng này của Java gọi là tính đa luồng. Trong mỗi chương trình Java.1 Khái niệm Thread – luồng chỉ một đơn vị chương trình có thể tách khỏi các phần khác của chương trình để thực hiện song song với các phần khác ở từng khoảng thời gian hoặc trong toàn bộ quá trình nó thực hiện. Phương thức toString() trả về tên phương thức.lang có một số constructor: Public Thread (<tên thread>) Public thread(): Khi này thread sẽ có tên là Thread_1. • Phương thức joint đợi (wait) một phản hổi của một thông điệp được gửi đi trước khi thực hiện thread. • Phương thức static currentThread() trả về tham chiếu tới thread hiện hành đang thực hiện.3 Các bước để tạo một thread Sau đây là các bước đơn giản để thực hiện một nhiệm vụ trong một thread riêng: 132 .Đề tài 11.2. Threading Java là ngôn ngữ thông dụng duy nhất hỗ trợ cho lập trình viên các giải pháp lập trình song song. Thread_2. • Phương thức interrupt() được gọi để để ngắt một thread. Trong khi một thread “sleep”. nó trả về điều khiển cho chương trình gọi nó.…. Lập trình viên xác định số lượng các thread được chạy trong chương trình và chúng được thực hiện song song với nhau ở những giai đoạn nào. có một luồng chính được bắt đầu bằng việc gọi hàm main(). Sau khi start() thực hiện xong. Phương thức này có thể được khai báo chồng trong lớp khai báo kế thừa Thread hoặc khai báo cài đặt giao diện Runable. nó sẽ không tiêu tốn tài nguyên CPU và thread khác có thể chạy. các luồng khác có thể phát sinh từ luồng chính này. I. Lớp Thread Lớp Thread trong gói java. • Phương thức start() sẽ ném ra một ngoại lệ IllegalThreadStateException nếu thread cần bắt đầu đã bắt đầu rồi. Khái niệm thread I. getName() lấy tên một thread. I. phương thức start() sau đó sẽ gọi run(). chương trình gọi nó và thread được thực hiện một cách đồng thời. • Phương thức isAlive() trả về true nếu start() đã được gọi và phương thức run() vẫn đang thực hiện. Các công việc của một thread được đặt trong phương thức run(). Phương thức isInterrupted() dùng để kiểm tra xem thread có bị ngắt hay không. độ ưu tiên và nhóm của thread.

một thread running cũng có thể bị chặn (blocked) trong các thao tác vào ra.1. Nếu đang ở trạng thái sleep mà gọi phương thức interrupt().start(). tread sẽ thoát khỏi trạng thái sleep và chuyển sang trạng thái ready. Tạo một đối tượng Thread từ đối tượng Runable trên: Thread t = new Thread(r). Một thread cũng có thể được tạo ra bằng cách xây dựng một lớp con của lớp Thread: class MyThread extends Thread { public void run() { // code của thread } } Sau đó ta cũng làm theo các bước 2. • Trạng thái dead: Khi một Thread ngưng hoặc hoàn thành nhiệm vụ của nó. Khai báo một lớp có cài đặt giao diện Runable với phương thức run() được định nghĩa: class MyRunnable implements Runnable { public void run() { // code thực hiện } } 2. Các trạng thái của thread. Gọi phương thức start() t. Trạng thái born: Khi thread chưa gọi start(). II. Trạng thái running: Một Thread ở trạng thái ready có quyền ưu tiên cao nhất sẽ được chuyển sang trạng thái này. Sau đây là sơ đồ trạng thái của một thread. Tạo một đối tượng của lớp Runnable r = new MyRunnable(). • Trạng thái sleep: Khi Thread gọi phương thức sleep. 4. 3. • • • 133 .3 và 4 để thực hiện thread. Trạng thái ready: Khi phương thức start() được gọi. Ngoài ra. Lúc này nó cũng không sử dụng tài nguyên CPU.

1 Độ ưu tiên của thread Mỗi Thread có một độ ưu tiên. Các thuộc tính của thread III. Mặc định thì thread thừa kế độ ưu tiên từ thread cha của nó.là thread đã gọi nó. III. Trình từ thực hiện của các thread theo độ ưu tiên của nó được minh họa như sau: 134 .Khi một thread đang chạy gọi phương thức wait(). thread sẽ rơi vào một trạng thái wait để đợi một đối tượng mà nó đã gọi. Ta có thể tăng hoặc giảm độ ưu tiên của bất kỳ thread nào với phương thức setPriority() bằng một giá trị nằm giữa MIN_PRIORITY(1) và MAX_PRIORITY (10).

. ta dùng phương thức: g.Các thread có độ ưu tiên càng cao thì khả năng thực hiện càng cao. Để ngắt tất cả các thread trong nhóm g ta gọi: g.2 Nhóm thread Các thread có thể được đưa vào cùng một nhóm để có thể đồng thời làm việc với cả nhóm thread này.interrupt(). Khai báo một nhóm Thread: String groupName = . . III. Không có mệnh đề catch nào được thực hiện mà 135 . Các thread có cùng độ ưu tiên sẽ được xếp vào một hàng đợi. ThreadGroup g = new ThreadGroup(groupName) Sau đó. threadName). activeCount(). . Để kiểm tra xem có thread nào trong nhóm g còn hoạt động không. với mỗi thread được tạo ra ta dùng constructor có khai báo nhóm thread: Thread t = new Thread(g.3 Quản lý các ngoại lệ của thread Phương thức run() không thể ném ra một ngoại lệ được kiểm soát mà bị kết thúc bởi một ngoại lệ không kiểm soát được mỗi khi có lỗi. III.

không có gì xảy ra.1 Interrupt một thread Khi sử dụng phương thức Thread. Lý do là thread bị dừng lại trong một khoảng thời gian lâu và trong khoảng thời gian đó nó không thể tự đánh thức nó được..err. ngoại lệ này sẽ được gửi cho một bộ xử lý ngoại lệ không được kiểm soát. Throwable e). public class SleepyHead extends Thread { // Phương thức được chạy khi thread khởi động lần đầu public void run() { System.").sleep(int) thì chương trình thường phải bắt các ngoại lệ để xử lý.println ("Đó là một giấc ngủ trưa").println ("Chỉ mới được hơn 5 phút thôi. Mgoaif ra ta có thể cài bộ xử lý ngoại lệ mặc định cho tất cả các thread bằng cách gọi phương thức setDefaultUncaughtExceptionHandler của lớp Thread. nếu Throwable là một đối tượng của TheadDead. Khi này. IV. nếu một thread cần phải được đánh thức sớm hơn. nếu phương thức Thread. ta có thể cài bộ xử lý ngoại lệ cho bất cứ thread nào bằng phương thức: setUncaughtExceptionHandler(). Điều khiển các thread Sau khi đã khởi động được một thread rồi. Từ phiên bản Java 1.println ("Thread đang ngủ. phương thức uncaughtException sẽ làm các việc sau: 1. IV. 4.IOException { 136 .. vấn đề tiếp theo sẽ là điều khiển thread. trước khi thread bị dead. 3.Ngược lại.Nếu là null. System.out.thay vào đó. try { // Ngủ trong 8 tiếng Thread. Bộ xử lý này phải thuộc một lớp có cài đặt giao diện Thread. } } // Phương thức main tạo và bắt đầu thread public static void main(String args[]) throws java..err và đưa ra màn hình. Nếu không cài bộ xử lý ngoại lệ cho một thread thì mặc định là null.getDefaultExceptionHandler trả về một bộ xử lý không phải là null thì bộ xử lý này được gọi. tên của thread và stack trace được gửi tới System. Tuy nhiên. ta có thể ngắt nó dùng phương thức interrupt(). Hãy đánh thức nó").Nếu nhóm thread có cài đặt uncaughtException thì phương thức đó được gọi.io.5.sleep( 1000 * 60 * 60 * 8 ).out. 2. Tuy nhiên. } catch (InterruptedException ie) { System.Nếu không.UncaughtExceptionHandler chỉ với 1 phương thức: void uncaughtException(Thread t. các thread riêng lại phụ thuộc vào bộ xử lý của nhóm thread chứa nó.

System. // bắt đầu thread sleepy. // Ngắt thread sleepy.println ("Nhấn Enter để ngưng thread"). sau đó gửi một thông điệp ngắt tới thread đang ngủ.) { // In ra biến count và tăng giá trị cho nó System.in.in. Điều này yêu cầu thread điều khiển phải giữ một tham chiếu tới thread muốn dừng. }} Cách thực hiện ở đây là gửi một thông điệp từ một thread khác để đánh thức một thread đang ngủ.out.print (count++ + " ").start(). System. System..read().hàm main. thread chính.sleep(500).read().stop().out.stop().println ("Nhấn Enter để dừng đếm"). IV. public class StopMe extends Thread { // Phương thức được thực hiện khi thread khởi động lần đầu public void run() { int count = 1. // Nhắc người dùng để dừng thread System.// Tạo một thread Thread sleepy = new SleepyHead().start().out. }} 137 .println ("Thread đếm!"). counter.2 Dừng một thread Đôi khi ta muốn một thread dừng lại trước khi nhiệm vụ của nó hoàn thành.interrupt(). for (.IOException { // Tạo và bắt đầu thread Thread counter = new StopMe(). Một thread (gọi là thread điều khiển) có thể gửi một thông điệp dừng tới một thread khác bằng việc gọi phương thức Thread.out.sẽ đợi cho người dùng ấn enter. // Nhắc người dùng System.io. Ở đây. } catch (InterruptedException ie) {} }} // phương thức main public static void main(String args[]) throws java. // Dừng thread counter. // Ngủ nửa giây try { Thread.

4 Giải phóng thời gian cho CPU Khi một thread rơi vào trạng thái đợi một sự kiện xảy ra hoặc đi vào một vùng mã lệnh mà nếu giải phóng thời gian cho CPU sẽ nâng cao hiệu quả của hệ thống...").out.}} 138 . dying. dying. Ta không thể giải phóng thời gian CPU của bất kỳ thread nào mà chỉ đối với thread hiện thời. Một cách hiệu quả là gọi phương thức joint() để đợi một thread kết thúc công việc. thread nên giải phóng thời gian hệ thống hơn là dùng sleep() để nghỉ trong thời gian dài.println ("thread chuẩn bị nghỉ.InterruptedException { // Tạo thread Thread dying = new WaitForDeath().join().…Ta dùng phương thức isAlive() để xác định thread còn chạy không.println ("Thread đã dừng"). } catch (InterruptedException ie) {} } // phương thức main public static void main(String args[]) throws java. public class WaitForDeath extends Thread { // Phương thức run() public void run() { System.out.lang. Để làm điều này ta dùng phương thức static yield() của Thread để giải phóng thời gian CPU cho thread hiện thời. IV.sleep(5000). Tuy nhiên.IV. // Nhắc user System. // Nghỉ trong 5 giây try { Thread.start(). IV.. Trong trường hợp này.out. nếu thường xuyên dùng phương thức này để kiểm tra sau đó dùng sleep() hoặc yield() thì hiệu quả sử dụng CPU sẽ rất thấp. System.3 Tạm dừng và phục hồi một thread Các phương thức suspend() dùng để tạm dừng một thread trong khi resume() dùng để tiếp tục một thread đã bị suspend. Tuy nhiên sử dụng các thread này rất hay gây ra tình trạng deadlock do thread bị suspend đang chiếm giữ một tài nguyên và không giải phóng trong khi nhiều thread khác có thể đang đợi sử dụng tài nguyên đó.5 Đợi một thread kết thúc công việc Đôi khi ta cần đợi cho một thread kết thúc một công việc nào đó như gọi một phương thức hay đọc một thuộc tính thành phần.println ("Đợi cho thread kết thúc").

2f from %d to %d". public void run() { try { int toAccount = (int) (bank. System. tức là cùng thực hiện câu lệnh: account[to] += amount. bank. accounts[to] += amount. Chương trình trên chạy và không bao giờ dừng lại. 139 .transfer(fromAccount.. Tuy nhiên. amount. Thread.sleep((int) (DELAY * Math. Điều gì xảy ra nếu cả hai thread cùng truy cập đến đối tượng và làm thay đổi thuộc tính đối tượng.printf(" Số dư: %10.2f%n"..random()). Nếu account chuyển không đủ tiền.1 Tình trạng “đua tranh” Trong phần tiếp theo. } Sau đây là đoạn code cho class transferRunnable: class TransferRunnable implements Runnable { . Đồng bộ thread Trong hầu hết các chương trình đa luồng. ta phải ấn Ctrl + C để dừng nó.currentThread()). Kết quả có thể là các thread bị ảnh hưởng lẫn nhau và không đạt được kết quả mong muốn. getTotalBalance()).out.random())). public void transfer(int from. trong một số tình huống chương trình trên có thể gây lỗi và in ra tổng số tiền khác nhau. double amount) { System. V. from. ta không biết được trong mỗi tài khoản còn bao nhiêu tiền nhưng tổng số tiền của tất cả các tài khoản là không đổi.print(Thread.V. Mỗi tài khoản có một thread riêng.size() * Math. giao dịch kết thúc ngay. int to. đó là khi có nhiều hơn một tài khoản cùng chuyển tiền đến một tài khoản khác. Chúng ta thử thiết kế một chương trình để chuyển tiền ngẫu nhiên giữa các tài khoản. amount). to). System.random(). Tình trạng này gọi là “đua tranh”. chúng ta mô phỏng một ngân hàng có rất nhiều tài khoản khách hàng. Mỗi giao dịch thực hiện việc chuyển tiền từ account sang một account ngẫu nhiên khác. } catch(InterruptedException e) {} } } Khi chương trình chạy.out. double amount = maxAmount * Math. các thread có thể cần phải truy cập đến cùng một đối tượng. toAccount. Ta có một class Bank với phương thức transfer để chuyển tiền.printf(" %10. accounts[from] -= amount.out.

lock(). Java 5. Thread_1 thực hiện xong bước 1 và 2 thì bị ngắt. // đối tượng ReentrantLock try { //Đoạn lệnh cần bảo vệ } finally { myLock.2 Khóa đối tượng Trong ví dụ trên. System.2f%n". Từ phiên bản Java 5.Load kết quả ngược trả lại cho account[to] Giả sử có 2 thread là thread_1 và thread_2 cùng thực hiện đến dòng lệnh này.out. account[to] lúc này đã ghi đè giá trị do thread_2 cập nhật. Bây giờ chúng ta sẽ khóa phương thức transfer() trong lớp Bank: public class Bank { public void transfer(int from. amount.Cộng với account 3. trong một thời điểm sẽ chỉ có một thread được truy cập vào một đoạn mã lệnh nào đó.lock().out. V. Điều này dẫn tới việc tổng số tiền bị thay đổi. Các phiên bản trước của Java sử dụng từ khóa synchronized. int to. 140 .0 giới thiệu thêm lớp ReentrantLock cho mục đích này. from. phép tính này lại không phải là atomic. Tuy nhiên. accounts[from] -= amount. // đảm bảo khóa được mở kể cả khi exception xảy ra } Đoạn lệnh này đảm bảo rằng chỉ có một thread tại một thời điểm có thể đi vào vùng được bảo vệ. getTotalBalance()). try { if (accounts[from] < amount) return.unlock(). System. CPU cũng chỉ phục vụ được cho một thread. Khi một thread đầu tiên đã gọi lock thì không một thread nào sau đó có thể vượt qua lệnh lock().Load giá trị account[to] vào thanh ghi 2. Cấu trúc đoạn lệnh căn bản để sử dụng cơ chế này là: myLock. công việc có thể phải làm là: 1.Giả sử đây là một hành vi đơn vị (atomic. int amount) { bankLock. sau đó thread_2 sẽ thực hiện câu lệnh trên với đầy đủ 3 bước tức là account[to] đã bị thay đổi giá trị.currentThread()).2f from %d to %d".hành vi chỉ chiếm một thao tác thực hiện lệnh của CPU). khi đó mỗi thread sẽ thực hiện phép tính này một cách tuần tự mà không gây ảnh hưởng vì trong một thời điểm.0 có hỗ trợ hai cơ chế để bảo vệ một khối lệnh khỏi sự truy cập đồng thời. System.printf(" %10. phần tiền do thread_2 chuyển cho account[to] đã bị mất. to).print(Thread. thread_1 thức dậy và làm tiếp bước 3. accounts[to] += amount.out.printf(" Total Balance: %10. nếu ta đảm bảo rằng phương thức transfer() được thực hiện thành công trước khi thread bị ngắt thì sẽ không có vấn đề gì xảy ra. Tiếp theo. Có nghĩa là.

Đến đây..3 Đối tượng điều kiện Trong trường hợp thread đi vào vùng bảo vệ. 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. private Lock bankLock = new ReentrantLock(). Khi có điều kiện này. 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. chẳng hạn ở đây. } } Việc đợi ở đây sẽ kết thúc khi một thread khác chuyển tiền vào cho nó. 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.unlock(). 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.... 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. int amount) { bankLock. Đây là tình huống mà ta phải sử dụng đối tượng điều kiện: class Bank { public Bank() 141 .unlock(). // ReentrantLock là một lớp cài đặt giao diện lock.transfer(from.lock().. try { while (accounts[from] < amount) // Đợi cho đến khi tài khoản của nó có đủ tiền { // đợi .. to. tức là công việc của nó là không hữu ích. } V.getBalance(from) >= amount) bank. } // Chuyển tiền . 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. 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 đó. } finally { bankLock.} finally { bankLock. int to. } } . amount).

await(). sau khi cộng tiền vào cho tài khoản nhận và thì signalAll() sẽ được gọi. Một thread chỉ có thể gọi các phương thức signalAll(). sufficientFunds = bankLock.vị trí gọi phương thức await() và kiểm tra lại điều kiện. Một thread thực hiện xong việc chuyển tiền. } } 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.{ . chương trình sẽ bị treo. 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ệ. nó nên gọi: sufficientFunds. private Condition sufficientFunds. int amount) { bankLock. Ở đây. } 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. } finally { bankLock.lock(). 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(). 142 . sign() và await() trong vùng được bảo vệ.signalAll() để mở khóa cho các thread đang nằm đợi thỏa mãn điều kiện đủ tiền. Nếu tất cả các thread khác đều đang bị chặn. try { while (accounts[from] < amount) sufficientFunds. 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 đó . // Chuyển tiền . Một khi thread đã thoát khỏi tình trạng đợi do await() gây ra. int to.newCondition(). 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. 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.unlock(). 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.. Một phương thức await() nên được gọi trong một vòng lặp đợi: while (!(đủ tiền)) condition. 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(). 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().await(). 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ả.. } .signalAll()... public void transfer(int from. sufficientFunds.Lúc này nó sẽ nằm chờ thread khác chuyển tiền..await()..

Nếu chẳng may người đang thực hiện chuyển số tiền lớn hơn anh ta có. mỗi người chuyển cho một người khác trong số 9 người còn lại. 9 người khác phải chờ ngoài cổng. 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. 2. 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. 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. Một trong số 9 người ngoài cổng sẽ được đi vào trong ngân hàng. người được gửi tiền sẽ được vào trong ngân hàng và giữ khóa cổng. thực hiện việc chuyển tiền. sau đó những người đang đợi cũng quay ra cổng để đợi đến lượt vào. 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. Sau khi chuyển xong. Mỗi thời điểm ngân hàng chỉ chuyển tiền cho một người. Bài tập 1. 143 .Chúng ta có thể kết thúc phần này bằng một câu chuyện minh họa: Có 10 người cùng đến ngân hàng để chuyển tiền cho nhau.

Các từ khóa của Java Từ khóa abstract assert boolean break byte case catch char class const continue default do double else extends final finally float for goto if implements import instanceof int interface long Ý nghĩa Một lớp hoặc phương thức trừu tượng Được sử dụng để định vị lỗi nội bộ chương trình Kiểu boolean Thoát khỏi lệnh switch hoặc các vòng lặp Số nguyên 1 byte Một lựa chọn của switch Một mệnh đề của khối Try để bắt một ngoại lệ Kiểu ký tự Unicode Định nghĩa một class Không được sử dụng Tiếp tục tại vị trí cuối vòng lặp hiện thời Mệnh đề mặc định của switch Phần trên của vòng lặp do/while Kiểu số thực floating-number 8 byte Mệnh đề else của một lệnh if Xác định lớp cha của một lớp Một hằng số. Một phần của khối try mà luôn được thực hiện Số thực 4 byte Một kiểu vòng lặp Không sử dụng Một lệnh điều khiển rẽ nhánh Chỉ ra các interfaces mà lớp sẽ cài đặt. hoặc một lớp hay phương thức không thể bị khai báo chồng. Nhập một package Kiểm tra xem đối tượng có phải là biểu hiện của một lớp Số nguyên 4 byte 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 Số nguyên 8 byte 144 .Phụ lục A.

int. x có thể là các kiểu long. Trả về giá trị trong một phương thức Kiểu số nguyên 2 byte. 7. 8. Cấp phát vùng nhớ cho một đối tượng hoặc mảng mới Một tham chiếu null Một gói các lớp Giới hạn phạm vi truy cập chỉ trong lớp Giới hạn phạm vi truy cập trong lớp.} 1. acos(double x) = arccos(x). atan(double x) = arctag(x).math..0 .. x từ -PI/2 . asin(double x) = arcsin(x). lớp java.lang. log(double x) = Ln(x).. ceil(double x): làm cận trên hoặc cận dưới của số x. PI/2 4. PI 3. abs(number x): lấy |x|. 6. các lớp dẫn xuất và các lớp trong cùng gói Không giới hạn phạm vi truy cập. 145 .Math. x từ 0. float. double.. 5. Một giá trị tồn tại ở phạm vi lớp Use strict rules for floating-point computations Đối tượng hoặc constructor lớp cha Câu lện lựa chọn đối tượng ngầm định của một lớp quăng ra một ngoại lệ Các exceptions mà một phương thức có thể quăng Đánh dấu dữ liệu không cố định Khối lệnh bắt lỗi Ký hiệu cho một phương thức không trả về giá trị ensures that a field is coherently accessed by multiple threads Vòng lặp synchronized Một phương thức hoặc khối lệnh chỉ thuộc về một thread Phụ lục B Một số hàm hay sử dụng a) Hàm toán học. cos(double x) = cos(x). x là radian.Từ khóa Native new null package private protected public return short static strictfp super switch this throw tHRows transient try void volatile while Ý nghĩa phương thức được cài đặt bằng ngôn ngữ khác. 2.*. exp(double x) = ex. {java.

long. date lấy giá trị từ 1. năm thực = date. y}.. năm.9.. number y) = min{x. 12. Horstmann. Lấy mốc là 1900. 0 = CN.. 2. 5. 13. max(number x. tháng. String(String s) : Khởi động một chuỗi bằng chuỗi s. 11. 3. 8.lang. Addison Wesley. getMinutes(): trả về giá trị int chỉ phút trong giờ. [3] David Reilly. min(number x. 8. 10.util.getYear() +1900.11). getYear(): trả về giá trị int là năm. y có thể là kiểu int. toLowerCase(): thay đổi chuỗi thành chữ thường. 15. setDate(int date) đặt lại ngày trong biến. random(): cho một số ngẫu nhiên trong [0. Prentice Hall PTR. [4] Deitel & Associates (2001). Tài liệu tham khảo [1] Alistair Cockburn (2000). “Network Programming and Distributed Computing”. 7.Date. month có giá trị 0.11. 15. Lớp Date khai báo java. 1. fourth edition. charAt(int i): trả về một ký tự thứ sau i. long. 9. indexOf(int ch): trả về vị trí trước của ký tự ch đầu tiên tìm thấy. “Writing Effective Use Cases”. sqrt(double x) = 16. giờ.tên_hàm. ngày. length() : trả về giá trị int là độ dài một chuỗi. 5. “Core Java™ 2”. getDate(): trả về giá trị của ngày trong tháng. getTime(): trả về là một số được tính theo giây đồng hồ. setYear(int year): thay đổi giá trị năm trong biến date. (year + 1900). 4. sin(double x) = sin(x).2.. . double y) = xy.. y}.31 11. round(number x): làm tròn số x. setSeconds(int i): thay đổi giá trị giây trong biến date. khai báo java. 1. nếu x là kiểu float thì thành kiểu int. [2] Cay S. volume 1. double. How to program”. Addison-Wesley Longman. float.String. Michael Reilly (2002). getMonth(): trả về giá trị int là tháng trong năm (0. String() : Khởi động một đối tượng chuỗi. 6 = Sat. 3. float. 12.. b) Lớp String. Gary Cornell (2004). trong đó x. 13. “Java. double. 14.0]. 4. 1 = mon. 6.. 2. setMonth(int month): thay đổi giá trị tháng trong biến date. pow(double x. 146 . 6. 10. getDay(): trả về giá trị int là thứ trong tuần. getHours(): trả về giá trị int chỉ giờ trong ngày. 14. setHours(int hour): thay đổi giá trị giờ trong biến date. 7. setMinutes(int i): thay đổi giá trị phút trong biến date. tan(double x) = tg(x). 1. nếu x là kiểu double thì thành kiểu long. toUpperCase(): chuyển đổi chuỗi thành chữ HOA. number y) = max{x. Khi sử dụng ta phải dùng Math. y có thể là kiểu int. getSeconds(): trả về giá trị int chỉ giây đồng hồ trong phút. trong đó x. concat(String str): nối thêm chuỗi str vào sau.0. Date(): cho thứ.

Sign up to vote on this title
UsefulNot useful