Lập trình Java cơ bản: Từ "Hello World" đến các khái niệm cốt lõi

Chương trình "Hello, World!" đầu tiên

Để bắt đầu hành trình với Java, hãy thực hiện các bước sau:

  1. Tạo một thư mục mới để lưu trữ mã nguồn của bạn.
  2. Tạo một tệp Java mới.
    • Tệp này phải có phần mở rộng là .java.
    • Ví dụ: đặt tên tệp là HelloWorld.java.
  3. Viết mã nguồn Java:
    
    public class HelloWorld {
        public static void main(String[] args) {
            System.out.print("Hello, World!");
        }
    }
                
  4. Biên dịch tệp Java bằng trình biên dịch javac. Lệnh này sẽ tạo ra một tệp .class.
  5. Chạy tệp .class đã biên dịch bằng trình thông dịch Java.

Các vấn đề thường gặp khi bắt đầu

  • Phân biệt chữ hoa chữ thường: Java rất nhạy cảm với việc phân biệt chữ hoa, chữ thường trong tên từ khóa và định danh.
  • Sử dụng tiếng Anh: Nên ưu tiên sử dụng tiếng Anh trong mã nguồn để dễ dàng giao tiếp và tuân thủ các quy ước chung.
  • Tên tệp và tên lớp: Tên tệp Java phải khớp chính xác với tên lớp được khai báo bên trong tệp đó, và ký tự đầu tiên của cả hai phải được viết hoa.
  • Ký tự: Tránh sử dụng các ký tự tiếng Việt hoặc các ký tự đặc biệt không phải là chuẩn ASCII trong mã nguồn.

Cú pháp cơ bản của Java

Chú thích (Comments)

  • Chú thích một dòng: Bắt đầu bằng //.
  • Chú thích nhiều dòng: Được bao bọc bởi /* và */.
  • Chú thích tài liệu (JavaDoc): Bắt đầu bằng /** và kết thúc bằng */, thường được sử dụng để tạo tài liệu cho mã nguồn.

Định danh (Identifiers)

Định danh là tên được đặt cho các thành phần trong chương trình như biến, lớp, phương thức, v.v. Khi đặt tên định danh, cần tuân thủ các quy tắc sau:

  • Định danh phải bắt đầu bằng một chữ cái (A-Z, a-z), ký tự đô la ($) hoặc dấu gạch dưới (_).
  • Các ký tự tiếp theo có thể là bất kỳ chữ cái, số, ký tự đô la hoặc dấu gạch dưới nào.
  • Không được sử dụng từ khóa của Java làm tên định danh.
  • Định danh phân biệt chữ hoa, chữ thường.

public class HelloWorldSyntax {
    public static void main(String[] args) {
        System.out.println("Xin chào thế giới!"); // Chú thích một dòng

        String personName = "Nguyễn Văn A";
        String tênNgườiDùng = "Nguyễn Văn A"; // Không khuyến khích dùng tiếng Việt
        System.out.println(tênNgườiDùng);

        /*
         * Đây là một
         * ví dụ về
         * chú thích nhiều dòng.
         */

        /**
         * @Description Đây là lớp HelloWorldSyntax
         * @Author Tên tác giả
         */
    }
}
    

Kiểu dữ liệu

Java là một ngôn ngữ kiểu tĩnh (strongly typed), nghĩa là mọi biến đều phải được khai báo kiểu dữ liệu trước khi sử dụng.

Các kiểu dữ liệu cơ bản

  • Kiểu số nguyên: byte, short, int, long.
  • Kiểu số thực (dấu phẩy động): float, double.
  • Kiểu ký tự: char.
  • Kiểu boolean: Chỉ có hai giá trị là true và false.

// Khai báo các biến thuộc 8 kiểu dữ liệu cơ bản
// Kiểu số nguyên
int soNguyen = 100;         // Phổ biến nhất
byte soByte = 120;
short soShort = 30000;
long soLong = 50000L;       // Cần thêm hậu tố 'L' cho giá trị long

// Kiểu số thực
float soFloat = 12.345F;    // Cần thêm hậu tố 'F' cho giá trị float
double soDouble = 3.1415926535;

