"Java masih belum mati - dan orang -orang mulai mengetahuinya."
Tutorial ini akan menggunakan kode beranotasi sederhana untuk menggambarkan fitur baru, dan Anda tidak akan melihat teks blockbuster.
1. Metode default antarmuka
Java 8 memungkinkan kita untuk menambahkan implementasi metode non-abstrak ke antarmuka, cukup gunakan kata kunci default.
Salinan kode adalah sebagai berikut:
Formula antarmuka {
Hitung ganda (int a);
default sqrt ganda (int a) {
return math.sqrt (a);
}
}
Selain memiliki metode yang dihitung, antarmuka rumus juga mendefinisikan metode SQRT.
Salinan kode adalah sebagai berikut:
Rumus rumus = rumus baru () {
@Mengesampingkan
PUBLIK PUBLIK Hitung (int a) {
return sqrt (a * 100);
}
};
Formula.Calculate (100);
Formula.sqrt (16);
Formula dalam artikel ini diimplementasikan sebagai contoh dari kelas anonim. Pada bagian selanjutnya, kita akan melihat pendekatan yang lebih sederhana untuk menerapkan antarmuka metode tunggal.
Catatan Penerjemah: Hanya ada warisan tunggal di Java. Dalam bahasa lain, metode memiliki kelas memiliki kode lain yang dapat digunakan kembali pada saat yang sama disebut mixin. Khusus Java 8 baru ini lebih dekat dengan sifat Scala dari perspektif implementasi kompiler. Ada juga konsep yang disebut metode ekstensi di C#, yang memungkinkan jenis yang ada diperpanjang, yang secara semantik berbeda dari ini di Java 8.
2. Ekspresi Lambda
Pertama, mari kita lihat bagaimana string diatur dalam versi lama Java:
Salinan kode adalah sebagai berikut:
Daftar <string> names = arrays.aslist ("Peter", "Anna", "Mike", "Xenia");
Collections.sort (nama, pembanding baru <string> () {
@Mengesampingkan
Public int Compare (String a, String b) {
return b.c.careto (a);
}
});
Lewati saja objek daftar dan pembanding dengan koleksi metode statis. Sort untuk mengaturnya dalam urutan yang ditentukan. Biasanya dilakukan untuk membuat objek pembanding anonim dan meneruskannya ke metode sortir.
Di Java 8, Anda tidak perlu menggunakan metode tradisional objek anonim ini.
Salinan kode adalah sebagai berikut:
Collections.sort (nama, (string a, string b) -> {
return b.c.careto (a);
});
Lihat, kode menjadi lebih tersegmentasi dan dapat dibaca, tetapi sebenarnya dapat ditulis lebih pendek:
Salinan kode adalah sebagai berikut:
Collections.sort (nama, (string a, string b) -> b.Compareto (a));
Untuk badan fungsi dengan hanya satu baris kode, Anda dapat menghapus kawat gigi {} dan mengembalikan kata kunci, tetapi Anda dapat menulisnya lebih pendek:
Salinan kode adalah sebagai berikut:
Collections.sort (nama, (a, b) -> b.c.careto (a));
Kompiler Java dapat secara otomatis menyimpulkan jenis parameter, jadi Anda tidak perlu menulis jenisnya lagi. Selanjutnya, mari kita lihat apa yang bisa dilakukan oleh ekspresi lambda yang lebih nyaman:
3. Antarmuka fungsional
Bagaimana ekspresi lambda diwakili dalam sistem jenis Java? Setiap ekspresi lambda sesuai dengan jenis, biasanya tipe antarmuka. "Antarmuka fungsional" mengacu pada antarmuka yang hanya berisi metode abstrak, dan setiap ekspresi lambda dari jenis ini akan dicocokkan dengan metode abstrak ini. Karena metode default bukan metode abstrak, Anda juga dapat menambahkan metode default ke antarmuka fungsional Anda.
Kami dapat memperlakukan ekspresi lambda sebagai jenis antarmuka apa pun yang hanya berisi satu metode abstrak untuk memastikan bahwa antarmuka Anda harus memenuhi persyaratan ini. Anotasi, kompiler akan menemukan bahwa antarmuka yang Anda tandai dianotasi oleh anotasi ini.
Contohnya adalah sebagai berikut:
Salinan kode adalah sebagai berikut:
@FunctionalInterface
konverter antarmuka <f, t> {
T mengonversi (f dari);
}
Converter <string, integer> converter = (from) -> integer.valueof (dari);
Integer dikonversi = converter.convert ("123");
System.out.println (dikonversi);
Perlu dicatat bahwa jika @functionalInterface tidak ditentukan, kode di atas juga benar.
Catatan penerjemah Lambda Expression ke antarmuka metode tunggal. Fungsi.
4. Metode dan Referensi Konstruktor
Kode di bagian sebelumnya juga dapat diwakili dengan referensi metode statis:
Salinan kode adalah sebagai berikut:
Konverter <string, integer> converter = integer :: valueof;
Integer dikonversi = converter.convert ("123");
System.out.println (dikonversi);
Java 8 memungkinkan Anda untuk menggunakan kata kunci :: untuk melewati metode atau referensi konstruktor.
Salinan kode adalah sebagai berikut:
converter = sesuatu :: startswith;
String converted = converter.convert ("java");
System.out.println (dikonversi); // "J"
Mari kita lihat bagaimana konstruktor direferensikan menggunakan kata kunci :: kami. Kami mendefinisikan kelas sederhana dengan beberapa konstruktor:
Salinan kode adalah sebagai berikut:
Class Person {
String FirstName;
String LastName;
Orang() {}
Person (String FirstName, String LastName) {
this.firstName = firstName;
this.LastName = LastName;
}
}
Selanjutnya kami menentukan antarmuka pabrik objek untuk membuat objek orang:
Salinan kode adalah sebagai berikut:
antarmuka personfactory <p memperluas orang> {
P create (string firstName, string lastName);
}
Di sini kami menggunakan referensi konstruktor untuk mengaitkannya alih -alih menerapkan pabrik lengkap:
Salinan kode adalah sebagai berikut:
Personfactory <Fone> personfactory = orang :: baru;
Orang orang = personfactory.create ("Peter", "Parker");
Kami hanya perlu menggunakan orang :: Baru untuk mendapatkan referensi ke Konstruktor Kelas Orang.
5. Lambda Scope
Cara untuk mengakses lingkup luar dalam ekspresi lambda mirip dengan yang ada di versi yang lebih lama dari objek anonim. Anda dapat secara langsung mengakses variabel lokal eksternal yang ditandai akhir, atau bidang dan variabel statis dari instance.
6. Akses variabel lokal
Kami dapat mengakses variabel lokal eksternal secara langsung dalam ekspresi lambda:
Salinan kode adalah sebagai berikut:
final int num = 1;
Converter <Integer, String> StringConverter =
(dari) -> string.valueof (dari + num);
StringConverter.convert (2);
Tetapi tidak seperti objek anonim, variabel num di sini dapat dinyatakan sebagai final tanpa menyatakannya sebagai final, dan kodenya juga benar:
Salinan kode adalah sebagai berikut:
int num = 1;
Converter <Integer, String> StringConverter =
(dari) -> string.valueof (dari + num);
StringConverter.convert (2);
Namun, num di sini tidak boleh dimodifikasi oleh kode selanjutnya (yaitu, secara implisit memiliki semantik akhir), misalnya, berikut ini tidak dapat dikompilasi:
Salinan kode adalah sebagai berikut:
int num = 1;
Converter <Integer, String> StringConverter =
(dari) -> string.valueof (dari + num);
num = 3;
Mencoba memodifikasi NUM dalam ekspresi lambda juga tidak diizinkan.
7. Bidang Objek Akses dan Variabel Statis
Tidak seperti variabel lokal, bidang dan variabel statis dalam lambda dapat dibaca dan ditulis. Perilaku ini konsisten dengan objek anonim:
Salin kode sebagai berikut: kelas lambda4 {
statis int outerstaticnum;
interernum int;
void testscopes () {
Converter <integer, string> stringConverter1 = (from) -> {
Ook Otorum = 23;
return string.valueof (dari);
};
Converter <integer, string> stringConverter2 = (from) -> {
outerstaticnum = 72;
return string.valueof (dari);
};
}
}
8. Metode default untuk mengakses antarmuka
Ingat contoh rumus di bagian pertama.
Metode default tidak dapat diakses dalam ekspresi Lambda, dan kode berikut tidak akan dikompilasi:
Salinan kode adalah sebagai berikut:
Rumus rumus = (a) -> sqrt (a * 100);
Antarmuka fungsional bawaan
JDK 1.8 API berisi banyak antarmuka fungsional built-in, seperti komparator atau antarmuka runnable yang biasa digunakan dalam java lama, dan antarmuka ini telah menambahkan anotasi @FunctionAlinterface untuk digunakan pada lambdas.
Java 8 API juga menyediakan banyak antarmuka fungsional baru untuk membuat pekerjaan lebih nyaman.
Antarmuka predikat
Antarmuka predikat hanya memiliki satu parameter, yang mengembalikan tipe boolean. Antarmuka ini berisi sejumlah metode default untuk menggabungkan predikat ke dalam logika kompleks lainnya (seperti: versus, atau, non):
Salinan kode adalah sebagai berikut:
Predikat <string> predicate = (s) -> s.length ()> 0;
predict.test ("foo");
predict.negate (). Test ("foo");
Predikat <Boolean> nonnull = objek :: nonnull;
Predikat <Boolean> isnull = objek :: isnull;
Predikat <string> isEmpty = string :: isEmpty;
Predikat <string> isNotEmpty = isEmpty.negate ();
Antarmuka fungsi
Antarmuka fungsi memiliki parameter dan mengembalikan hasilnya, dan dilengkapi dengan beberapa metode default (komposisi, dan kemudian) yang dapat dikombinasikan dengan fungsi lain:
Salinan kode adalah sebagai berikut:
Fungsi <string, integer> tointeger = integer :: valueof;
Function <string, string> backtoString = toInteger.andthen (string :: valueof);
backtoString.Amply ("123");
Antarmuka pemasok
Antarmuka pemasok mengembalikan nilai jenis apa pun.
Salinan kode adalah sebagai berikut:
Pemasok <FERSON> PERSUSPLIER = orang :: baru;
Personsupplier.get ();
Antarmuka konsumen
Antarmuka konsumen mewakili operasi yang dilakukan pada satu parameter.
Salinan kode adalah sebagai berikut:
Konsumen <Son> sore = (p) -> System.out.println ("Hello," + p.firstname);
penyambut.
Antarmuka pembanding
Comparator adalah antarmuka klasik di java lama, dan Java 8 telah menambahkan berbagai metode default di dalamnya:
Salinan kode adalah sebagai berikut:
Komparator <Fone> comparator = (p1, p2) -> p1.firstname.compareto (p2.firstname);
Orang p1 = orang baru ("John", "doe");
Orang P2 = orang baru ("Alice", "Wonderland");
pembanding.compare (P1, P2);
pembanding. Reversed (). Bandingkan (P1, P2);
Antarmuka opsional
Opsional bukanlah fungsi tetapi antarmuka.
Opsional didefinisikan sebagai wadah sederhana yang nilainya mungkin nol atau tidak. Sebelum Java 8, suatu fungsi umumnya harus mengembalikan objek yang tidak kosong, tetapi kadang-kadang dapat mengembalikan nol.
Salinan kode adalah sebagai berikut:
Opsional <string> opsional = opsional.of ("bam");
opsional.ispresent ();
opsional.get ();
opsional.orelse ("Fallback"); // "BAM"
opsional.ifpresent ((s) -> System.out.println (S.charat (0)));
Antarmuka aliran
java.util.stream mewakili urutan operasi yang dapat diterapkan pada satu set elemen pada satu waktu. Operasi stream dibagi menjadi dua jenis: Operasi menengah atau operasi akhir. Penciptaan aliran membutuhkan penentu sumber data, seperti subkelas java.util.collection, daftar atau set, yang tidak didukung oleh peta. Operasi stream dapat dieksekusi secara serial atau paralel.
Pertama, mari kita lihat bagaimana aliran digunakan.
Salinan kode adalah sebagai berikut:
Daftar <String> StringCollection = ArrayList baru <> ();
StringCollection.Add ("ddd2");
StringCollection.Add ("AAA2");
StringCollection.Add ("BBB1");
StringCollection.Add ("AAA1");
StringCollection.Add ("BBB3");
StringCollection.Add ("CCC");
StringCollection.Add ("BBB2");
StringCollection.Add ("ddd1");
Java 8 memperluas kelas koleksi, dan dapat membuat aliran melalui collection.stream () atau collection.parallelstream (). Bagian berikut akan menjelaskan operasi aliran yang umum digunakan secara rinci:
Filter filter
Penyaringan disaring melalui antarmuka predikat dan hanya elemen yang memenuhi kriteria yang disimpan. Foreach membutuhkan fungsi untuk menjalankan elemen yang difilter secara berurutan. Foreach adalah operasi terakhir, jadi kami tidak dapat melakukan operasi aliran lain setelah foreach.
Salinan kode adalah sebagai berikut:
StringCollection
.sungai kecil()
.filter ((s) -> s.startswith ("a"))
.foreach (System.out :: println);
// "aaa2", "aaa1"
Sortir
Sort adalah operasi perantara, dan aliran yang dikembalikan setelah penyortiran dikembalikan. Jika Anda tidak menentukan pembanding khusus, jenis default akan digunakan.
Salinan kode adalah sebagai berikut:
StringCollection
.sungai kecil()
.sorted ()
.filter ((s) -> s.startswith ("a"))
.foreach (System.out :: println);
// "aaa1", "aaa2"
Perlu dicatat bahwa penyortiran hanya membuat aliran yang diatur, dan tidak akan mempengaruhi sumber data asli.
Salinan kode adalah sebagai berikut:
System.out.println (StringCollection);
// DDD2, AAA2, BBB1, AAA1, BBB3, CCC, BBB2, DDD1
Pemetaan peta
Peta operasi menengah mengubah elemen menjadi objek tambahan secara berurutan sesuai dengan antarmuka fungsi yang ditentukan. Contoh berikut menunjukkan mengkonversi string ke string modal. Anda juga dapat menggunakan peta untuk mengonversi objek ke jenis lain.
Salinan kode adalah sebagai berikut:
StringCollection
.sungai kecil()
.map (string :: toUppercase)
.sorted ((a, b) -> b.c.careto (a))
.foreach (System.out :: println);
// "ddd2", "ddd1", "ccc", "bbb3", "bbb2", "aaa2", "aaa1"
Cocok
Stream menyediakan berbagai operasi pencocokan, memungkinkan deteksi apakah predikat tertentu cocok dengan seluruh aliran. Semua operasi pencocokan adalah operasi akhir dan mengembalikan nilai tipe boolean.
Salinan kode adalah sebagai berikut:
boolean anystartswitha =
StringCollection
.sungai kecil()
.anymatch ((s) -> s.startswith ("a"));
System.out.println (Anystartswitha);
boolean allstartswitha =
StringCollection
.sungai kecil()
.AllMatch ((S) -> S.Startswith ("A"));
System.out.println (Allstartswitha);
boolean non -startswithz =
StringCollection
.sungai kecil()
.nonematch ((s) -> s.startswith ("z"));
System.out.println (nonestartswithz);
Menghitung
Penghitungan adalah operasi akhir, yang mengembalikan jumlah elemen dalam aliran, dan tipe nilai pengembalian panjang.
Salinan kode adalah sebagai berikut:
startSwithb long =
StringCollection
.sungai kecil()
.filter ((s) -> s.startswith ("b"))
.menghitung();
System.out.println (StartSwithB);
Mengurangi peraturan
Ini adalah operasi terakhir, memungkinkan beberapa elemen dalam aliran untuk didefinisikan sebagai satu elemen melalui fungsi yang ditentukan, dan hasil kelayakan diwakili oleh antarmuka opsional:
Salinan kode adalah sebagai berikut:
Opsional <string> direduksi =
StringCollection
.sungai kecil()
.sorted ()
.reduce ((s1, s2) -> s1 + "#" + s2);
reded.ifpresent (System.out :: println);
// "AAA1#AAA2#BB1#BB2#BB3#CCC#DDD1#DDD2"
Aliran paralel
Seperti yang disebutkan sebelumnya, Stream memiliki dua jenis: serial dan paralel.
Contoh berikut menunjukkan cara meningkatkan kinerja melalui aliran paralel:
Pertama kami membuat meja besar tanpa elemen duplikat:
Salinan kode adalah sebagai berikut:
int maks = 1000000;
Daftar <String> values = new ArrayList <> (max);
untuk (int i = 0; i <max; i ++) {
Uuid uuid = uuid.randomuuid ();
values.add (uuid.tostring ());
}
Lalu kami menghitung berapa lama untuk mengurutkan aliran ini.
Jenis Serial:
Salinan kode adalah sebagai berikut:
long t0 = system.nanoTime ();
long count = values.stream (). sorted (). count ();
System.out.println (Count);
long t1 = system.nanoTime ();
long millis = timeunit.nanoseconds.tomillis (t1 - t0);
System.out.println (string.format ("Sortir Sequential mengambil: %d ms", millis));
// Waktu Seri: 899 ms
Penyortiran paralel:
Salinan kode adalah sebagai berikut:
long t0 = system.nanoTime ();
long count = values.parallelstream (). disortir (). count ();
System.out.println (Count);
long t1 = system.nanoTime ();
long millis = timeunit.nanoseconds.tomillis (t1 - t0);
System.out.println (string.format ("Sortir Paralel mengambil: %d ms", millis));
// Penyortiran paralel membutuhkan waktu: 472 ms
Dua kode di atas hampir sama, tetapi versi paralelnya secepat 50%.
Peta
Seperti yang disebutkan sebelumnya, jenis peta tidak mendukung aliran, tetapi MAP menyediakan beberapa metode baru dan berguna untuk menangani beberapa tugas harian.
Salinan kode adalah sebagai berikut:
Peta <integer, string> peta = hashmap baru <> ();
untuk (int i = 0; i <10; i ++) {
peta.putifabsent (i, "val" + i);
}
peta.foreach ((id, val) -> system.out.println (val));
Kode di atas mudah dimengerti.
Contoh berikut menunjukkan fungsi berguna lainnya di peta:
Salinan kode adalah sebagai berikut:
peta.ComputeIfpresent (3, (num, val) -> val + num);
Map.get (3);
peta.ComputeIfpresent (9, (num, val) -> null);
Map.ContainsKey (9);
peta.ComputeIfabSent (23, num -> "val" + num);
Map.ContainsKey (23);
peta.ComputeIfabSent (3, num -> "bam");
Map.get (3);
Selanjutnya, tunjukkan cara menghapus item di peta yang cocok dengan semua kunci:
Salinan kode adalah sebagai berikut:
peta.remove (3, "val3");
Map.get (3);
Map.Remove (3, "Val33");
Map.get (3);
Metode lain yang berguna:
Salinan kode adalah sebagai berikut:
Map.getordefault (42, "tidak ditemukan");
Juga mudah untuk menggabungkan elemen peta:
Salinan kode adalah sebagai berikut:
peta.merge (9, "val9", (nilai, newValue) -> value.concat (newValue));
Map.get (9);
peta.merge (9, "concat", (nilai, newValue) -> value.concat (newValue));
Map.get (9);
Apa yang digabungkan adalah memasukkan jika nama kunci tidak ada, jika tidak, gabungan nilai yang sesuai dengan kunci asli dan masukkan kembali ke peta.
9. API Tanggal
Java 8 berisi serangkaian API waktu dan tanggal baru di bawah paket java.time. API Tanggal Baru mirip dengan Perpustakaan Joda-Time Open Source, tetapi tidak persis sama.
Jam jam
Kelas jam menyediakan metode untuk mengakses tanggal dan waktu saat ini. Titik waktu tertentu juga dapat diwakili oleh kelas instan, yang juga dapat digunakan untuk membuat objek java.util.telate lama.
Salinan kode adalah sebagai berikut:
Jam clock = clock.systemdefaultzone ();
long millis = clock.millis ();
Instan instan = clock.instant ();
Tanggal legacydate = date.dari (instan); // warisan java.util.date
Zona waktu waktu
Di API baru, zona waktu diwakili oleh ZoneID. Zona waktu dapat dengan mudah diperoleh dengan menggunakan metode statis. Zona waktu mendefinisikan perbedaan waktu ke waktu UTS, yang sangat penting ketika mengonversi antara objek titik waktu instan dan objek tanggal lokal.
Salinan kode adalah sebagai berikut:
System.out.println (zonaid.getavailablezoneids ());
// mencetak semua ID zona waktu yang tersedia
Zonaid zona1 = zonaid.of ("Eropa/Berlin");
Zonaid zona2 = zoneid.of ("Brasil/East");
System.out.println (zona1.getrules ());
System.out.println (zona2.getrules ());
// zonerules [currentstandardoffset =+01: 00]
// Zonerules [CurrentStandardOffset = -03: 00]
Waktu setempat waktu
Localtime mendefinisikan waktu tanpa informasi zona waktu, seperti jam 10 malam, atau 17:30:15. Contoh berikut menciptakan dua waktu lokal menggunakan zona waktu yang dibuat oleh kode sebelumnya. Waktu kemudian dibandingkan dan perbedaan waktu antara dua kali dihitung dalam jam dan menit:
Salinan kode adalah sebagai berikut:
Localtime now1 = localtime.now (zona1);
Localtime now2 = localtime.now (zona2);
System.out.println (Now1.isbefore (Now2));
jam kerja panjang antara = chronounit.hours.between (Now1, Now2);
menit panjang di antara = chronounit.minutes.between (sekarang1, sekarang2);
System.out.println (jam antara);
System.out.println (Minutesbetween);
LocalTime menyediakan berbagai metode pabrik untuk menyederhanakan pembuatan objek, termasuk string waktu penguraian.
Salinan kode adalah sebagai berikut:
Localtime Late = LocalTime.OF (23, 59, 59);
System.out.println (terlambat);
Datetimeformatter GermanFormatter =
Datetimeformatter
.oflocalizedtime (formatstyle.short)
.withlocale (locale.german);
Localtime leettime = localtime.parse ("13:37", GermanFormatter);
System.out.println (leettime);
Tanggal Lokal Lokas
LocalDate mewakili tanggal pasti, seperti 2014-03-11. Nilai objek ini tidak dapat diubah dan pada dasarnya sama dengan nilai waktu. Contoh berikut menunjukkan cara menambah/bulan/tahun ke objek tanggal. Perhatikan juga bahwa objek -objek ini tidak dapat diubah, dan operasi mengembalikan instance baru.
Salinan kode adalah sebagai berikut:
LocalDate hari ini = localdate.now ();
LocalDate Tomorrow = Today.plus (1, chroneunit.days);
LocalDate kemarin = Tomorrow.minusdays (2);
Localdate independenceday = localdate.of (2014, bulan. Juli, 4);
Dayofweek dayofweek = independenceday.getdayofweek ();
System.out.println (dayofweek);
Menguras tipe lokal dari string sesederhana parsing localtime:
Salinan kode adalah sebagai berikut:
Datetimeformatter GermanFormatter =
Datetimeformatter
.oflocalizedDate (formatstyle.medium)
.withlocale (locale.german);
Localdate xmas = localdate.parse ("24.12.2014", GermanFormatter);
System.out.println (xmas); // 2014-12-24
LocalDateTime Datetime Lokal
LocalDateTime mewakili waktu dan tanggal, yang setara dengan penggabungan isi dua bagian pertama menjadi satu objek. LocalDateTime, seperti Localtime dan LocalDate, keduanya tidak berubah. LocalDateTime menyediakan beberapa metode untuk mengakses bidang tertentu.
Salinan kode adalah sebagai berikut:
LocalDateTime sylvester = localDateTime.of (2014, bulan. Desember, 31, 23, 59, 59);
Dayofweek dayofweek = sylvester.getdayofweek ();
System.out.println (DayOfWeek);
Bulan bulan = sylvester.getmonth ();
System.out.println (bulan);
Minuteofday panjang = sylvester.getlong (chronofield.minute_of_day);
System.out.println (MinuteOfday);
Cukup lampirkan informasi zona waktu dan dapat dikonversi menjadi objek instan titik waktu.
Salinan kode adalah sebagai berikut:
Instan Instan = Sylvester
.atzone (zonaid.systemdefault ())
.toinstant ();
Tanggal legacydate = date.dari (instan);
System.out.println (LegacyDate);
Memformat LocalDateTime sama dengan waktu dan tanggal pemformatan.
Salinan kode adalah sebagai berikut:
DateTimeFormatter Formatter =
Datetimeformatter
.ofpattern ("mmm dd, yyyy - hh: mm");
LocalDateTime parsed = localDatetime.parse ("Nov 03, 2014 - 07:13", formatter);
String string = formatter.format (parsed);
System.out.println (String); // Nov 03, 2014 - 07:13
Tidak seperti java.text.numberformat, versi baru dari Datetimef diimable, jadi ini aman.
Informasi terperinci tentang format waktu dan tanggal: http://download.java.net/jdk8/docs/api/java/time/format/dateTimeformatter.html
10. Catatan Anotasi
Beberapa anotasi didukung di Java 8. Mari pertama -tama lihat contoh untuk memahami apa artinya.
Pertama, tentukan anotasi petunjuk yang dikemas untuk menempatkan serangkaian anotasi petunjuk tertentu:
Salinan kode adalah sebagai berikut:
@Interface mengisyaratkan {
Nilai Petunjuk [] ();
}
@Repeatable (hints.class)
@Interface mengisyaratkan {
Nilai string ();
}
Java 8 memungkinkan kita untuk menggunakan anotasi dari tipe yang sama beberapa kali, cukup beri label anotasi @RePeatable.
Contoh 1: Gunakan kelas pembungkus sebagai wadah untuk menyimpan beberapa anotasi (metode lama)
Salinan kode adalah sebagai berikut:
@Hints ({ @hint ("hint1"), @hint ("hint2")})
Class Person {}
Contoh 2: Menggunakan beberapa anotasi (metode baru)
Salinan kode adalah sebagai berikut:
@Hint ("Hint1")
@Hint ("Hint2")
Class Person {}
Dalam contoh kedua, kompiler Java akan secara implisit mendefinisikan anotasi @Hints untuk Anda.
Salinan kode adalah sebagai berikut:
Petunjuk Petunjuk = person.class.getAnnotation (hint.class);
System.out.println (petunjuk);
Petunjuk Petunjuk1 = Person.class.getAnnotation (Hints.class);
System.out.println (hints1.value (). Panjang);
Hint [] hints2 = person.class.getAnnotationsByType (hint.class);
System.out.println (hints2.length);
Bahkan jika kita tidak mendefinisikan anotasi @Hints pada kelas orang, kita masih bisa mendapatkan anotasi @Hints melalui getAnnotation (hints.class).
Selain itu, anotasi Java 8 telah ditambahkan ke dua target baru:
Salinan kode adalah sebagai berikut:
@Target ({elementType.type_parameter, elementType.type_use})
@Interface myannotation {}
Itu semua tentang fitur baru Java 8, dan pasti ada lebih banyak fitur yang menunggu untuk ditemukan. Ada banyak hal berguna di JDK 1.8, seperti arrays.parallelsort, Stampedlock dan FulsibleFuture.