6 inconsistent syntaxes in Java

6 inconsistent syntaxes in Java

·

4 min read

Java nói chung là một ngôn ngữ được thiết kế tốt. Java tránh được các lỗi thiết kế trong các ngôn ngữ C-family trước đó, giúp Java trở nên an toàn hơn để viết.

Tuy nhiên, vẫn còn một vài lỗi trong số chúng tồn tại trong Java cho đến ngày nay. Tuy không quá ảnh hưởng, nhưng sẽ tốt hơn nếu Java sửa chúng, giúp cho syntax rõ ràng và thống nhất hơn.

1. Code block

Trong Java, nếu phần body của statement cần thực thi nhiều câu lệnh, thì cần một block để chứa. Tuy nhiên, khối case lại không theo quy tắc này.

// Run multiple statements without {}
switch (point) {
    case 10:
        System.out.println("Good");
        break;
}

Java nên bắt buộc dùng một block {} trong trường hợp này.

switch (point) {
    case 10: {
        System.out.println("Good");
        break;
    }
}

Các statement đặc biệt như do while, try with resources,... thì luôn phải có ngoặc nhọn {} cả khi có một lệnh. Phần này có thể cải tiến trong tương lai bằng cách yêu cầu luôn dùng {} cả khi có một câu lệnh.

2. Case sensitive

Java là ngôn ngữ có phân biệt hoa thường (case sensitive), do đó nameNAME là hai định danh riêng biệt. Tuy nhiên các chữ cái ký hiệu trong number literal lại không tuân theo quy tắc này.

// Suffix
long a = 100l;
long b = 200L;
float c = 1.23f;

// Prefix
int d = 0xA1B2C3;
int e = 0XD4E5F6;

Đề xuất Java cần xác định rõ quy tắc hoa thường trong trường hợp này. Ví dụ prefix dùng chữ thường (lowercase) và suffix dùng chữ hoa (uppercase).

long f = 0xA1B2C3L;

3. Octal literal

Các giá trị bát phân (octal) chỉ có prefix 0, không giống với các hệ cơ số khác, như hexa dùng prefix 0x. Sự không thống nhất này dẫn đến nhầm lẫn, xem 0123 (decimal) tương đương với 123 (decimal).

int a = 0123; // Octal
int b = 123; // Decimal
System.out.println(a == b); // false

Thay vào đó, nên dùng prefix 0o để mô tả số octal, tương tự như cách PHP 8.1 đã làm.

int c = 0o123; // Octal

4. Data types naming

4a. Wrapper class

Tên một số wrapper class chưa tương ứng với primitive type.

Wrapper classPrimitive type
Integerint
Characterchar

Nên đổi lại cho phù hợp với nguyên tắc tên primitive type in hoa chữ cái đầu tiên thành tên wrapper class tương ứng. Giúp code ngắn gọn và trông thống nhất hơn.

Int a = 10;
Char ch = 'A';

4b. Boolean type

Kiểu dữ liệu boolean nên rút gọn tên thành bool, tương tự như dùng int thay vì integer.

bool a = true;
Bool b = false;

5. Annotation array parameter

Đây là quyết định khá tồi tệ của nhóm Java, khi cho phép bỏ qua {} khi chỉ định array parameter trên annotation. Điều này dẫn đến không thể phân biệt được parameter đó là array hay single value.

@Relationship(friends = "John")
private Person mike;

Thay vào đó, nên bắt buộc có {} nếu parameter là array, và không có nếu là single value.

@Relationship(friends = {"John"}, bestFriend= "John")
private Person mike;

Trông rõ ràng hơn nhiều, phải không?

6. Method reference

Method reference là syntax mới trong Java 8, giúp viết lambda gọn gàng hơn. Ví dụ, hai cách viêt sau là tương đương nhau (dạng object::method).

StringUtil util = new StringUtil();

// Reference to instance method
s -> util.length(s);
util::length;

Tuy nhiên lại có sự nhầm lẫn khi dùng cách viết Class::method vì có đến hai ý nghĩa như sau.

String::length;

// Reference to instance method of the parameter
// Or reference to static method
s -> s.length();
s -> String.length(s);

Trong trường hợp này, nên có thêm syntax hay keyword mới giúp phân biệt chúng với nhau. Ví dụ như sử dụng từ khóa param như sau.

// Reference to static method
String::length;
s -> String.length(s);

// Reference to instance method of the parameter
param::length;
s -> s.length();

Cover image: https://www.linkedin.com/pulse/modern-java-features-shivangam-soni/