Ciri-ciri Baru di Java 8

1. Gambaran keseluruhan

Dalam artikel ini, kita akan melihat dengan cepat beberapa ciri baru yang paling menarik di Java 8.

Kita akan membincangkan: kaedah lalai antara muka dan kaedah statik, rujukan kaedah dan Pilihan.

Kami telah membahas beberapa ciri peluncuran Java 8 - streaming API, ekspresi lambda dan antara muka fungsional - kerana topik tersebut merangkumi topik komprehensif yang layak untuk dilihat.

2. Kaedah Lalai dan Statik Antara Muka

Sebelum Java 8, antara muka hanya boleh menggunakan kaedah abstrak awam. Tidak mungkin untuk menambahkan fungsi baru ke antara muka yang ada tanpa memaksa semua kelas pelaksana untuk membuat pelaksanaan metode baru, dan juga tidak mungkin untuk membuat kaedah antara muka dengan implementasi.

Bermula dengan Java 8, antaramuka dapat memiliki metode statis dan lalai yang, meskipun dinyatakan dalam antarmuka, memiliki perilaku yang ditentukan.

2.1. Kaedah Statik

Pertimbangkan kaedah antara muka berikut (mari kita panggil Kenderaan antara muka ini ):

static String producer() { return "N&F Vehicles"; }

Kaedah pengeluar statik () hanya tersedia melalui dan dalam antara muka. Ia tidak boleh diganti oleh kelas pelaksana.

Untuk memanggilnya di luar antara muka, pendekatan standard untuk kaedah panggilan statik harus digunakan:

String producer = Vehicle.producer();

2.2. Kaedah Lalai

Kaedah lalai dinyatakan menggunakan kata kunci lalai baru . Ini dapat diakses melalui contoh kelas pelaksana dan boleh diganti.

Mari tambahkan kaedah lalai ke antara muka Kenderaan kami , yang juga akan membuat panggilan ke kaedah statik antara muka ini:

default String getOverview() { return "ATV made by " + producer(); }

Andaikan bahawa antara muka ini dilaksanakan oleh kelas VehicleImpl. Untuk melaksanakan kaedah lalai , contoh kelas ini harus dibuat:

Vehicle vehicle = new VehicleImpl(); String overview = vehicle.getOverview();

3. Rujukan Kaedah

Rujukan kaedah boleh digunakan sebagai alternatif yang lebih pendek dan lebih mudah dibaca untuk ungkapan lambda yang hanya memanggil kaedah yang ada. Terdapat empat varian rujukan kaedah.

3.1. Rujukan kepada Kaedah Statik

Rujukan kepada kaedah statik memegang sintaks berikut: ContainingClass :: methodName.

Mari cuba hitung semua rentetan kosong dalam Senarai dengan bantuan Stream API.

boolean isReal = list.stream().anyMatch(u -> User.isRealUser(u));

Melihat dengan lebih dekat di lambda ungkapan dalam anyMatch () kaedah, ia hanya membuat panggilan kepada kaedah statik isRealUser (pengguna User) daripada pengguna kelas. Oleh itu, ia boleh diganti dengan merujuk kepada kaedah statik:

boolean isReal = list.stream().anyMatch(User::isRealUser);

Jenis kod ini kelihatan lebih bermaklumat.

3.2. Rujukan kepada Kaedah Instance

Rujukan ke kaedah instance memegang sintaks berikut: c onainingInstance :: methodName. Kaedah panggilan kod berikut adalahLegalName (String string) jenis Pengguna yang mengesahkan parameter input:

User user = new User(); boolean isLegalName = list.stream().anyMatch(user::isLegalName); 

3.3. Rujukan kepada Kaedah Instance Objek Jenis Tertentu

Kaedah rujukan ini mengambil sintaks berikut: C onainingType :: methodName. Satu contoh::

long count = list.stream().filter(String::isEmpty).count();

