JavaRush /Blog Java /Random-VI /Từ 8 đến 13: tổng quan đầy đủ về các phiên bản Java. Phần...

Từ 8 đến 13: tổng quan đầy đủ về các phiên bản Java. Phần 1

Xuất bản trong nhóm
Mèo con, xin chào mọi người)) Vì vậy, hôm nay chúng ta đang ở năm 2020 và chỉ còn rất ít cho đến khi Java 14 được phát hành. Bạn sẽ mong đợi phiên bản hoàn thiện vào ngày 17 tháng 3, sau đó chúng tôi sẽ phân tích những gì mới mẻ và thú vị ở đó, nhưng hôm nay tôi muốn làm mới bộ nhớ của mình về các phiên bản Java trước đó. Họ đã mang đến cho chúng ta điều gì mới? Chúng ta hãy xem xét. Hãy bắt đầu đánh giá với Java 8, vì nó vẫn khá phù hợp và được sử dụng trong hầu hết các dự án. Từ 8 đến 13: tổng quan đầy đủ về các phiên bản Java.  Phần 1 - 1Trước đây, các phiên bản mới được phát hành 3-5 năm một lần, nhưng gần đây Oracle đã thực hiện một cách tiếp cận khác - “Java mới sáu tháng một lần”. Và vì vậy, cứ sáu tháng chúng tôi lại thấy các tính năng được phát hành. Dù tốt hay xấu thì mỗi người đều nhìn nhận một cách khác nhau. Ví dụ, tôi không thích điều này lắm, vì các phiên bản mới không có nhiều tính năng mới, nhưng đồng thời, các phiên bản lại mọc lên như nấm sau mưa. Tôi đã chớp mắt vài lần về một dự án với Java 8 và Java 16 đã được phát hành (nhưng khi nó hiếm khi xuất hiện, các tính năng mới sẽ tích lũy và cuối cùng, sự kiện này đã được chờ đợi từ lâu, giống như một kỳ nghỉ: mọi người đang thảo luận về những món quà mới và bạn không thể bỏ qua nó). Vậy hãy bắt đầu!

Java 8

Giao diện chức năng

Cái này là cái gì? Giao diện chức năng là giao diện chứa một phương thức chưa được triển khai (trừu tượng). @FunctionalInterface là một chú thích tùy chọn được đặt phía trên một giao diện như vậy. Cần kiểm tra xem nó có đáp ứng các yêu cầu của giao diện chức năng hay không (chỉ có một phương thức trừu tượng). Nhưng như mọi khi, chúng tôi có một số lưu ý: các phương thức mặc định và tĩnh không đáp ứng các yêu cầu này. Do đó, có thể có một số phương thức như vậy + một phương thức trừu tượng và giao diện sẽ hoạt động. Nó cũng có thể chứa các phương thức của lớp Object không ảnh hưởng đến định nghĩa giao diện là chức năng. Tôi sẽ thêm một vài từ về các phương thức mặc định và tĩnh:
  1. Các phương thức có công cụ sửa đổi mặc định cho phép bạn thêm các phương thức mới vào giao diện mà không phá vỡ quá trình triển khai hiện có của chúng.

    public interface Something {
      default void someMethod {
          System.out.println("Some text......");
      }
    }

    Có, vâng, chúng tôi thêm phương thức đã triển khai vào giao diện và khi triển khai phương thức này, bạn không thể ghi đè lên nó mà hãy sử dụng nó như một phương thức kế thừa. Nhưng nếu một lớp thực hiện hai giao diện với một phương thức nhất định, chúng ta sẽ gặp lỗi biên dịch và nếu nó thực hiện các giao diện và kế thừa một lớp có một phương thức giống hệt nhau nhất định, thì phương thức của lớp cha sẽ chồng lên các phương thức giao diện và ngoại lệ sẽ không hoạt động.

  2. Các phương thức tĩnh trong một giao diện hoạt động giống như các phương thức tĩnh trong một lớp. Đừng quên: bạn không thể kế thừa các phương thức tĩnh , cũng như bạn không thể gọi một phương thức tĩnh từ lớp con.

