JavaRush /Java Blog /Random-ID /Dari 8 hingga 13: gambaran lengkap versi Java. Bagian 1

Dari 8 hingga 13: gambaran lengkap versi Java. Bagian 1

Dipublikasikan di grup Random-ID
Kittens, halo semuanya)) Jadi, hari ini kita berada di tahun 2020, dan hanya ada sedikit yang tersisa hingga rilis Java 14. Anda akan mengharapkan versi selesainya pada tanggal 17 Maret, kami akan menganalisis apa yang segar dan menarik di sana setelah faktanya, tetapi hari ini saya ingin menyegarkan ingatan saya tentang versi Java sebelumnya. Hal baru apa yang mereka bawakan untuk kita? Mari kita lihat. Mari kita mulai review dengan Java 8, karena masih cukup relevan dan digunakan di sebagian besar proyek. Dari 8 hingga 13: gambaran lengkap versi Java.  Bagian 1 - 1Sebelumnya, versi baru dirilis setiap 3-5 tahun, namun baru-baru ini Oracle mengambil pendekatan yang berbeda - “Java baru setiap enam bulan.” Jadi, setiap enam bulan kami melihat rilis fitur. Entah itu baik atau buruk, setiap orang melihatnya secara berbeda. Misalnya, saya tidak terlalu menyukainya, karena versi baru tidak memiliki banyak fitur baru, tetapi pada saat yang sama, versi tersebut tumbuh seperti jamur setelah hujan. Saya berkedip beberapa kali pada proyek dengan Java 8, dan Java 16 sudah dirilis (tetapi jarang keluar, fitur-fitur baru menumpuk, dan pada akhirnya acara ini ditunggu-tunggu, seperti hari libur: semua orang mendiskusikan barang baru dan Anda tidak dapat melewatinya). Jadi mari kita mulai!

Jawa 8

Antarmuka Fungsional

Apa ini? Antarmuka fungsional adalah antarmuka yang berisi satu metode (abstrak) yang belum diimplementasikan. @FunctionalInterface adalah anotasi opsional yang ditempatkan di atas antarmuka tersebut. Diperlukan untuk memeriksa apakah memenuhi persyaratan antarmuka fungsional (hanya memiliki satu metode abstrak). Namun seperti biasa, kami memiliki beberapa peringatan: metode default dan statis tidak termasuk dalam persyaratan ini. Oleh karena itu, mungkin ada beberapa metode seperti itu + satu metode abstrak, dan antarmuka akan berfungsi. Ini mungkin juga berisi metode kelas Object yang tidak mempengaruhi definisi antarmuka sebagai fungsional. Saya akan menambahkan beberapa kata tentang metode default dan statis:
  1. Metode dengan pengubah default memungkinkan Anda menambahkan metode baru ke antarmuka tanpa merusak implementasi yang sudah ada.

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

    Ya, ya, kami menambahkan metode yang diimplementasikan ke antarmuka, dan saat mengimplementasikan metode ini, Anda tidak dapat menimpanya, tetapi menggunakannya sebagai metode yang diwarisi. Tetapi jika suatu kelas mengimplementasikan dua antarmuka dengan metode tertentu, kita akan mengalami kesalahan kompilasi, dan jika kelas tersebut mengimplementasikan antarmuka dan mewarisi kelas dengan metode tertentu yang identik, metode kelas induk akan tumpang tindih dengan metode antarmuka dan pengecualian tidak akan berfungsi.

  2. metode statis di antarmuka bekerja sama dengan metode statis di kelas. Jangan lupa: Anda tidak bisa mewarisi metode statis , sama seperti Anda tidak bisa memanggil metode statis dari kelas turunannya.