3.4. Rujukan kepada Pembina

Rujukan kepada konstruktor mengambil sintaks berikut: ClassName :: new. Oleh kerana konstruktor di Java adalah metode khusus, referensi metode dapat diterapkan padanya juga dengan bantuan baru sebagai nama metode .

Stream stream = list.stream().map(User::new);

4. Pilihan

Sebelum Java 8 pemaju harus mengesahkan nilai-nilai yang mereka rujuk dengan hati-hati, kerana kemungkinan membuang NullPointerException (NPE) . Semua pemeriksaan ini memerlukan kod boilerplate yang cukup menjengkelkan dan rawan kesalahan.

Kelas pilihan Java 8 dapat membantu menangani situasi di mana ada kemungkinan mendapat NPE . Ia berfungsi sebagai wadah untuk objek jenis T. Ia dapat mengembalikan nilai objek ini jika nilai ini bukan nol . Apabila nilai di dalam bekas ini kosong, ia membolehkan melakukan beberapa tindakan yang telah ditentukan dan bukannya membuang NPE.

4.1. Penciptaan Pilihan

Contoh kelas Pilihan boleh dibuat dengan bantuan kaedah statiknya:

Optional optional = Optional.empty();

Mengembalikan Pilihan kosong .

String str = "value"; Optional optional = Optional.of(str);

Mengembalikan Pilihan yang mengandungi nilai bukan nol.

Optional optional = Optional.ofNullable(getString());

Will return an Optional with a specific value or an empty Optional if the parameter is null.

4.2. Optional Usage

For example, you expect to get a List and in the case of null you want to substitute it with a new instance of an ArrayList. With pre-Java 8's code you need to do something like this:

List list = getList(); List listOpt = list != null ? list : new ArrayList();

With Java 8 the same functionality can be achieved with a much shorter code:

List listOpt = getList().orElseGet(() -> new ArrayList());

There is even more boilerplate code when you need to reach some object's field in the old way. Assume you have an object of type User which has a field of type Address with a field street of type String. And for some reason you need to return a value of the street field if some exist or a default value if street is null:

User user = getUser(); if (user != null) { Address address = user.getAddress(); if (address != null) { String street = address.getStreet(); if (street != null) { return street; } } } return "not specified";

This can be simplified with Optional:

Optional user = Optional.ofNullable(getUser()); String result = user .map(User::getAddress) .map(Address::getStreet) .orElse("not specified");

In this example we used the map() method to convert results of calling the getAdress() to the Optional and getStreet() to Optional. If any of these methods returned null the map() method would return an empty Optional.

Imagine that our getters return Optional. So, we should use the flatMap() method instead of the map():

Optional optionalUser = Optional.ofNullable(getOptionalUser()); String result = optionalUser .flatMap(OptionalUser::getAddress) .flatMap(OptionalAddress::getStreet) .orElse("not specified");

Another use case of Optional is changing NPE with another exception. So, as we did previously, let's try to do this in pre-Java 8's style:

String value = null; String result = ""; try { result = value.toUpperCase(); } catch (NullPointerException exception) { throw new CustomException(); }

And what if we use Optional? The answer is more readable and simpler:

String value = null; Optional valueOpt = Optional.ofNullable(value); String result = valueOpt.orElseThrow(CustomException::new).toUpperCase();

Notice, that how and for what purpose to use Optional in your app is a serious and controversial design decision, and explanation of its all pros and cons is out of the scope of this article. If you are interested, you can dig deeper, there are plenty of interesting articles on the Internet devoted to this problem. This one and this another one could be very helpful.

5. Conclusion

In this article, we are briefly discussing some interesting new features in Java 8.

There are of course many other additions and improvements which are spread across many Java 8 JDK packages and classes.

But, the information illustrated in this article is a good starting point for exploring and learning about some of these new features.

Akhirnya, semua kod sumber untuk artikel tersebut tersedia di GitHub.