Vì vậy, hãy nói thêm một vài lời về giao diện chức năng và hãy tiếp tục. Dưới đây là danh sách chính của các FI (phần còn lại là các dạng của chúng):

    Vị ngữ - lấy một số giá trị T làm đối số, trả về boolean.

    Ví dụ:boolean someMethod(T t);

  • Người tiêu dùng - lấy đối số loại T, không trả về gì (void).

    Ví dụ:void someMethod(T t);

  • Nhà cung cấp - không lấy gì làm đầu vào nhưng trả về một số giá trị T.

    Ví dụ:T someMethod();

  • Hàm - lấy tham số loại T làm đầu vào, trả về giá trị loại R.

    Ví dụ:R someMethod(T t);

  • UnaryOperator - nhận đối số T và trả về giá trị kiểu T.

    Ví dụ:T someMethod(T t);

Suối

Luồng là một cách để xử lý cấu trúc dữ liệu theo kiểu chức năng. Thông thường đây là những bộ sưu tập (nhưng bạn có thể sử dụng chúng trong những tình huống khác ít phổ biến hơn). Theo ngôn ngữ dễ hiểu hơn, Stream là luồng dữ liệu mà chúng tôi xử lý như thể đang làm việc với tất cả dữ liệu cùng một lúc chứ không phải ép buộc như đối với mỗi dữ liệu. Hãy xem xét một ví dụ nhỏ. Giả sử chúng ta có một tập hợp các số mà chúng ta muốn lọc (nhỏ hơn 50), tăng thêm 5 và xuất 4 số đầu tiên từ các số còn lại ra bảng điều khiển. Làm thế nào chúng ta có thể làm điều này sớm hơn:
List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);

int count = 0;

for (int x : list) {

  if (x >= 50) continue;

  x += 5;

  count++;

  if (count > 4) break;

  System.out.print(x);

}
Có vẻ như không có nhiều mã và logic đã hơi khó hiểu. Hãy xem nó trông như thế nào khi sử dụng luồng:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
Luồng đơn giản hóa đáng kể cuộc sống bằng cách giảm số lượng mã và làm cho mã dễ đọc hơn. Đối với những người muốn tìm hiểu chi tiết hơn về chủ đề này, đây là một bài viết hay (tôi thậm chí có thể nói là xuất sắc) về chủ đề này .

Lambda

Có lẽ tính năng quan trọng và được chờ đợi từ lâu nhất là sự xuất hiện của lambdas. Lambda là gì? Đây là một khối mã có thể được chuyển đi khắp nơi để nó có thể được thực thi sau này bao nhiêu lần nếu cần. Nghe có vẻ khá khó hiểu phải không? Nói một cách đơn giản, bằng cách sử dụng lambdas, bạn có thể triển khai một phương thức của giao diện chức năng (một kiểu triển khai của một lớp ẩn danh):
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
Chúng tôi đã triển khai phương thức run() một cách nhanh chóng và không cần quan liêu. Và đúng: Runnable là một giao diện chức năng. Tôi cũng sử dụng lambda khi làm việc với luồng (như trong ví dụ về luồng ở trên). Chúng ta sẽ không đi quá sâu, vì chúng ta có thể lặn khá sâu, tôi sẽ để lại một vài liên kết để những người vẫn còn là người thích đào bới có thể đào sâu hơn:

cho mỗi

Java 8 có một foreach mới hoạt động với luồng dữ liệu giống như luồng. Đây là một ví dụ:
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(tương tự như someList.stream().foreach(…))

Tham khảo phương pháp

Phương thức tham chiếu là một cú pháp mới, hữu ích được thiết kế để tham chiếu các phương thức hoặc hàm tạo hiện có của các lớp hoặc đối tượng Java thông qua :: Tham chiếu phương thức có bốn loại:
  1. Liên kết với nhà thiết kế:

    SomeObject obj = SomeObject::new

  2. Tham khảo phương pháp tĩnh:

    SomeObject::someStaticMethod

  3. Một tham chiếu đến một phương thức không tĩnh của một đối tượng thuộc một loại nhất định:

    SomeObject::someMethod

  4. Tham chiếu đến phương thức thông thường (không tĩnh) của một đối tượng cụ thể

    obj::someMethod

Thông thường, tham chiếu phương thức được sử dụng trong luồng thay vì lambda (phương thức tham chiếu nhanh hơn lambda nhưng kém hơn về khả năng đọc).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
Dành cho những ai muốn biết thêm thông tin về các phương pháp tham khảo:

Thời gian API

