Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 202 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
202
Dung lượng
8,58 MB
Nội dung
Mục lục GIỚI THIỆU Chương MỞ ĐẦU .6 1.1 KHÁI NIỆM CƠ BẢN 11 1.2 ĐỐI TƯỢNG VÀ LỚP .11 1.3 CÁC NGUYÊN TẮC NỀN TẢNG .13 Chương NGÔN NGỮ JAVA 18 2.1 ĐẶC TÍNH CỦA JAVA .18 2.1.1 Máy ảo Java – Java Virtual Machine 19 2.1.2 Các tảng Java 21 2.1.3 Mơi trường lập trình Java 21 2.1.4 Cấu trúc mã nguồn Java 22 2.1.5 Chương trình Java 23 2.2 BIẾN 25 2.3 CÁC PHÉP TOÁN CƠ BẢN .25 2.3.1 Phép gán 25 2.3.2 Các phép toán số học .26 2.3.3 Các phép toán quan hệ 26 2.3.4 Độ ưu tiên phép toán 27 2.4 CÁC CẤU TRÚC ĐIỀU KHIỂN 28 2.4.1 Các cấu trúc rẽ nhánh 28 2.4.2 Các cấu trúc lặp 33 2.4.3 Biểu thức điều kiện cấu trúc điều khiển 40 Chương LỚP VÀ ĐỐI TƯỢNG .44 3.1 TẠO VÀ SỬ DỤNG ĐỐI TƯỢNG 45 3.2 TƯƠNG TÁC GIỮA CÁC ĐỐI TƯỢNG 46 Chương BIẾN VÀ CÁC KIỂU DỮ LIỆU .51 4.1 BIẾN VÀ CÁC KIỂU DỮ LIỆU CƠ BẢN 51 4.2 THAM CHIẾU ĐỐI TƯỢNG .53 4.3 Phép gán .54 4.3.1 Các phép so sánh .55 4.4 CUỘC ĐỜI CỦA ĐỐI TƯỢNG TRONG BỘ NHỚ HEAP 56 4.5 Mảng .56 Chương HÀNH VI CỦA ĐỐI TƯỢNG .62 5.1 PHƯƠNG THỨC VÀ TRẠNG THÁI ĐỐI TƯỢNG 62 5.2 TRUYỀN THAM SỐ VÀ GIÁ TRỊ TRẢ VỀ .63 5.3 Cơ chế truyền giá trị 65 5.4 Đóng gói phương thức truy nhập 66 5.5 Khai báo khởi tạo biến thực thể 70 5.6 Biến thực thể biến địa phương 71 Chương SỬ DỤNG THƯ VIỆN JAVA 75 6.1 ArrayList .75 6.2 SỬ DỤNG JAVA API 76 6.3 MỘT SỐ LỚP THÔNG DỤNG TRONG API 78 6.3.1 Math 78 6.3.2 Các lớp wrapper 79 6.4 Các lớp biểu diễn xâu kí tự 80 6.5 Trò chơi bắn tàu 81 Chương THỪA KẾ VÀ ĐA HÌNH 92 7.1 QUAN HỆ THỪA KẾ 92 7.2 THIẾT KẾ CÂY THỪA KẾ 93 7.3 OVERRIDING – PHƯƠNG THỨC NÀO ĐƯỢC GỌI? 96 7.4 Các quan hệ IS-A HAS-A .97 7.5 KHI NÀO NÊN DÙNG QUAN HỆ THỪA KẾ? .99 7.6 LỢI ÍCH CỦA QUAN HỆ THỪA KẾ 99 7.7 ĐA HÌNH 100 7.8 CÁC QUY TẮC CHO OVERRIDE 102 7.9 OVERLOAD PHƯƠNG THỨC 104 7.10 CÁC MỨC TRUY NHẬP 105 Chương LỚP TRỪU TƯỢNG VÀ INTERFACE .110 8.1 Một số lớp không nên tạo thực thể 110 8.2 LỚP TRỪU TƯỢNG VÀ LỚP CỤ THỂ 112 8.3 Phương thức trừu tượng 112 8.4 VÍ DỤ VỀ ĐA HÌNH 113 8.5 Lớp Object 114 8.6 Đổi kiểu, đối tượng hành vi .115 8.6.1 Chuyển kiểu tham chiếu trở lại kiểu đối tượng thực tế.118 8.7 Đa thừa kế vấn đề Hình thoi .118 8.8 Cấu trúc interface .121 8.9 Gọi phiên phương thức lớp cha 123 Chương CUỘC ĐỜI CỦA MỘT ĐỐI TƯỢNG 126 9.1 Bộ nhớ stack nhớ heap 126 9.2 Khởi tạo đối tượng 128 9.2.1 Khởi tạo trạng thái đối tượng 129 9.3 Hàm tạo vấn đề thừa kế .132 9.3.1 Truyền đối số cho hàm tạo lớp cha 134 9.4 Hàm tạo overload 135 9.5 Cuộc đời đối tượng 136 Chương 10 THÀNH VIÊN LỚP VÀ THÀNH VIÊN THỰC THỂ .139 10.1 Biến lớp .139 10.2 Phương thức lớp 140 10.3 Giới hạn phương thức lớp 142 10.4 Khởi tạo biến lớp 143 10.5 Thành viên final .144 Chương 11 NGOẠI LỆ 147 11.1 Ngoại lệ 147 11.1.1 Tình cố 147 11.1.2 Xử lý ngoại lệ 150 11.1.3 Ngoại lệ đối tượng 151 11.2 Khối try/catch 152 11.2.1 Bắt nhiều ngoại lệ 152 11.2.2 Hoạt động khối try/catch .153 11.2.3 Khối finally – việc phải làm trường hợp 155 11.2.4 Thứ tự cho khối catch .156 11.3 Ném ngoại lệ 157 11.3.1 Phân loại ngoại lệ – checked unchecked 158 11.4 Né ngoại lệ 158 Chương 12 CHUỖI HÓA ĐỐI TƯỢNG VÀ VÀO RA FILE 163 12.1 Quy trình ghi đối tượng 164 12.2 Chuỗi hóa đối tượng 165 12.3 Khôi phục đối tượng 168 12.4 Ghi chuỗi kí tự file text .171 12.4.1 Lớp File 172 12.4.2 Bộ nhớ đệm 173 12.5 Đọc file text .173 12.6 Các dòng vào Java API .175 Chương 13 LẬP TRÌNH TỔNG QUÁT VÀ CÁC LỚP COLLECTION 179 13.1 Lớp tổng quát 180 13.2 Phương thức tổng quát 182 13.3 Các cấu trúc liệu tổng quát Java API 183 13.4 Iterator vòng lặp for each 185 13.5 So sánh nội dung đối tượng 187 13.5.1 So sánh 187 13.5.2 So sánh lớn hơn/nhỏ 189 13.6 Wildcard khai báo tham số kiểu 191 Phụ lục A DỊCH CHƯƠNG TRÌNH BẰNG JDK 196 Phụ lục B PACKAGE – TỔ CHỨC GÓI CỦA JAVA 199 Tµi liƯu tham kh¶o 202 Giíi thiƯu Phần mềm ngày lớn phức tạp đòi hỏi cập nhật liên tục để đáp ứng yêu cầu người dùng Phương pháp lập trình thủ tục truyền thống dần trở nên khơng đáp ứng đòi hỏi ngành cơng nghiệp phần mềm Lập trình hướng đối tượng đời bối cảnh để hỗ trợ sử dụng lại phát triển phần mềm qui mơ lớn Giáo trình cung cấp cho sinh viên kiến thức từ số kỹ thuật nâng cao phương pháp lập trình hướng đối tượng Giáo trình dùng cho sinh viên ngành Cơng nghệ thơng tin có kiến thức lập trình Giáo trình sử dụng ngơn ngữ lập trình Java để minh họa đồng thời giới thiệu số kiến thức ngơn ngữ Các nội dung phương pháp lập trình hướng đối tượng trình bày giáo trình bao gồm lớp đối tượng, đóng gói/che giấu thơng tin, kế thừa đa hình, xử lý ngoại lệ lập trình tổng qt Ngồi ra, giáo trình trình bày kiến thức Java bao gồm đặc trưng ngôn ngữ, thư viện cách thức tổ chức vào/ra liệu Thay cách trình bày theo tính hàn lâm chủ đề rộng, để thuận tiện cho giảng dạy, giáo trình chọn cách trình bày theo học cụ thể xếp theo trình tự kiến thức từ sở đến chuyên sâu Mỗi chủ đề giảng dạy với thời lượng 2~3 lý thuyết thực hành tương ứng Các tác giả chân thành cảm ơn PGS TS Nguyễn Đình Hóa, TS Trương Anh Hồng đồng nghiệp Khoa Công nghệ thông tin, Trường Đại học Công nghệ đọc thảo giáo trình có góp ý q báu nội dung chun mơn cách thức trình bày Tuy vậy, giáo trình nhiều khiếm khuyết, tác giả mong tiếp tục nhận góp ý đồng nghiệp sinh viên để hoàn thiện tương lai Chương më ®Çu Một chương trình chất lượng tốt cần có thiết kế tốt Nếu lao vào lập trình mà bỏ qua cơng đoạn thiết kế khơng thể xây dựng chương trình có độ phức tạp cao Ngành công nghiệp phần mềm tập trung vào việc xây dựng chương trình chạy viết tốt Công việc kĩ sư phần mềm sử dụng phương pháp chứng minh chấp nhận cho việc phân tích tốn cần giải thiết kế chương trình giải tốn Trong thập kỷ 1970, 1980, phương pháp kĩ nghệ phần mềm chủ yếu lập trình có cấu trúc (structured programming) Cách tiếp cận cấu trúc việc thiết kế chương trình dựa chiến lược chia để trị: Để giải toán lớn, chia thành vài tốn nhỏ giải riêng bài; để giải bài, coi tốn tiếp tục chia thành tốn nhỏ hơn; cuối cùng, ta đến tốn giải mà không cần phải chia tiếp Cách tiếp cận gọi top-down programming Top-down programming khơng có sai Đây cách tiếp cận giá trị thường áp dụng cho việc giải vấn đề Tuy nhiên, khơng đủ Trước hết, đáp ứng việc tạo lệnh cần thiết quy trình để giải toán Dần dần, người ta nhận thiết kế cấu trúc liệu cho chương trình có tầm quan trọng khơng việc thiết kế hàm/thủ tục cấu trúc điều khiển Top-down programming khơng quan tâm đủ đến liệu mà chương trình cần xử lý Thứ hai, với top-down programming, ta khó tái sử dụng phần chương trình cho chương trình khác Bằng việc xuất phát từ tốn cụ thể chia thành mảnh cho thuận, cách tiếp cận có xu hướng tạo thiết kế đặc thù cho tốn Ta khó có khả lấy đoạn mã lớn từ chương trình cũ lắp vào dự án mà sửa đổi lớn Việc xây dựng chương trình chất lượng cao khó khăn tốn kém, nhà phát triển phần mềm luôn muốn tái sử dụng sản phẩm cũ Thứ ba, môi trường hoạt động thực tế ứng dụng thay đổi Dẫn đến việc yêu cầu phần mềm phải liên tục thay đổi theo để đáp ứng nhu cầu người dùng không muốn phần mềm bị đào thải Do đó, thiết kế linh hoạt mềm dẻo mà nhà phát triển phần mềm mong muốn Phương pháp bottom-up hỗ trợ tốt cho tính linh hoạt mềm dẻo Do đó, thực tế, thiết kế top-down thường kết hợp với thiết kế bottom-up Trong thiết kế bottom-up, cách tiếp cận xuất phát từ lên, từ vấn đề mà ta biết cách giải có sẵn thành phần tái sử dụng Từ đó, ta xây dựng dần theo hướng lên trên, hướng đến giải pháp cho toán tổng Các thành phần tái sử dụng nên có tính mơ-đun hóa cao Một mô-đun thành phần hệ thống lớn hơn, tương tác với phần lại hệ thống theo cách đơn giản quy ước chặt chẽ Ý tưởng mơ-đun "lắp vào" hệ thống Chi tiết xảy bên mơ-đun khơng quan trọng với hệ thống nói chung, miễn mơ-đun hồn thành tốt vai trò giao Đây gọi che giấu thông tin (information hiding), nguyên lý quan trọng công nghệ phần mềm Một dạng thường thấy mô-đun phần mềm chứa số liệu kèm theo số hàm/thủ tục để xử lý liệu Ví dụ, mơ-đun sổ địa chứa danh sách tên địa chỉ, kèm theo hàm/thủ tục để thêm mục tên mới, in nhãn địa chỉ…Với cách này, liệu bảo vệ xử lý theo cách biết trước định nghĩa chặt chẽ Ngoài ra, tạo thuận lợi cho chương trình sử dụng mơ-đun này, chương trình khơng phải quan tâm đến chi tiết biểu diễn liệu bên mô-đun Thông tin biểu diễn liệu che giấu Các mô-đun hỗ trợ dạng che giấu thông tin bắt trở nên phổ biến ngôn ngữ lập trình đầu thập kỷ 1980 Từ đó, hình thức tiên tiến ý tưởng lan rộng ngành công nghệ phần mềm Cách tiếp cận gọi lập trình hướng đối tượng (object-oriented programming), thường gọi tắt OOP Câu chuyện tưởng tượng sau đây1 minh họa phần khác biệt lập trình thủ tục lập trình hướng đối tượng thực tế ngành công nghệ phàn mềm Có hai lập trình viên nhận đặc tả hệ thống yêu cầu xây dựng hệ thống đó, thi xem người hồn thành sớm Dậu người chuyên dùng phương pháp lập trình thủ tục, người kia, Tuất, quen dùng lập trình hướng đối tượng Cả Dậu Tuất cho nhiệm vụ đơn giản Đặc tả sau: Dậu tính tốn, "Chương trình phải làm gì? Ta cần đến thủ tục nào?" Anh tự trả lời, "xoay chơi nhạc." Và anh bắt tay vào viết thủ tục Chương trình khơng phải loạt thủ tục gì? Trong đó, Tuất nghĩ, "Trong chương trình có thứ đâu nhân tố chính?" Đầu tiên, nghĩ đến Hình vẽ Ngồi ra, anh nghĩ đến đối tượng khác người dùng, âm thanh, kiện click chuột Nguồn: Head First Java, 2nd Edition Nhưng anh có sẵn thư viện mã cho đối tượng đó, nên anh tập trung vào việc xây dựng Hình vẽ Dậu thạo với công việc kiểu rồi, anh bắt tay vào viết thủ tục quan trọng nhanh chóng hồn thành hai thủ tục xoay (rotate) chơi nhạc (playSound): rotate(shapeNum) { // cho hình xoay 360o } playSound(shapeNum) { // dùng shapeNum để tra xem cần chơi file AIF // chơi file } Còn Tuất ngồi viết ba lớp, lớp dành cho hình Dậu vừa nghĩ thắng sếp nói "Về mặt kĩ thuật Dậu xong trước, ta phải bổ sung chút xíu vào chương trình." Hai người q quen với chuyện đặc tả thay đổi – chuyện thường ngày ngành Đặc tả bổ sung nội dung sau: Đối với Dậu, thủ tục rotate ổn, mã dùng bảng tra cứu để khớp giá trị shapeNum với hình đồ họa cụ thể Nhưng playSound phải sửa Rốt cục sửa nghiêm trọng, Dậu thấy không thoải mái phải động vào sửa phần mã test xong từ trước Anh biết, dù quản lý dự án có nói nữa, đặc tả thay đổi suốt Còn Tuất thản nhiên vừa nhâm nhi cà phê vừa viết lớp Điều anh thích OOP anh khơng phải sửa phần mã test bàn giao Anh nghĩ ích lợi OOP lẩm bẩm "Tính linh hoạt, khả mở rộng, " Dậu vừa kịp hoàn thành lát trước Tuất Nhưng nụ cười anh tắt nhìn thấy mặt sếp nghe thấy giọng sếp vẻ thất vọng "không rồi, amoeba thực khơng xoay kiểu " Thì hai lập trình viên viết đoạn xoay hình theo cách: (1) xác định hình chữ nhật bao hình; (2) xác định tâm hình chữ nhật xoay hình quanh điểm Nhưng hình trùng biến hình lại cần xoay quanh điểm đầu mút, kiểu kim đồng hồ "Mình tèo rồi." Dậu ngán ngẩm "Tuy là, ừm, thêm lệnh if/else vào thủ tục rotate, hard-code tâm xoay cho amoeba Làm không làm hỏng đoạn khác." Nhưng giọng nói đầu Dậu thào, "Nhầm to! Cậu có đặc tả không thay đổi lần không đấy?" Cuối Dậu chọn cách bổ sung tham số tâm xoay vào cho thủ tục rotate Rất nhiều đoạn mã bị ảnh hưởng Phải test lại, dịch lại đống mã Có đoạn trước chạy tốt khơng chạy rotate(shapeNum, xPt, yPt) { //nếu hình khơng phải amoeba, //tính tâm xoay //dựa hình chữ nhật // xoay hình //nếu khơng // dựng xPt yPt làm offset tâm xoay // xoay hình } Còn Tuất, khơng chần chừ chút nào, anh sửa phương thức rotate, sửa lớp Amoeba mà Tuất không động đến đoạn mã dịch, chạy test phần khác chương trình Để cho Amoeba tâm xoay, anh thêm thuộc tính mà tất hình trùng biến hình có Anh nhanh chóng sửa, test, bàn giao mã cho sếp "Không nhanh được!" Dậu tìm thấy nhược điểm cách tiếp cận Tuất, anh mẩm giúp anh chuyển bại thành thắng Dậu thấy mã Tuất bị lặp, rotate có mặt bốn thứ hình, thiết kế có hay ho phải bảo trì bốn phương thức rotate khác nhau? Tuất giải thích: Dậu chưa nhìn thấy đặc điểm quan trọng thiết kế, quan hệ thừa kế Bốn lớp có đặc điểm chung, đặc điểm tách đặt lớp tên Shape Các lớp kia, lớp xem "thừa kế từ lớp Shape" Nói cách khác, lớp Shape có chức lớp tự động có chức Tuy nhiên, Amoeba có tâm xoay khác chơi file nhạc khác Lớp Amoeba override hoạt động rotate playSound thừa kế từ Shape cách định nghĩa lại thủ tục Và chạy, hệ thống tự biết cần dùng phiên viết Amoeba thay dùng phiên thừa kế từ Shape Đó đặc điểm thú vị phương pháp hướng đối tượng Khi ta cần u cầu hình xoay, tam giác hay amoeba, ta việc gọi phương thức rotate cho đối tượng đó, hệ thống tự biết phải làm gì, phần lại chương trình khơng biết khơng quan tâm đến việc đối tượng xoay kiểu Và ta cần bổ sung vào chương trình, ta phải viết lớp cho loại đối tượng mới, từ đó, đối tượng có cách hành xử riêng chúng 10 Hình 13.7: Phương thức equals Ta lấy ví dụ Hai quân coi giống giống giá trị (value: A, 2, 3, J, Q, K) chất (suit: cơ, rơ, pic, tép) Mã hóa A, 2, , J, Q, K thành giá trị nguyên từ đến 13, bốn chất cơ, rô, pic, tép thành giá trị từ đến Ta có cài đặt đơn giản lớp Card với phương thức equals Hình 13.7 Do phiên override phương thức Object nên kiểu tham số equals phải giữ nguyên cũ Object Nếu ta sử dụng cấu trúc kiểu Set (tập hợp), ta cần phải cài thêm phương thức khác, hashCode(), phương thức thừa kế từ Object với hành vi mặc định phiên thừa kế từ Object cho đối tượng giá trị băm khác Khi cần kiểm tra xem hai đối tượng có trùng hay khơng, cấu trúc HashSet gọi đến phương thức hashCode() hai đối tượng để lấy giá trị băm chúng Nếu hai đối tượng có giá trị băm khác nhau, HashSet khẳng định chúng hai đối tượng khác Còn giá trị băm trùng (dữ liệu khác có giá trị băm trùng nhau), HashSet dùng đến phương thức equals() để kiểm tra tiếp xem hai đối tượng có thực hay khơng Do đó, ta cần override hashCode() để hai đối tượng cho giá trị băm trùng nhau, nhờ qua bước kiểm tra 188 Hình 13.8: Override equals() hashCode() Ta lấy ví dụ với lớp Contact - địa liên lạc Giả sử, ta quy ước hai Contact cho người có trường name (tên) trùng Khi đó, override hai phương thức equals() hashCode() Hình 13.8, ta tận dụng phiên sẵn có equals() hashCode() cho lớp String 13.5.2 So sánh lớn hơn/nhỏ Tương tự với so sánh vấn đề so sánh lớn hơn, nhỏ Giả sử ta cần cấu trúc contactList danh sách địa liên lạc – lớp Contact cài mục trước, ta cần danh sách xếp theo tên Có số cách để làm việc với lớp có sẵn Collection framework Ta dùng phương thức Collections.sort() danh bạ dạng đối tượng List, dùng cấu trúc tự động xếp chẳng hạn TreeSet để lưu danh bạ Cả hai cách cần phải so sánh hai đối tượng Contact để biết đối tượng "lớn hơn" hay "nhỏ hơn" Hình 13.9: Lỗi run-time sử dụng TreeSet cho Contact Tương tự tình so sánh bằng, TreeSet, hay Collections tự biết cách so sánh đối tượng thuộc lớp mà lập trình viên tự xây dựng 189 Chương trình Hình 13.9 biên dịch khơng có lỗi add() khơng u cầu tham số kiểu Comparable, chạy gặp lỗi run-time lệnh gọi đến phương thức Tóm lại, phần tử cấu trúc danh bạ phải thuộc lớp đối tượng có cung cấp phương tiện so sánh Ta chọn hai cách sau để giải vấn đề đó: Các phần tử danh sách phải thuộc lớp có cài interface Comparable Ta sửa lớp Contact để bổ sung phần in đậm Hình 13.10, chương trình Hình 13.9, sau chạy khơng có lỗi Hình 13.10: Cài interface Comparable Sử dụng phương thức overload có lấy tham số Comparator Ta viết thêm lớp ContactCompare theo interface Comparator dùng chương trình TreeTest dòng in đậm Hình 13.11 Theo đó, ContactCompare loại Comparator riêng dành cho việc so sánh đối tượng Contact Còn danh bạ đối tượng TreeSet tạo kèm với loại Comparator đặc biệt để biết cách đối xử với phần tử danh bạ (cContact đối số gọi hàm tạo TreeSet) Hình 13.11: Sử dụng Comparator Cả hai cách áp dụng cho phương thức sort() Collections tiện ích tổng quát tương tự thư viện Java 190 13.6 Wildcard khai báo tham số kiểu Quan hệ thừa kế hai lớp ảnh hưởng đến quan hệ cấu trúc tổng quát dùng cho hai lớp Chẳng hạn, Dog Cat lớp Animal, ta đưa đối tượng Dog Cat vào ArrayList, tính chất đa hình Dog, Cat, Animal hoạt động bình thường (xem ví dụ Hình 13.12) Tuy nhiên, ArrayList, ArrayList thực khơng có quan hệ với ArrayList Vậy cho nên, dùng ArrayList làm đối số cho phương thức yêu cầu đối số kiểu ArrayList, ví dụ Hình 13.13, trình biên dịch báo lỗi sai kiểu liệu 191 Hình 13.12: Đa hình bên cấu trúc tổng qt Hình 13.13: Khơng có đa hình cấu trúc tổng quát Tóm lại, ta khai báo phương thức lấy đối số kiểu ArrayList, lấy đối số kiểu ArrayList lấy kiểu ArrayList hay ArrayList Ta không hài lòng với với việc thỏa hiệp, nghĩa dùng ArrayList thay ArrayList cho danh sách chứa tồn Dog Vì trình biên dịch không kiểm tra kiểu liệu để ngăn chặn tình chẳng hạn danh sách chó nghiệp vụ lính cứu hỏa lại có mèo 192 Hình 13.14: Nguy cho mèo vào danh sách chó Vậy làm để làm cho phương thức nhận đối số thuộc kiểu ArrayList, ArrayList,…nghĩa ArrayList dành cho kiểu lớp Animal? Giải pháp wildcard Ta sửa phương thức makeASymphony() sau, chương trình Hình 13.13 chạy chạy ? extends Animal có nghĩa kiểu thuộc loại Animal Nhớ từ khóa extends có nghĩa "là lớp của" "cài đặt", tùy vào việc theo sau từ khóa extends tên lớp hay tên interface Vậy nên muốn makeASymphony() lấy đối số ArrayList loại cài interface Pet, ta khai báo sau: ArrayList khai báo, trình biên dịch khơng cho ta thêm vào danh sách mà tham số phương thức chiếu tới Ta gọi phương thức phần tử danh sách, ta thêm phần tử vào danh sách Do đó, ta n tâm chương trình chạy Ví dụ, makeASymphony() với nội dung khơng gặp lỗi biên dịch, takeAnimals() với nội dung Hình 13.14 khơng biên dịch 193 Hai cú pháp sau tương đương: public void foo( ArrayList