Jadi, beberapa kata lagi tentang antarmuka fungsional dan mari kita lanjutkan. Berikut adalah daftar utama FI (sisanya adalah jenisnya):

    Predikat - mengambil beberapa nilai T sebagai argumen, mengembalikan boolean.

    Contoh:boolean someMethod(T t);

  • Konsumen - mengambil argumen tipe T, tidak mengembalikan apa pun (batal).

    Contoh:void someMethod(T t);

  • Pemasok - tidak mengambil apa pun sebagai masukan, tetapi mengembalikan sejumlah nilai T.

    Contoh:T someMethod();

  • Fungsi - mengambil parameter tipe T sebagai input, mengembalikan nilai tipe R.

    Contoh:R someMethod(T t);

  • UnaryOperator - mengambil argumen T dan mengembalikan nilai tipe T.

    Contoh:T someMethod(T t);

Sungai kecil

Aliran adalah cara untuk menangani struktur data dalam gaya fungsional. Biasanya ini adalah koleksi (tetapi Anda dapat menggunakannya dalam situasi lain yang kurang umum). Dalam bahasa yang lebih mudah dipahami, Stream adalah aliran data yang kami proses seolah-olah bekerja dengan semua data pada saat yang sama, dan bukan brute force, seperti pada for-each. Mari kita lihat contoh kecilnya. Katakanlah kita memiliki sekumpulan angka yang ingin kita filter (kurang dari 50), ditambah 5, dan menampilkan 4 angka pertama dari angka yang tersisa ke konsol. Bagaimana kita melakukan ini sebelumnya:
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);

}
Sepertinya tidak banyak kode, dan logikanya sudah sedikit membingungkan. Mari kita lihat tampilannya menggunakan aliran:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
Streaming sangat menyederhanakan hidup dengan mengurangi jumlah kode dan membuatnya lebih mudah dibaca. Bagi mereka yang ingin mempelajari topik ini lebih detail, berikut adalah artikel bagus (bahkan menurut saya sangat bagus) tentang topik ini .

Lambda

Mungkin fitur yang paling penting dan ditunggu-tunggu adalah tampilan lambda. Apa itu lambda? Ini adalah blok kode yang dapat diteruskan ke berbagai tempat sehingga dapat dieksekusi nanti sebanyak yang diperlukan. Kedengarannya cukup membingungkan, bukan? Sederhananya, dengan menggunakan lambda, Anda dapat mengimplementasikan metode antarmuka fungsional (semacam implementasi kelas anonim):
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
Kami menerapkan metode run() dengan cepat dan tanpa birokrasi yang tidak perlu. Dan ya: Runnable adalah antarmuka fungsional. Saya juga menggunakan lambda saat bekerja dengan stream (seperti pada contoh stream di atas). Kita tidak akan membahasnya terlalu dalam, karena kita bisa menyelam cukup dalam, saya akan meninggalkan beberapa tautan agar orang-orang yang masih berjiwa penggali bisa menggali lebih dalam:

untuk setiap

Java 8 memiliki foreach baru yang bekerja dengan aliran data seperti aliran. Berikut ini contohnya:
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(analog dengan someList.stream().foreach(…))

Referensi metode

Metode referensi adalah sintaks baru dan berguna yang dirancang untuk mereferensikan metode atau konstruktor kelas atau objek Java yang ada melalui :: Referensi metode tersedia dalam empat jenis:
  1. Tautan ke desainer:

    SomeObject obj = SomeObject::new

  2. Referensi metode statis:

    SomeObject::someStaticMethod

  3. Referensi ke metode non-statis dari suatu objek dengan tipe tertentu:

    SomeObject::someMethod

  4. Referensi ke metode reguler (non-statis) dari objek tertentu

    obj::someMethod

Seringkali, referensi metode digunakan dalam aliran daripada lambda (metode referensi lebih cepat daripada lambda, tetapi keterbacaannya lebih rendah).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
Bagi mereka yang menginginkan informasi lebih lanjut tentang metode referensi:

Waktu API