Có một thư viện mới để làm việc với ngày và giờ - java.time. Từ 8 đến 13: tổng quan đầy đủ về các phiên bản Java.  Phần 1 - 2API mới tương tự như bất kỳ Joda-Time nào. Các phần quan trọng nhất của API này là:
  • Ví dụ: LocalDate là một ngày cụ thể - 2010-01-09;
  • LocalTime - thời gian có tính đến múi giờ - 19:45:55 (tương tự LocalDate);
  • LocalDateTime - kết hợp LocalDate + LocalTime - 2020-01-04 15:37:47;
  • ZoneId - đại diện cho múi giờ;
  • Đồng hồ - sử dụng loại này bạn có thể truy cập ngày giờ hiện tại.
Dưới đây là một vài bài viết thực sự thú vị về chủ đề này:

Không bắt buộc

Đây là một lớp mới trong gói java.util , một trình bao bọc giá trị có mẹo nhỏ là nó cũng có thể chứa null một cách an toàn . Nhận tùy chọn: Nếu chúng tôi chuyển nullOptional<String> someOptional = Optional.of("Something"); vào Tùy chọn.of , chúng tôi sẽ nhận được NullPointerException yêu thích của mình . Đối với những trường hợp như vậy, họ sử dụng: - trong phương pháp này, bạn không cần phải sợ giá trị rỗng. Tiếp theo, tạo một tùy chọn trống ban đầu: Để kiểm tra xem nó có trống không, hãy sử dụng: sẽ trả về true hoặc false cho chúng tôi. Thực hiện một hành động nhất định nếu có một giá trị và không làm gì nếu không có giá trị: Phương thức đảo ngược trả về giá trị được truyền nếu Tùy chọn trống (một loại kế hoạch dự phòng): Bạn có thể tiếp tục trong một thời gian rất, rất dài ( may mắn thay, Tùy chọn đã thêm các phương pháp bằng cả hai bàn tay hào phóng), nhưng chúng tôi sẽ không đề cập đến vấn đề này. Tốt hơn hết là tôi nên để lại một vài liên kết cho người mới bắt đầu: Optional<String> someOptional = Optional.ofNullable("Something");Optional<String> someOptional = Optional.empty();someOptional.isPresent();someOptional.ifPresent(System.out::println);System.out.println(someOptional.orElse("Some default content")); Chúng ta đã điểm qua những cải tiến nổi tiếng nhất trong Java 8 - đó chưa phải là tất cả. Nếu bạn muốn biết thêm thì tôi để lại điều này cho bạn:

Java 9

Vì vậy, vào ngày 21 tháng 9 năm 2017, thế giới đã chứng kiến ​​JDK 9. Java 9 này đi kèm với một bộ tính năng phong phú. Mặc dù không có khái niệm ngôn ngữ mới nhưng các API và lệnh chẩn đoán mới chắc chắn sẽ được các nhà phát triển quan tâm. Từ 8 đến 13: tổng quan đầy đủ về các phiên bản Java.  Phần 1 - 4

JShell (REPL - vòng lặp đọc-eval-in)

Đây là một bản triển khai Java của bảng điều khiển tương tác được sử dụng để kiểm tra chức năng và sử dụng các cấu trúc khác nhau trong bảng điều khiển, chẳng hạn như giao diện, lớp, enum, toán tử, v.v. Để khởi chạy JShell, bạn chỉ cần viết jshell trong terminal. Sau đó, chúng ta có thể viết bất cứ điều gì mà trí tưởng tượng của chúng ta cho phép: Từ 8 đến 13: tổng quan đầy đủ về các phiên bản Java.  Phần 1 - 5Sử dụng JShell, bạn có thể tạo các phương thức cấp cao nhất và sử dụng chúng trong cùng một phiên. Các phương thức này sẽ hoạt động giống như các phương thức tĩnh, ngoại trừ từ khóa tĩnh có thể được bỏ qua.Đọc thêm trong sách hướng dẫn Java 9 REPL (JShell) .

Riêng tư

Bắt đầu với phiên bản 9 của Java, chúng ta có cơ hội sử dụng các phương thức riêng tư trong các giao diện (các phương thức mặc định và tĩnh, vì đơn giản là chúng ta không thể ghi đè các phương thức khác do không đủ quyền truy cập). private static void someMethod(){} try-with-resources Khả năng xử lý các ngoại lệ Try-With-Resources đã được nâng cấp:
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

Tính mô đun ( ghép hình )