// Kiểu ký tự
char kyTu = 'A';
// Kiểu chuỗi (String không phải là kiểu cơ bản mà là một lớp)
// String chuoi = "Đây là một chuỗi";

// Kiểu boolean
boolean ketQua = true;
// boolean trangThai = false;
    

Kiểu dữ liệu tham chiếu (Reference Types)

Bao gồm tất cả các kiểu không phải là kiểu cơ bản:

  • Lớp (Class)
  • Giao diện (Interface)
  • Mảng (Array)

Mở rộng về kiểu dữ liệu

Mở rộng kiểu số nguyên

Java hỗ trợ các hệ đếm khác nhau:

  • Nhị phân (Binary): Bắt đầu bằng 0b.
  • Bát phân (Octal): Bắt đầu bằng 0.
  • Thập lục phân (Hexadecimal): Bắt đầu bằng 0x hoặc 0X.

Mở rộng kiểu số thực

Lưu ý về sai số làm tròn khi làm việc với float và double. Đối với các ứng dụng tài chính, nên sử dụng lớp BigDecimal để đảm bảo độ chính xác.


// Khám phá sai số làm tròn của kiểu float và double
float f1 = 0.1f;
double d1 = 1.0 / 10; // Tương đương 0.1
System.out.println(f1 == d1); // Thường sẽ in ra false do sai số

System.out.println(f1);
System.out.println(d1);

float veryLargeFloat = 23333333333333333F;
float veryLargeFloatPlusOne = veryLargeFloat + 1;
System.out.println(veryLargeFloat == veryLargeFloatPlusOne); // Có thể in ra true do giới hạn độ chính xác
    

Mở rộng kiểu ký tự

Mỗi ký tự đều có một mã số Unicode tương ứng. Bạn có thể ép kiểu ký tự sang số nguyên để lấy mã của nó.


char char1 = 'A';
char char2 = 'Đ'; // Ví dụ ký tự tiếng Việt

System.out.println("Mã Unicode của '" + char1 + "': " + (int)char1);
System.out.println("Mã Unicode của '" + char2 + "': " + (int)char2);

// Khai báo ký tự bằng mã Unicode
char unicodeChar = '\u0041'; // Mã Unicode cho 'A'
System.out.println("Ký tự từ mã Unicode: " + unicodeChar);
    

Ký tự đặc biệt (Escape Characters)

  • \t: Tab
  • \n: Xuống dòng

Mở rộng kiểu boolean

Biến boolean thường được sử dụng trong các câu lệnh điều kiện.


boolean isActive = true;
if (isActive) { // Cách viết ngắn gọn thay cho if (isActive == true)
    System.out.println("Trạng thái đang hoạt động.");
}
    

Chuyển đổi kiểu dữ liệu

Chuyển đổi tự động (Widening Conversion)

Xảy ra khi chuyển đổi từ kiểu dữ liệu có phạm vi nhỏ sang kiểu có phạm vi lớn hơn (ví dụ: int sang double).

Chuyển đổi cưỡng bức (Narrowing Conversion)

Xảy ra khi chuyển đổi từ kiểu dữ liệu có phạm vi lớn sang kiểu có phạm vi nhỏ hơn (ví dụ: int sang byte). Cần sử dụng toán tử ép kiểu (kiểu_dữ_liệu) và có thể dẫn đến mất dữ liệu hoặc tràn số.


int largeNumber = 128;
byte smallNumber = (byte) largeNumber; // Ép kiểu cưỡng bức, có thể gây tràn số

double decimalNumber = 23.7;
int integerPart = (int) decimalNumber; // Lấy phần nguyên, bỏ phần thập phân

char character = 'b';
int asciiValue = character; // Tự động chuyển đổi sang mã ASCII
System.out.println("Giá trị ASCII của 'b': " + asciiValue); // Kết quả là 98
char nextChar = (char) (asciiValue + 1); // Ép kiểu lại về char
System.out.println("Ký tự tiếp theo: " + nextChar); // Kết quả là 'c'
    

