Module 2: Nền tảng ngôn ngữ Java
2.1 Cấu trúc chương trình Java
2.1.1 Gói (package)
1. Tầm quan trọng của gói
- Quản lý lớp: Ngăn ngừa xung đột tên, tránh xung đột đặt tên
- Kiểm soát truy cập: Sử dụng quyền kiểm soát truy cập để quản lý việc truy cập lớp, giao diện, trường, phương thức
- Tổ chức lớp: Phân loại và quản lý các lớp
2. Khai báo gói (tạo)
- Khai báo gói:
package tên_gói; - Nhập gói:
import tên_gói;hoặcimport tên_gói.*;, trong đó*có nghĩa là nhập tất cả các lớp trong gói, ví dụ:import java.util.*;nhập tất cả các lớp trong góijava.util
Ngoài ra, có thể sử dụng
import staticđể nhập các thành viên tĩnh của lớp, ví dụ:
> import static java.lang.Math.*;
>
> ```
>
> //Giải thích: Nhập tất cả các thành viên tĩnh của lớp `java.lang.Math`
> **Cũng có thể sử dụng trực tiếp các lớp trong gói `java.lang` trong chương trình**, ví dụ:
>
> ```
> System.out.println("Xin chào Thế giới!");
>
> ```
>
> Vì gói `java.lang` là gói cốt lõi của Java, được tự động nhập
- Lưu ý: Tên gói nên viết thường toàn bộ, ví dụ
java.lang,java.util,com.viettel
3. Quy tắc đặt tên gói ()
- Chỉ sử dụng chữ thường: ví dụ
java.lang - Đảo ngược tên miền: ví dụ
com.viettel - Tên lớp: ví dụ
com.viettel.util.DateUtil - Mở rộng đọc thêm:
Sổ tay phát triển Java của Viettel
Tài liệu tham khảo quy tắc đặt tên Java toàn diện nhất!
Tác dụng, quy tắc đặt tên và lưu ý khi đặt tên gói Java
3. Các gói tiêu chuẩn thường dùng trong Java
- java.lang: Chứa các lớp cốt lõi của Java, như String, Math, System và Thread, không cần nhập rõ ràng, tự động nhập
- java.util: Chứa thư viện tiện ích của Java, như khung sưu tập, lớp ngày giờ và trình tạo số ngẫu nhiên
- java.io: Chứa thư viện nhập/xuất của Java, như đọc/ghi file, giao tiếp mạng, v.v.
- java.net: Chứa thư trình lập trình mạng của Java, như URL, Socket, v.v.
- java.sql: Chứa thư trình lập trình cơ sở dữ liệu của Java, như giao diện JDBC
- java.awt: Chứa thư trình lập trình giao diện đồ họa của Java, như cửa sổ, nút, hộp văn bản, v.v.
1. Hàm chính
Hàm chính là điểm bắt đầu của chương trình Java, định dạng như sau:
public static void main(String[] args)
2. Tham số trong hàm main
thamSo là một mảng chuỗi, dùng để nhận các tham số dòng lệnh. Khi chạy chương trình, có thể truyền tham số cho hàm chính qua dòng lệnh. Ví dụ, giả sử có một chương trình Java tên làXinChao.java, có thể chạy lệnh sau trên dòng lệnh:
java XinChao tham1 tham2 tham3
Trong đó, tham1, tham2 và tham3 là các tham số được truyền cho hàm chính. Trong chương trình, có thể truy cập các tham số này thông qua mảng thamSo. Ví dụ, có thể sử dụng đoạn mã sau để in ra tất cả các tham số được truyền cho hàm chính:
for (String giaTri : thamSo) {
System.out.println(giaTri);
}
2.1.3 Khối mã
Khối mã là một tập hợp các câu lược được bao quanh bởi dấu ngoặc nhọn{}. Khối mã có thể được dùng để xác định phạm vi, trong đó các biến được khai báo chỉ có thể nhìn thấy trong khối mã. Khối mã có thể được lồng vào nhau, tức là một khối có thể chứa một khối khác.
Khối mã có thể chia thành: khối mã thông thường, khối mã tĩnh, khối mã khởi tạo và khối mã đồng bộ. Dưới đây là giải thích 3 loại đầu:
1. Khối mã thông thường
Khối mã thông thường là khối mã được định nghĩa bên trong phương thức, có thể chứa bất kỳ số lượng câu lệnh nào. Khối mã thông thường có thể được dùng để xác định một phạm vi, trong đó các biến được khai báo chỉ có thể nhìn thấy trong khối mã. Ví dụ:
public class XinChao {
public static void main(String[] args) {
{
int x = 10;
System.out.println(x);
}
// x không thể truy cập ở đây
}
}
Trong ví dụ trên, biến x chỉ có thể nhìn thấy trong khối mã đầu tiên.
2. Khối mã tĩnh
Khối mã tĩnh là khối mã được định nghĩa trong lớp, sử dụng từ khóa static để sửa đổi. Khối mã tĩnh được thực thi khi lớp được tải và chỉ thực thi một lần. Khối mã tĩnh có thể được dùng để khởi tạo biến tĩnh hoặc thực hiện các thao tác khởi tạo tĩnh khác. Ví dụ:
public class XinChao {
static int x;
static {
x = 10;
System.out.println("Khối mã tĩnh thực thi");
}
public static void main(String[] args) {
System.out.println(x);
}
}
Trong ví dụ trên, khối mã tĩnh được thực thi khi lớp được tải và khởi tạo biến tĩnh x.
3. Khối mã khởi tạo
Khối mã khởi tạo là khối mã được định nghĩa trong lớp, không có từ khóa static để sửa đổi. Khối mã khởi tạo được thực thi mỗi khi tạo đối tượng và thực thi trước hàm khởi tạo. Khối mã khởi tạo có thể được dùng để khởi tạo biến thể hiện hoặc thực hiện các thao tác khởi tạo khác. Ví dụ:
public class XinChao {
int x;
{
x = 10;
System.out.println("Khối mã khởi tạo thực thi");
}
public XinChao() {
System.out.println("Hàm khởi tạo thực thi");
}
public static void main(String[] args) {
XinChao doiTuong = new XinChao();
System.out.println(doiTuong.x);
}
}
Trong ví dụ trên, khối mã khởi tạo được thực thi mỗi khi tạo đối tượng và khởi tạo biến thể hiện x.
Khối mã đồng bộ là khối mã được định nghĩa bên trong phương thức, sử dụng từ khóa synchronized để sửa đổi. Khối mã đồng bộ có thể được dùng để đảm bảo rằng trong môi trường đa luồng, cùng một thời điểm chỉ có một luồng có thể thực thi mã trong khối. Ví dụ:
public class XinChao {
private int x = 0;
public synchronized void tang() {
x++;
}
}
Trong ví dụ trên, phương thức tang sử dụng từ khóa synchronized để sửa đổi, đảm bảo rằng trong môi trường đa luồng, cùng một thời điểm chỉ có một luồng có thể thực thi mã trong phương thức.
5. Câu lệnh try-with-resources
Câu lệnh try-with-resources là cú pháp được giới thiệu trong Java 7, dùng để tự động đóng tài nguyên đã thực hiện giao diện AutoCloseable. Ví dụ:
public class XinChao {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line = br.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Trong ví dụ trên, đối tượng BufferedReader được tạo trong câu lệnh try-with-resources và được tự động đóng khi kết thúc câu lệnh.
6. Biểu thức lambda
Biểu thức lambda là cú pháp được giới thiệu trong Java 8, dùng để đơn giản hóa việc viết lớp nội ẩn. Ví dụ:
public class XinChao {
public static void main(String[] args) {
List list = Arrays.asList("a", "b", "c");
list.forEach(s -> System.out.println(s));
}
}
Trong ví dụ trên, phương thức forEach chấp nhận biểu thức lambda làm tham số, dùng để thực hiện thao tác trên từng phần tử trong danh sách.
7. API Stream
API Stream là cú pháp được giới thiệu trong Java 8, dùng để xử lý dữ liệu tập hợp. Ví dụ:
public class XinChao {
public static void main(String[] args) {
List list = Arrays.asList("a", "b", "c");
list.stream()
.filter(s -> s.startsWith("a"))
.forEach(System.out::println);
}
}
Trong ví dụ trên, phương thức stream chuyển đổi danh sách thành luồng, phương thức filter lọc các phần tử trong luồng, phương thức forEach thực hiện thao tác trên từng phần tử trong luồng.
8. Optional
Optional là lớp chứa được giới thiệu trong Java 8, dùng để biểu thị đối tượng có thể rỗng. Ví dụ:
public class XinChao {
public static void main(String[] args) {
Optional optional = Optional.of("Xin chào");
optional.ifPresent(System.out::println);
}
}
Trong ví dụ trên, phương thức Optional.of tạo một đối tượng Optional chứa giá trị chỉ định, phương thức ifPresent thực hiện thao tác khi đối tượng Optional chứa giá trị.
9. Phương thức mặc định của giao diện
Phương thức mặc định của giao diện là cú pháp được giới thiệu trong Java 8, cho phép định nghĩa phương thức mặc định trong giao diện. Ví dụ:
public interface GiaoDieu {
default void phuongThucCuaToi() {
System.out.println("Xin chào");
}
}
Trong ví dụ trên, phuongThucCuaToi là một phương thức mặc định, có thể được gọi trực tiếp trong lớp thực hiện giao diện này.
10. Tham chiếu phương thức
Tham chiếu phương thức là cú pháp được giới thiệu trong Java 8, dùng để đơn giản hóa cách viết biểu thức lambda. Ví dụ:
public class XinChao {
public static void main(String[] args) {
List list = Arrays.asList("a", "b", "c");
list.forEach(System.out::println);
}
}
Trong ví dụ trên, System.out::println là một tham chiếu phương thức, dùng để gọi phương thức println của đối tượng System.out.