1 điểm bởi GN⁺ 2024-08-04 | 1 bình luận | Chia sẻ qua WhatsApp

Null-Restricted and Nullable Types (Preview)

Tóm tắt

Một tính năng ngôn ngữ ở trạng thái xem trước hỗ trợ các dấu đánh dấu nullness để cho phép hoặc từ chối null trong các kiểu Java.

Mục tiêu

  • Cải tiến các kiểu tham chiếu của Java để lập trình viên có thể biểu đạt liệu có mong đợi tham chiếu null hay không
  • Hỗ trợ chuyển đổi giữa các kiểu có thuộc tính nullness khác nhau, đồng thời đưa ra cảnh báo về các giá trị null được xử lý không đúng cách
  • Tương thích với mã Java hiện có và hỗ trợ áp dụng dần tính năng mới
  • Đảm bảo các biến của kiểu từ chối null được khởi tạo trước lần đọc đầu tiên
  • Thực thi kiểu từ chối null ở thời gian chạy ngay cả trong các lớp được biên dịch riêng biệt
  • Cung cấp siêu dữ liệu cần thiết và đảm bảo tính toàn vẹn để tối ưu hóa thời gian chạy

Không nhằm mục tiêu

  • Không tự động diễn giải lại mã hiện có
  • Không yêu cầu xử lý tường minh mọi giá trị null
  • Không bao gồm thay đổi đối với kiểu nguyên thủy
  • Không áp dụng các cải tiến ngôn ngữ cho thư viện chuẩn

Động cơ

  • Trong các chương trình Java, biến kiểu String có thể chứa tham chiếu đến đối tượng String hoặc giá trị null
  • Không thể biểu đạt rõ ràng việc một biến có cho phép null hay không, gây ra nhầm lẫn và lỗi
  • Cần có công cụ để nhà phát triển có thể chỉ rõ, như một phần của kiểu, liệu null có được hỗ trợ hay được mong đợi hay không

Mô tả

Thuộc tính nullness và dấu đánh dấu

  • Kiểu tham chiếu có thể biểu đạt nullness một cách tùy chọn
  • Foo! là kiểu giới hạn null không bao gồm null
  • Foo? là kiểu nullable có bao gồm null
  • Mặc định, nullness của Foo là không được chỉ định

Khởi tạo trường và mảng

  • Trường hoặc mảng kiểu giới hạn null phải được khởi tạo trước khi sử dụng
  • Nếu cố đọc một trường kiểu giới hạn null chưa được khởi tạo thì sẽ phát sinh ngoại lệ

Nullness của biểu thức và chuyển đổi

  • Trình biên dịch Java xác định nullness của mọi biểu thức
  • Có thể xử lý các biểu thức có nullness khác nhau thông qua chuyển đổi nullness
  • Chuyển đổi nullness theo hướng thu hẹp có thể gây ra NullPointerException ở thời gian chạy

Kiểm tra null ở thời gian chạy

  • Khi xảy ra chuyển đổi nullness theo hướng thu hẹp, NullPointerException sẽ phát sinh

Nullness của biến kiểu

  • Biến kiểu cũng có thể biểu đạt nullness
  • Biến kiểu giới hạn null và nullable khẳng định nullness cụ thể trong mã generic

Đối số kiểu và ràng buộc

  • Đối số kiểu có thể biểu đạt nullness, và điều này ảnh hưởng đến nullness của API
  • Đối số kiểu có nullness không khớp có thể tạo ra cảnh báo

Ghi đè phương thức và suy luận đối số kiểu

  • Nullness bị bỏ qua khi xác định chữ ký phương thức có giống nhau hay không
  • Kiểu trả về của phương thức ghi đè có thể được chuyển đổi thông qua chuyển đổi nullness

Cảnh báo của trình biên dịch

  • Việc tạo kiểu giới hạn null có thể làm phát sinh các lỗi mới ở thời điểm biên dịch
  • Chuyển đổi nullness theo hướng thu hẹp, dùng kiểu ? trong các phép toán không chấp nhận null, v.v. có thể tạo ra cảnh báo

Biểu diễn khi biên dịch và trong tệp lớp

  • Phần lớn các dấu đánh dấu null bị loại bỏ khỏi tệp lớp
  • Thuộc tính NullRestricted mới cho biết một trường không cho phép giá trị null

Core Reflection

  • Không tồn tại literal Foo!.class hay Foo?.class
  • API RuntimeType mới mô tả biến thể giới hạn null ở thời gian chạy