Mô-đun là một nhóm các gói và tài nguyên có liên quan cùng với tệp mô tả mô-đun mới. Cách tiếp cận này được sử dụng để nới lỏng sự ghép nối của mã. Khớp nối lỏng lẻo là yếu tố chính cho khả năng bảo trì và mở rộng mã. Tính mô đun được thực hiện ở các cấp độ khác nhau:
  1. Ngôn ngữ lập trình.
  2. Máy ảo.
  3. API java tiêu chuẩn.
JDK 9 đi kèm với 92 mô-đun: chúng ta có thể sử dụng chúng hoặc tạo mô-đun của riêng mình. Dưới đây là một số liên kết để có cái nhìn sâu hơn:

Bộ sưu tập bất biến

Trong Java 9, có thể tạo và điền một bộ sưu tập bằng một dòng, đồng thời làm cho nó bất biến (trước đây, để tạo một bộ sưu tập bất biến, chúng ta cần tạo một bộ sưu tập, điền dữ liệu vào đó và gọi một phương thức, chẳng hạn: Collections.unmodibilityList). Một ví dụ về sự sáng tạo như vậy: List someList = List.of("first","second","third");

Những đổi mới khác:

  • tùy chọn mở rộng (thêm phương pháp mới);
  • các giao diện ProcessHandle và ProcessHandle xuất hiện để kiểm soát các hoạt động của hệ điều hành;
  • G1 - trình thu gom rác mặc định;
  • Máy khách HTTP hỗ trợ cả giao thức HTTP/2 và WebSocket;
  • Luồng mở rộng;
  • đã thêm khung API Luồng phản ứng (để lập trình phản ứng);
Để hiểu rõ hơn về Java 9, tôi khuyên bạn nên đọc:

Java 10

Vì vậy, sáu tháng sau khi phát hành Java 9, vào tháng 3 năm 2018 (tôi nhớ như in ngày hôm qua), Java 10 đã xuất hiện. Từ 8 đến 13: tổng quan đầy đủ về các phiên bản Java.  Phần 1 - 6

var

Bây giờ chúng tôi không phải cung cấp loại dữ liệu. Chúng tôi đánh dấu thông báo là var và trình biên dịch xác định loại thông báo theo loại trình khởi tạo ở bên phải. Tính năng này chỉ khả dụng cho các biến cục bộ có bộ khởi tạo: nó không thể được sử dụng cho các đối số phương thức, kiểu trả về, v.v., vì không có bộ khởi tạo nào có thể xác định kiểu. Ví dụ var (đối với loại Chuỗi):
var message = "Some message…..";
System.out.println(message);
var không phải là một từ khóa: về cơ bản nó là một tên loại dành riêng, giống như int . Lợi ích của var rất lớn: việc khai báo kiểu chiếm nhiều sự chú ý mà không mang lại lợi ích gì, và tính năng này sẽ tiết kiệm thời gian. Nhưng đồng thời, nếu một biến được lấy từ một chuỗi phương thức dài, mã sẽ trở nên khó đọc hơn vì ngay lập tức không rõ loại đối tượng nào nằm ở đó. Dành riêng cho những ai muốn làm quen hơn với chức năng này:

Trình biên dịch JIT (GraalVM)