Ada perpustakaan baru untuk bekerja dengan tanggal dan waktu - java.time. Dari 8 hingga 13: gambaran lengkap versi Java.  Bagian 1 - 2API baru ini mirip dengan Joda-Time mana pun. Bagian terpenting dari API ini adalah:
  • LocalDate adalah tanggal tertentu, sebagai contoh - 09-01-2010;
  • LocalTime - waktu dengan mempertimbangkan zona waktu - 19:45:55 (analog dengan LocalDate);
  • LocalDateTime - kombo LocalDate + LocalTime - 04-01-2020 15:37:47;
  • ZoneId - mewakili zona waktu;
  • Jam - menggunakan tipe ini Anda dapat mengakses waktu dan tanggal saat ini.
Berikut adalah beberapa artikel yang sangat menarik tentang topik ini:

Opsional

Ini adalah kelas baru dalam paket java.util , pembungkus nilai yang triknya adalah ia juga dapat berisi null dengan aman . Menerima opsional: Jika kita meneruskan nullOptional<String> someOptional = Optional.of("Something"); di Optional.of , kita akan mendapatkan NullPointerException favorit kita . Untuk kasus seperti ini mereka menggunakan: - dalam metode ini Anda tidak perlu takut dengan null. Selanjutnya, buat Optional: yang awalnya kosong: Untuk memeriksa apakah kosong, gunakan: akan mengembalikan nilai true atau false kepada kita. Lakukan tindakan tertentu jika ada nilai, dan tidak melakukan apa pun jika tidak ada nilai: Metode sebaliknya yang mengembalikan nilai yang diteruskan jika Opsional kosong (semacam rencana cadangan): Anda dapat melanjutkan untuk waktu yang sangat, sangat lama ( untungnya, Opsional telah menambahkan metode dengan kedua tangan yang murah hati), tetapi kami tidak akan memikirkan hal ini. Lebih baik saya meninggalkan beberapa tautan sebagai permulaan: 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")); Kami membahas inovasi paling terkenal di Java 8 - bukan itu saja. Jika Anda ingin tahu lebih banyak, saya tinggalkan ini untuk Anda:

Jawa 9

Jadi, pada tanggal 21 September 2017, dunia melihat JDK 9. Java 9 ini hadir dengan serangkaian fitur yang kaya. Meskipun tidak ada konsep bahasa baru, API dan perintah diagnostik baru pasti akan menarik bagi pengembang. Dari 8 hingga 13: gambaran lengkap versi Java.  Bagian 1 - 4

JShell (REPL - loop baca-eval-cetak)

Ini adalah implementasi Java dari konsol interaktif yang digunakan untuk menguji fungsionalitas dan menggunakan konstruksi berbeda di konsol, seperti antarmuka, kelas, enum, operator, dll. Untuk meluncurkan JShell, Anda hanya perlu menulis jshell di terminal. Kemudian kita dapat menulis apa pun yang dimungkinkan oleh imajinasi kita: Dari 8 hingga 13: gambaran lengkap versi Java.  Bagian 1 - 5Dengan menggunakan JShell, Anda dapat membuat metode tingkat atas dan menggunakannya dalam sesi yang sama. Metode ini akan bekerja seperti metode statis, hanya saja kata kunci static dapat dihilangkan. Baca lebih lanjut di manual Java 9. REPL (JShell) .

Pribadi

Dimulai dengan Java versi 9, kami memiliki kesempatan untuk menggunakan metode pribadi di antarmuka (metode default dan statis, karena kami tidak dapat mengganti metode lain karena akses yang tidak memadai). private static void someMethod(){} try-with-resources Kemampuan untuk menangani pengecualian Coba-Dengan-Sumber Daya telah ditingkatkan:
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

Modularitas ( Gergaji ukir )

Modul adalah sekelompok paket dan sumber daya terkait bersama dengan file deskriptor modul baru. Pendekatan ini digunakan untuk melonggarkan sambungan kode. Kopling yang longgar adalah faktor kunci untuk pemeliharaan dan ekstensibilitas kode. Modularitas diimplementasikan pada tingkat yang berbeda:
  1. Bahasa pemrograman.
  2. Mesin virtual.
  3. API java standar.