Lưu ý khi chuyển đổi kiểu:

  • Không thể chuyển đổi trực tiếp kiểu boolean sang các kiểu khác.
  • Không thể chuyển đổi giữa các kiểu tham chiếu không tương thích.
  • Chuyển đổi từ kiểu có phạm vi lớn sang nhỏ có thể gây tràn số hoặc mất độ chính xác.

Xử lý tràn số khi tính toán

Cần cẩn thận khi thực hiện các phép tính với số lượng lớn để tránh tràn số.


// Sử dụng dấu gạch dưới để dễ đọc số lớn (từ JDK 7)
int billion = 1_000_000_000;
int years = 20;

// Phép tính này có thể bị tràn nếu thực hiện với kiểu int
int totalAmount = billion * years;
System.out.println("Tổng số (int overflow): " + totalAmount); // Kết quả có thể sai lệch

// Chuyển đổi một toán hạng sang long trước để đảm bảo phép tính thực hiện với kiểu long
long totalAmountCorrect = (long) billion * years;
System.out.println("Tổng số (long): " + totalAmountCorrect); // Kết quả chính xác
    

Biến (Variables)

Biến là một vùng nhớ được đặt tên để lưu trữ dữ liệu. Cú pháp khai báo biến: kiểu_dữ_liệu tên_biến = giá_trị;

  • Mỗi biến phải được khai báo với một kiểu dữ liệu cụ thể.
  • Tên biến phải là một định danh hợp lệ.
  • Mỗi khai báo biến phải kết thúc bằng dấu chấm phẩy (;).

Phạm vi của biến (Variable Scope)

  • Biến lớp (Class Variables): Khai báo với từ khóa static, thuộc về lớp.
  • Biến thể hiện (Instance Variables): Khai báo trong lớp nhưng ngoài phương thức, thuộc về đối tượng. Nếu không khởi tạo, chúng sẽ nhận giá trị mặc định của kiểu dữ liệu.
  • Biến cục bộ (Local Variables): Khai báo bên trong một phương thức, chỉ có giá trị trong phạm vi phương thức đó. Phải được khởi tạo trước khi sử dụng.

public class VariableScope {

    // Biến lớp (static)
    static double staticSalary = 2500.75;

    // Biến thể hiện (instance variables)
    String instanceName; // Giá trị mặc định là null
    int instanceAge;     // Giá trị mặc định là 0
    boolean instanceStatus; // Giá trị mặc định là false

    public static void main(String[] args) {
        // Biến cục bộ
        int localCounter = 10;
        System.out.println("Biến cục bộ: " + localCounter);

        // Khai báo một đối tượng của lớp
        VariableScope demo = new VariableScope();

        // Truy cập biến thể hiện thông qua đối tượng
        System.out.println("Tuổi mặc định: " + demo.instanceAge);
        System.out.println("Tên mặc định: " + demo.instanceName);
        System.out.println("Trạng thái mặc định: " + demo.instanceStatus);

        // Truy cập biến lớp
        System.out.println("Lương tĩnh: " + staticSalary);
    }

    public void anotherMethod() {
        // Biến cục bộ trong phương thức này
        int anotherLocalVar = 5;
        // System.out.println(localCounter); // Lỗi: localCounter không có trong phạm vi này
    }
}
    

Quy tắc đặt tên biến

  • Nguyên tắc "Nguyên tắc tên có ý nghĩa" (Meaningful Names): Tên biến, phương thức, lớp nên phản ánh rõ mục đích sử dụng.
  • Biến thành viên lớp (Instance/Class Variables): Bắt đầu bằng chữ thường, áp dụng quy tắc "Camel Case" cho các từ tiếp theo (ví dụ: monthlySalary).
  • Biến cục bộ (Local Variables): Tương tự biến thành viên, áp dụng "Camel Case".
  • Hằng số (Constants): Viết hoa toàn bộ và dùng dấu gạch dưới để phân tách các từ (ví dụ: MAX_VALUE).
  • Tên lớp: Bắt đầu bằng chữ hoa, áp dụng "Pascal Case" (ví dụ: MyClass, GoodStudent).
  • Tên phương thức: Bắt đầu bằng chữ thường, áp dụng "Camel Case" (ví dụ: run(), calculateTotal()).

Hằng số (Constants)