Không dài dòng nữa, hãy để tôi nhắc bạn rằng khi bạn chạy lệnh javac, ứng dụng Java sẽ được biên dịch từ mã Java thành mã byte JVM, đây là biểu diễn nhị phân của ứng dụng. Nhưng bộ xử lý máy tính thông thường không thể thực thi mã byte JVM một cách đơn giản. Để chương trình JVM của bạn hoạt động, bạn cần một trình biên dịch khác cho mã byte này, mã này được chuyển đổi thành mã máy mà bộ xử lý đã có thể sử dụng. So với javac, trình biên dịch này phức tạp hơn nhiều nhưng cũng tạo ra mã máy chất lượng cao hơn. Hiện tại, OpenJDK chứa máy ảo HotSpot, máy ảo này có hai trình biên dịch JIT chính. Đầu tiên, C1 ( trình biên dịch máy khách ), được thiết kế để hoạt động ở tốc độ cao hơn, nhưng việc tối ưu hóa mã bị ảnh hưởng. Thứ hai là C2 (trình biên dịch máy chủ). Tốc độ thực thi bị ảnh hưởng nhưng mã được tối ưu hóa hơn. Khi nào cái nào được sử dụng? C1 rất lý tưởng cho các ứng dụng máy tính để bàn, nơi mà việc tạm dừng JIT kéo dài là điều không mong muốn và C2 rất lý tưởng cho các chương trình máy chủ chạy dài, nơi việc dành nhiều thời gian hơn cho việc biên dịch là khá chấp nhận được. Quá trình biên dịch đa cấp là khi quá trình biên dịch đầu tiên đi qua C1 và kết quả đi qua C2 (được sử dụng để tối ưu hóa cao hơn). GraalVM là một dự án được tạo ra để thay thế hoàn toàn HotSpot. Chúng ta có thể coi Graal như một số dự án liên quan: trình biên dịch JIT mới cho HotSpot và máy ảo đa ngôn ngữ mới. Điểm đặc biệt của trình biên dịch JIT này là nó được viết bằng Java. Ưu điểm của trình biên dịch Graal là an toàn, tức là không gặp sự cố mà là ngoại lệ, không rò rỉ bộ nhớ. Chúng tôi cũng sẽ có sự hỗ trợ tốt về IDE và chúng tôi sẽ có thể sử dụng trình gỡ lỗi, trình phân tích hồ sơ hoặc các công cụ tiện lợi khác. Ngoài ra, trình biên dịch có thể độc lập với HotSpot và nó sẽ có thể tạo phiên bản do JIT biên dịch nhanh hơn. Đối với máy đào:

Song song G1

Trình thu gom rác G1 chắc chắn rất tuyệt vời, không còn nghi ngờ gì nữa, nhưng nó cũng có một điểm yếu: nó thực hiện chu trình GC đầy đủ một luồng. Vào thời điểm bạn cần tất cả sức mạnh của phần cứng mà bạn có thể tập hợp để tìm các đối tượng không sử dụng, chúng tôi bị giới hạn ở một luồng duy nhất. Java 10 đã sửa lỗi này. Bây giờ GC hiện hoạt động với tất cả tài nguyên mà chúng tôi thêm vào nó (nghĩa là nó trở nên đa luồng). Để đạt được điều này, các nhà phát triển ngôn ngữ đã cải thiện khả năng tách biệt các nguồn chính khỏi GC, tạo ra một giao diện sạch đẹp cho GC. Các nhà phát triển của sự dễ thương này, OpenJDK, đã phải đặc biệt dọn sạch kết xuất trong mã để không chỉ đơn giản hóa việc tạo các GC mới càng nhiều càng tốt mà còn để có thể nhanh chóng vô hiệu hóa các GC không cần thiết khỏi tổ hợp. Một trong những tiêu chí chính để thành công là không bị giảm tốc độ vận hành sau tất cả những cải tiến này. Chúng ta hãy xem thêm: Những đổi mới khác:
  1. Giao diện thu gom rác sạch sẽ được giới thiệu. Điều này cải thiện khả năng cách ly mã nguồn khỏi các trình thu gom rác khác nhau, giúp có thể tích hợp các trình thu gom thay thế một cách nhanh chóng và dễ dàng;
  2. Kết hợp các nguồn JDK vào một kho lưu trữ;
  3. Bộ sưu tập đã nhận được một phương thức mới - copyOf (Collection) , trả về một bản sao bất biến của bộ sưu tập này;
  4. Tùy chọn (và các biến thể của nó) có phương thức mới .orElseThrow() ;
  5. Từ giờ trở đi, các JVM biết rằng chúng đang chạy trong vùng chứa Docker và sẽ tìm nạp cấu hình dành riêng cho vùng chứa thay vì truy vấn chính hệ điều hành.
Dưới đây là một số tài liệu khác để giới thiệu chi tiết hơn về Java 10: Tôi đã từng rất bối rối vì một số phiên bản Java được gọi là 1.x. Tôi muốn nói rõ: Các phiên bản Java trước phiên bản 9 chỉ đơn giản là có cách đặt tên khác. Ví dụ: Java 8 cũng có thể được gọi là 1.8 , Java 5 - 1.5 , v.v. Và bây giờ chúng ta thấy rằng với việc chuyển đổi sang các bản phát hành từ Java 9, cách đặt tên cũng đã thay đổi và các phiên bản Java không còn có tiền tố 1.x nữa . Đến đây là phần cuối của phần đầu tiên: chúng ta đã điểm qua các tính năng mới thú vị của java 8-10. Hãy cùng tiếp tục làm quen với những thông tin mới nhất ở bài viết tiếp theo nhé.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION