Môi Trường Phát Triển và Cấu Hình
Khi làm việc với IntelliJ IDEA, việc nắm vững các phím tắt giúp tối ưu hóa tốc độ phát triển:
- Ctrl + P: Hiển thị danh sách các tham số khi khởi tạo đối tượng hoặc gọi phương thức.
- Alt + Insert: Tự động sinh mã nguồn (Getter/Setter, Constructor, toString).
- Shift + F6: Refactor - đổi tên hàng loạt cho biến, phương thức hoặc class.
- Ctrl + Shift + U: Chuyển đổi chữ hoa/thường cho đoạn văn bản được bôi đen.
Trong hệ sinh thái Java, cần phân biệt rõ JDK (Java Development Kit) và JRE (Java Runtime Environment). JRE cung cấp môi trường thực thi bao gồm JVM và các thư viện lõi. JDK là bộ công cụ phát triển đầy đủ, chứa JRE cùng với trình biên dịch (javac) và các công cụ gỡ lỗi. Do đó, JRE là một tập con của JDK.
Nền Tảng Ngôn Ngữ
Phạm vi biến và Đóng gói: Biến được khai báo bên trong phương thức gọi là biến cục bộ, trong khi biến khai báo trực tiếp trong class được gọi là biến thành viên. Từ khóa private giới hạn quyền truy cập của biến hoặc phương thức chỉ trong nội bộ class đó. Nếu biến cục bộ và biến thành viên trùng tên, Java sẽ ưu tiên biến cục bộ. Để tham chiếu chính xác đến biến thành viên, ta sử dụng từ khóa this.
Xuất nhập dữ liệu:
System.out.print(): In dữ liệu ra console mà không xuống dòng.System.out.println(): In dữ liệu và tự động xuống dòng.System.out.printf(): In dữ liệu có định dạng thông qua các placeholder (ví dụ:%d,%s).
Khi sử dụng Scanner để đọc chuỗi, phương thức next() sẽ dừng đọc khi gặp khoảng trắng đầu tiên. Ngược lại, nextLine() sẽ đọc toàn bộ nội dung của dòng cho đến khi gặp ký tự xuống dòng.
Toán tử ba ngôi: Giúp rút gọn các câu lệnh điều kiện if-else đơn giản.
int temperature = -5;
// Nếu nhiệt độ âm, đặt về 0, ngược lại giữ nguyên giá trị
int validTemp = (temperature < 0) ? 0 : temperature;
Lập Trình Hướng Đối Tượng (OOP)
Nạp chồng phương thức (Overloading): Cho phép định nghĩa nhiều phương thức có cùng tên trong một class, nhưng phải khác nhau về số lượng hoặc kiểu dữ liệu của tham số.
Hàm tạo (Constructor): Được JVM gọi tự động khi khởi tạo đối tượng để thiết lập giá trị ban đầu. Nếu lập trình viên không định nghĩa bất kỳ constructor nào, JVM sẽ cung cấp một constructor mặc định không tham số. Tuy nhiên, nếu đã tạo constructor có tham số, constructor mặc định sẽ không còn được tự động sinh ra. Trong thực tế, nên định nghĩa cả hai để đảm bảo tính linh hoạt. Constructor cũng hỗ trợ nạp chồng.
Kế thừa (Inheritance): Mọi class trong Java đều kế thừa trực tiếp hoặc gián tiếp từ lớp Object. Lớp con không thể kế thừa constructor của lớp cha nhưng có thể gọi nó thông qua super(). Các thuộc tính private của lớp cha vẫn được kế thừa nhưng lớp con chỉ có thể tương tác với chúng thông qua các phương thức public (getter/setter). Phương thức public của lớp cha có thể bị lớp con ghi đè (Override) bằng cách sử dụng annotation @Override để đảm bảo tính chính xác của chữ ký phương thức.
Đa hình (Polymorphism): Cho phép một tham chiếu kiểu lớp cha trỏ đến đối tượng của lớp con. Điều này giúp code linh hoạt hơn nhưng hạn chế việc gọi trực tiếp các phương thức đặc thù chỉ có ở lớp con. Để giải quyết, ta dùng ép kiểu kết hợp với toán tử instanceof.
Vehicle transport = new ElectricCar();
// Pattern matching cho instanceof (Java 16+)
if (transport instanceof ElectricCar evCar) {
evCar.chargeBattery();
}
// Cách viết tương đương ở các phiên bản cũ
if (transport instanceof ElectricCar) {
ElectricCar evCar = (ElectricCar) transport;
evCar.chargeBattery();
}
Từ khóa static và final:
Các thành phần được đánh dấu static (biến, phương thức, block code) thuộc về chính class đó thay vì thuộc về một instance cụ thể, và được chia sẻ giữa mọi đối tượng. Block static { } thường dùng để khởi tạo dữ liệu phức tạp và chỉ chạy một lần duy nhất khi class được tải. Từ khóa final được sử dụng để khai báo các hằng số không thể thay đổi giá trị sau khi gán.
Lớp trừu tượng và Interface: Abstract class có thể chứa cả phương thức thường và phương thức trừu tượng (bắt buộc lớp con phải override). Interface không có constructor, các phương thức mặc định là public abstract và các biến mặc định là public static final. Một interface có thể kế thừa nhiều interface khác.
Lớp nội bộ (Inner Class): Bao gồm Member Inner Class, Static Inner Class, Local Inner Class và Anonymous Inner Class. Lớp ẩn danh (Anonymous) thường được sử dụng để implement nhanh các interface hoặc override phương thức mà không cần tạo một file class riêng biệt, rất phổ biến trong xử lý sự kiện giao diện.
Xử Lý Chuỗi và Cấu Trúc Dữ Liệu
Để so sánh nội dung chuỗi, sử dụng equals() (phân biệt hoa thường) hoặc equalsIgnoreCase(). Phương thức charAt() trích xuất ký tự tại vị trí index chỉ định.
Do String trong Java là bất biến (immutable), việc thao tác nối chuỗi liên tục sẽ gây tốn kém bộ nhớ. StringBuilder giải quyết vấn đề này bằng cách cung cấp một vùng nhớ có thể thay đổi.
StringBuilder builder = new StringBuilder();
builder.append("System ");
builder.append("Active");
builder.reverse(); // Đảo ngược chuỗi
String finalLog = builder.toString();
Ngoài ra, StringJoiner (thuộc package java.util) là công cụ hữu hiệu để ghép nhiều chuỗi lại với nhau kèm theo ký tự phân cách, tiền tố và hậu tố.
ArrayList: Là một cấu trúc dữ liệu động thuộc Collections Framework, chỉ cho phép lưu trữ kiểu dữ liệu tham chiếu. Các thao tác cơ bản bao gồm:
List<String> productList = new ArrayList<>();
productList.add("Monitor"); // Thêm phần tử
productList.remove("Monitor"); // Xóa theo giá trị
String deletedItem = productList.remove(0); // Xóa theo index và trả về giá trị đã xóa
productList.set(0, "Keyboard"); // Cập nhật phần tử tại index 0
String firstItem = productList.get(0); // Lấy phần tử đầu tiên
int totalItems = productList.size(); // Lấy kích thước danh sách
Các API quan trọng khác:
Math,System,Runtime: Cung cấp các hàm toán học, thao tác với hệ thống và quản lý tiến trình.Object: Chứa phương thứcclone()hỗ trợ sao chép đối tượng (shallow clone và deep clone).BigInteger: Nằm trongjava.math, dùng để tính toán các số nguyên có độ lớn tùy ý, vượt qua giới hạn của kiểulong, thường ứng dụng trong mật mã học.- Biểu thức chính quy (Regex): Công cụ mạnh mẽ để kiểm tra định dạng, tìm kiếm và thay thế chuỗi dựa trên các pattern.
Đa Luồng và Lập Trình Mạng
Đa luồng (Multithreading): Khi làm việc với luồng, cần phân biệt rõ start() và run(). Việc gọi start() sẽ yêu cầu JVM cấp phát một luồng thực thi mới, sau đó tự động gọi đến phương thức run(). Nếu gọi trực tiếp run(), mã nguồn sẽ chỉ thực thi tuần tự như một phương thức bình thường trên luồng hiện tại mà không tạo ra tính song song.
Lập trình mạng: Giao tiếp mạng dựa trên địa chỉ IP. Công nghệ NAT (Network Address Translation) giúp bảo mật mạng nội bộ và tiết kiệm địa chỉ IPv4 công cộng bằng cách cho phép nhiều thiết bị chia sẻ một IP duy nhất khi ra Internet. Các dải IP như 192.168.x.x được quy định là địa chỉ private dành riêng cho mạng LAN. Địa chỉ 127.0.0.1 (hoặc localhost) là vòng lặp cục bộ (loopback), luôn trỏ về chính thiết bị đang chạy ứng dụng.