JDK 9 hadir dengan 92 modul: kita dapat menggunakannya atau membuatnya sendiri. Berikut ini beberapa tautan untuk melihat lebih dalam:

Koleksi yang Tidak Dapat Diubah

Di Java 9, dimungkinkan untuk membuat dan mengisi koleksi dengan satu baris, sekaligus membuatnya tidak dapat diubah (sebelumnya, untuk membuat koleksi yang tidak dapat diubah, kita perlu membuat koleksi, mengisinya dengan data, dan memanggil metode, misalnya, Koleksi.daftar yang tidak dapat dimodifikasi). Contoh kreasi tersebut: List someList = List.of("first","second","third");

Inovasi lainnya:

  • diperluas Opsional (metode baru ditambahkan);
  • antarmuka ProcessHandle dan ProcessHandle muncul untuk mengontrol tindakan sistem operasi;
  • G1 - pengumpul sampah default;
  • Klien HTTP dengan dukungan untuk protokol HTTP/2 dan WebSocket;
  • Aliran yang diperluas;
  • menambahkan kerangka API Reaktif Streams (untuk pemrograman reaktif);
Untuk pemahaman yang lebih lengkap tentang Java 9, saya menyarankan Anda untuk membaca:

Jawa 10

Jadi, enam bulan setelah rilis Java 9, pada bulan Maret 2018 (saya ingat seperti kemarin), Java 10 hadir. Dari 8 hingga 13: gambaran lengkap versi Java.  Bagian 1 - 6

var

Sekarang kita tidak perlu menyediakan tipe data. Kami menandai pesan tersebut sebagai var dan kompiler menentukan jenis pesan berdasarkan jenis penginisialisasi yang ada di sebelah kanan. Fitur ini hanya tersedia untuk variabel lokal dengan penginisialisasi: tidak dapat digunakan untuk argumen metode, tipe kembalian, dll., karena tidak ada penginisialisasi untuk dapat menentukan tipenya. Contoh var (untuk tipe String):
var message = "Some message…..";
System.out.println(message);
var bukan kata kunci: pada dasarnya ini adalah nama tipe yang dicadangkan, sama seperti int . Manfaat var sangat besar: deklarasi tipe menyita banyak perhatian tanpa memberikan manfaat apa pun, dan fitur ini akan menghemat waktu. Tetapi pada saat yang sama, jika suatu variabel diperoleh dari serangkaian metode yang panjang, kodenya menjadi kurang mudah dibaca, karena tidak jelas objek apa yang ada di sana. Didedikasikan untuk mereka yang ingin lebih mengenal fungsi ini:

Kompiler JIT (GraalVM)