Hằng số là những giá trị không thay đổi sau khi đã được gán. Sử dụng từ khóa final để khai báo hằng số. Tên hằng số thường được viết hoa toàn bộ.


public class ConstantsDemo {
    // Khai báo hằng số PI
    final static double PI_VALUE = 3.14159;

    public static void main(String[] args) {
        System.out.println("Giá trị của PI: " + PI_VALUE);
        // PI_VALUE = 3.14; // Lỗi: Không thể gán lại giá trị cho hằng số
    }
}
    

Toán tử (Operators)

Toán tử số học

Bao gồm: + (cộng), - (trừ), * (nhân), / (chia), % (chia lấy dư), ++ (tăng 1), -- (giảm 1).


public class ArithmeticOperators {
    public static void main(String[] args) {
        int num1 = 15;
        int num2 = 4;

        System.out.println("Tổng: " + (num1 + num2)); // 19
        System.out.println("Hiệu: " + (num1 - num2)); // 11
        System.out.println("Tích: " + (num1 * num2)); // 60
        System.out.println("Thương (int): " + (num1 / num2)); // 3 (phần nguyên)
        System.out.println("Thương (double): " + ((double)num1 / num2)); // 3.75
        System.out.println("Dư: " + (num1 % num2)); // 3

        // Toán tử tăng/giảm
        int x = 5;
        int y = x++; // y = 5, sau đó x = 6 (hậu tố - tăng sau)
        int z = ++x; // x = 7, sau đó z = 7 (tiền tố - tăng trước)

        System.out.println("x: " + x); // 7
        System.out.println("y: " + y); // 5
        System.out.println("z: " + z); // 7

        // Tính toán với các kiểu dữ liệu khác nhau
        long bigNum = 123123123123L;
        int regularInt = 100;
        short smallShort = 50;
        byte tinyByte = 10;
        double fraction = 2.5;

        // Khi thực hiện phép tính giữa các kiểu số, kết quả sẽ là kiểu có phạm vi lớn nhất
        System.out.println("Kết quả long: " + (bigNum + regularInt));
        System.out.println("Kết quả int: " + (regularInt + smallShort + tinyByte));
        System.out.println("Kết quả double: " + (fraction + smallShort));
    }
}
    

Toán tử gán (Assignment Operators)

Dùng để gán giá trị cho biến, phổ biến nhất là =. Bao gồm cả các toán tử kết hợp như +=, -=, *=, /=, %=.

Toán tử so sánh (Relational Operators)

Dùng để so sánh hai giá trị, trả về kết quả là true hoặc false.

Các toán tử: > (lớn hơn), < (nhỏ hơn), >= (lớn hơn hoặc bằng), <= (nhỏ hơn hoặc bằng), == (bằng), != (khác).


public class ComparisonOperators {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 10;

        System.out.println("a > b: " + (a > b));   // false
        System.out.println("a < b: " + (a < b));   // true
        System.out.println("a == c: " + (a == c)); // true
        System.out.println("a != b: " + (a != b)); // true
        System.out.println("a >= c: " + (a >= c)); // true
        System.out.println("b <= c: " + (b <= c)); // false
    }
}
    

Toán tử logic (Logical Operators)

Dùng để kết hợp các biểu thức boolean.

  • && (AND - và): Trả về true nếu cả hai biểu thức đều đúng.
  • || (OR - hoặc): Trả về true nếu ít nhất một trong hai biểu thức đúng.
  • ! (NOT - phủ định): Đảo ngược giá trị boolean.

Toán tử Bitwise

Thực hiện các phép toán trên từng bit của số nguyên.

Toán tử điều kiện (Ternary Operator)

Cú pháp: (điều_kiện) ? giá_trị_nếu_đúng : giá_trị_nếu_sai;

Toán tử tăng/giảm (Increment/Decrement Operators)

Đã được đề cập trong phần toán tử số học.


// Ví dụ toán tử điều kiện
int age = 25;
String status = (age >= 18) ? "Trưởng thành" : "Chưa trưởng thành";
System.out.println("Trạng thái: " + status);
    

Thẻ: Java lập trình cơ bản Cú pháp Java Kiểu dữ liệu Java Biến Java

Đăng vào ngày 10 tháng 11 lúc 05:23