Các thay đổi bổ sung

  • Cơ chế tuần tự hóa truyền thống không tương thích với trường và mảng kiểu giới hạn null
  • javadoc bao gồm các dấu đánh dấu nullness
  • API java.lang.reflect.Typejavax.lang.model mã hóa nullness

Phương án thay thế

  • Nhiều công cụ phát triển trong hệ sinh thái Java tự triển khai việc theo dõi null
  • Các ngôn ngữ lập trình khác theo dõi nullness trong hệ thống kiểu
  • Việc thực thi nullness ở thời gian chạy có thể được triển khai bằng các kiểm tra tường minh hoặc lời gọi Objects.requireNonNull

Phụ thuộc

  • Cần Flexible Constructor Bodies (Second Preview)
  • Các công việc trong tương lai như Null-Restricted Value Class Types (Preview) và JEP 402: Enhanced Primitive Boxing (Preview)

Tóm tắt của GN⁺

  • JEP này cung cấp công cụ để xử lý rõ ràng giá trị null trong Java, giúp tăng độ ổn định và khả năng đọc của mã
  • Việc đưa vào kiểu giới hạn null và kiểu nullable có thể giúp giảm lỗi do tham chiếu null
  • Tương thích với mã hiện có và có thể được áp dụng dần, mang lại sự linh hoạt cho nhà phát triển
  • So với các ngôn ngữ khác, nó có thể tăng cường khả năng xử lý null của Java
  • Một công cụ cung cấp tính năng tương tự là null-safety của Kotlin

1 bình luận

 
GN⁺ 2024-08-04
Ý kiến trên Hacker News
  • So sánh cách xử lý null của C# và Kotlin

    • C# khi bật nullability trong dự án thì mọi biến mặc định được khai báo là non-null
    • Kotlin cũng tương tự, nhưng không cần backward compatibility
    • Kotlin cung cấp tính năng cho phép khởi tạo sau đối với biến non-nullable chưa được khởi tạo thông qua khai báo lateinit var
  • Ý kiến về đề xuất mới

    • Các biến hiện có được phân thành nullable, explicitly nullable và explicitly non-nullable
    • Cách tiếp cận của C# có vẻ tốt hơn, đặc biệt là không cần giải quyết vấn đề nullability trong codebase legacy
    • Tuy nhiên, cách tiếp cận của C# sẽ ngay lập tức làm nổi bật các vấn đề nullability trong codebase
  • Lo ngại về ép kiểu tự động trong nullness-narrowing

    • Việc tự động chuyển đổi tạo cảm giác không đúng
    • Có những trường hợp nên phát sinh lỗi biên dịch
    • Chuyển đổi tường minh an toàn hơn
  • Sự cần thiết của cách đánh dấu mọi biến là non-null theo mặc định

    • Cần có cách đánh dấu mọi biến là non-null ở cấp package hoặc file
    • Nếu không thì sẽ phải dùng cú pháp T! cho gần như mọi biến, làm mã nguồn trở nên phức tạp
  • Sự cần thiết của tính năng optionality tường minh ở cấp độ ngôn ngữ trong Java

    • Dựa trên trải nghiệm với Kotlin và Typescript, hỗ trợ ở cấp độ ngôn ngữ là tốt hơn
    • Các công cụ như NullAway trong Java khá phiền phức
  • Chỉ trích quyết định không áp dụng các cải tiến ngôn ngữ vào thư viện tiêu chuẩn

    • Từ kinh nghiệm dùng PHP, việc tương tác với thư viện tiêu chuẩn khá bất tiện
    • Cần bổ sung khả năng biểu đạt này vào thư viện tiêu chuẩn
  • Sự cần thiết của một cách dễ dàng để nâng cảnh báo thời điểm biên dịch thành lỗi

    • Java chủ yếu là ngôn ngữ kiểu tĩnh, nên việc đưa hành vi động vào là không tốt
  • Sự cần thiết phải mặc định là non-nullable, immutable và phạm vi hẹp

    • Nhiều quyết định thiết kế mới thường từ bỏ con đường an toàn để đổi lấy sự tiện lợi tức thời
    • Trong nhiều ngôn ngữ và công nghệ, những vấn đề này gây ra rất nhiều lỗi
  • Kinh nghiệm xử lý null trong ngôn ngữ Hack

    • Nullness là phần quan trọng trong hệ thống kiểu của Hack
    • Có câu hỏi về mảng nullable
    • Trong Java, đây trở thành vấn đề vì toàn bộ code legacy đều giả định có nullability
  • Câu hỏi về việc có thể áp dụng tính năng này cho Java SDK hay không

    • Băn khoăn về cách áp dụng nó cho code legacy
  • Liên kết liên quan