Tanpa basa-basi lagi, izinkan saya mengingatkan Anda bahwa ketika Anda menjalankan perintah javac, aplikasi Java dikompilasi dari kode Java menjadi bytecode JVM, yang merupakan representasi biner dari aplikasi tersebut. Tapi prosesor komputer biasa tidak bisa begitu saja mengeksekusi bytecode JVM. Agar program JVM Anda dapat berfungsi, Anda memerlukan kompiler lain untuk bytecode ini, yang diubah menjadi kode mesin yang sudah dapat digunakan oleh prosesor. Dibandingkan dengan javac, kompiler ini jauh lebih kompleks, tetapi juga menghasilkan kode mesin dengan kualitas lebih tinggi. Saat ini, OpenJDK berisi mesin virtual HotSpot, yang memiliki dua kompiler JIT utama. Yang pertama, C1 ( kompiler klien ), dirancang untuk operasi berkecepatan lebih tinggi, tetapi optimasi kode terganggu. Yang kedua adalah C2 (kompiler server). Kecepatan eksekusinya menurun, tetapi kodenya lebih optimal. Kapan yang mana yang digunakan? C1 sangat bagus untuk aplikasi desktop di mana jeda JIT yang lama tidak diinginkan, dan C2 sangat bagus untuk program server yang berjalan lama di mana menghabiskan lebih banyak waktu untuk kompilasi cukup dapat diterima. Kompilasi bertingkat adalah ketika kompilasi pertama kali melewati C1, dan hasilnya melewati C2 (digunakan untuk optimasi yang lebih baik). GraalVM adalah proyek yang dibuat untuk sepenuhnya menggantikan HotSpot. Kita dapat menganggap Graal sebagai beberapa proyek terkait: kompiler JIT baru untuk HotSpot dan mesin virtual poliglot baru. Keunikan kompiler JIT ini adalah ditulis dalam Java. Keuntungan dari kompiler Graal adalah keamanan, bukan crash, tetapi pengecualian, bukan kebocoran memori. Kami juga akan memiliki dukungan IDE yang baik, dan kami akan dapat menggunakan debugger, profiler, atau alat praktis lainnya. Selain itu, kompiler mungkin tidak bergantung pada HotSpot, dan ia akan mampu membuat versi kompilasi JIT yang lebih cepat. Untuk penggali:

Paralel G1

Pengumpul sampah G1 memang keren, tidak diragukan lagi, tetapi ia juga memiliki titik lemah: ia menjalankan siklus GC penuh berulir tunggal. Pada saat Anda membutuhkan semua kekuatan perangkat keras yang dapat Anda kumpulkan untuk menemukan objek yang tidak terpakai, kami terbatas pada satu thread. Java 10 memperbaikinya. Sekarang GC berfungsi dengan semua sumber daya yang kami tambahkan ke dalamnya (yaitu, menjadi multi-thread). Untuk mencapai hal ini, pengembang bahasa telah meningkatkan isolasi sumber utama dari GC, menciptakan antarmuka bersih yang bagus untuk GC. Pengembang kelucuan ini, OpenJDK, harus secara khusus membersihkan dump dalam kode agar tidak hanya menyederhanakan pembuatan GC baru sebanyak mungkin, tetapi juga memungkinkan untuk dengan cepat menonaktifkan GC yang tidak perlu dari perakitan. Salah satu kriteria utama kesuksesan adalah tidak adanya penurunan kecepatan operasi setelah semua peningkatan ini. Mari kita lihat juga: Inovasi lainnya:
  1. Antarmuka Pengumpul Sampah yang bersih diperkenalkan. Hal ini meningkatkan isolasi kode sumber dari pengumpul sampah yang berbeda, sehingga memungkinkan untuk mengintegrasikan pengumpul alternatif dengan cepat dan mudah;
  2. Menggabungkan sumber JDK ke dalam satu repositori;
  3. Koleksi menerima metode baru - copyOf (Collection) , yang mengembalikan salinan koleksi ini yang tidak dapat diubah;
  4. Opsional (dan variannya) memiliki metode baru .orElseThrow() ;
  5. Mulai sekarang, JVM menyadari bahwa mereka berjalan di container Docker dan akan mengambil konfigurasi khusus container daripada menanyakan sistem operasi itu sendiri.
Berikut adalah beberapa materi untuk pengenalan lebih rinci tentang Java 10: Saya dulu sangat bingung dengan kenyataan bahwa beberapa versi Java disebut 1.x. Saya ingin memperjelas: Versi Java sebelum 9 memiliki skema penamaan yang berbeda. Misalnya, Java 8 juga bisa disebut 1.8 , Java 5 - 1.5 , dll. Dan sekarang kita melihat bahwa dengan transisi ke rilis dari Java 9, skema penamaan juga telah berubah, dan versi Java tidak lagi diawali dengan 1.x . Ini adalah akhir dari bagian pertama: kita membahas fitur-fitur baru yang menarik dari Java 8-10. Mari kita lanjutkan perkenalan kita yang terbaru pada postingan selanjutnya .
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION