Maqola tarjimasining birinchi qismi Java 8 Xususiyatlari – ULTIMATE Guide . Ikkinchi qism bu erda (havola o'zgarishi mumkin). Tahrirlovchining eslatmasi : Ushbu maqola Java 8 omma uchun mavjud bo'lgan paytda nashr etilgan va barcha ko'rsatkichlar bu haqiqatan ham asosiy versiya ekanligini ko'rsatadi. Bu yerda biz Java 8 bilan oʻynash – Lambdas va parallellik , Java 8 Sana va vaqt API qoʻllanmasi: LocalDateTime va Abstract Class va Java 8 Era interfeysi kabi koʻplab Java Code Geeks qoʻllanmalarini taqdim etdik . Shuningdek, biz boshqa manbalardan o'qilishi kerak bo'lgan 15 ta Java 8 darsliklariga havola qilamiz . Albatta, biz Java 8 ning qorong'u tomoni kabi ba'zi kamchiliklarni ko'rib chiqamiz . Shunday qilib, sizga qulaylik uchun Java 8 ning barcha asosiy xususiyatlarini bir joyda to'plash vaqti keldi. Rohatlaning!
1.Kirish
Shubhasiz, Java 8-ning chiqarilishi Java 5-dan keyingi eng katta voqeadir (juda uzoq vaqt oldin, 2004 yilda chiqarilgan). U Java-ga tilda, kompilyatorda, kutubxonalarda, asboblarda va JVM (Java Virtual Machine) kabi ko'plab yangi xususiyatlarni keltirdi. Ushbu qo'llanmada biz ushbu o'zgarishlarni ko'rib chiqamiz va turli xil foydalanish holatlarini hayotiy misollar bilan ko'rsatamiz. Qo'llanma bir nechta qismlardan iborat bo'lib, ularning har biri platformaning o'ziga xos tomonini ko'rib chiqadi:- Til
- Kompilyator
- Kutubxonalar
- Asboblar
- Ish vaqti muhiti (JVM)
2. Java 8 da yangi funksiyalar
Har holda, Java 8 asosiy versiyadir. Aytishimiz mumkinki, har bir Java dasturchisi izlayotgan xususiyatlarni amalga oshirish juda uzoq davom etdi. Ushbu bo'limda biz ularning ko'pchiligini ko'rib chiqamiz.2.1. Lambdalar va funktsional interfeyslar
Lambdalar (shuningdek, shaxsiy yoki anonim usullar sifatida ham tanilgan) Java 8-ning butun versiyasidagi eng katta va eng kutilgan til o'zgarishidir. Ular bizga funksionallikni metod argumenti sifatida belgilashga (uning atrofida funktsiyani e'lon qilish orqali) yoki kodni ma'lumotlar sifatida ko'rsatishga imkon beradi. : har bir ishlab chiquvchiga tanish bo'lgan tushunchalar . dasturlash _ JVM platformasidagi ko'plab tillarda (Groovy, Scala , ...) birinchi kundan boshlab lambdalar mavjud edi, ammo Java ishlab chiquvchilari lambdalarni anonim sinflar orqali ifodalashdan boshqa iloji yo'q edi. Lambdalar dizaynini muhokama qilish jamoatchilikdan ko'p vaqt va kuch talab qildi. Ammo oxir-oqibat murosalar topildi, bu esa yangi ixcham dizaynlarning paydo bo'lishiga olib keldi. Eng oddiy shaklda lambda vergul bilan ajratilgan parametrlar roʻyxati, –> belgisi va tana sifatida koʻrsatilishi mumkin. Masalan:Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) )
E'tibor bering, e argumentining turi kompilyator tomonidan belgilanadi. Bundan tashqari, siz parametrni qavslar ichiga o'rash orqali parametr turini aniq belgilashingiz mumkin. Masalan:
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );
Agar lambda tanasi murakkabroq bo'lsa, uni Java'dagi oddiy funksiya ta'rifiga o'xshash jingalak qavslarga o'rash mumkin. Masalan:
Arrays.asList( "a", "b", "d" ).forEach( e -< {
System.out.print( e );
System.out.print( e );
} );
final
Lambda sinf a'zolariga va mahalliy o'zgaruvchilarga murojaat qilishi mumkin ( maydonga kirish yoki yo'qligidan qat'i nazar, qo'ng'iroqni bevosita samarali qiladi ). Misol uchun, bu 2 parcha ekvivalentdir:
String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
( String e ) -> System.out.print( e + separator ) );
VA:
final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
( String e ) -> System.out.print( e + separator ) );
Lambdalar qiymatni qaytarishi mumkin. Qaytish turi kompilyator tomonidan aniqlanadi. return
Agar lambda tanasi bitta chiziqdan iborat bo'lsa, deklaratsiya talab qilinmaydi. Quyidagi ikkita kod parchasi ekvivalentdir:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
VA:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
int result = e1.compareTo( e2 );
return result;
} );
Tilni ishlab chiquvchilar uzoq vaqt davomida mavjud funktsiyalarni lambda uchun qulay qilish haqida o'ylashdi. Natijada, funktsional interfeys tushunchasi paydo bo'ldi. Funktsional interfeys faqat bitta usulga ega interfeysdir. Natijada, uni bilvosita lambda ifodasiga aylantirish mumkin. java.lang.Runnable
va java.util.concurrent.Callable
funktsional interfeyslarning ikkita ajoyib namunasi. Amalda, funktsional interfeyslar juda nozik: agar kimdir interfeys ta'rifiga hatto bitta boshqa usulni qo'shsa, u endi funksional bo'lmaydi va kompilyatsiya jarayoni tugamaydi. Ushbu mo'rtlikning oldini olish va interfeysning maqsadini funktsional sifatida aniq belgilash uchun Java 8-ga maxsus izoh qo'shildi @FunctionalInterface
(Java kutubxonasidagi barcha mavjud interfeyslar @FunctionalInterface izohini oldi). Keling, funktsional interfeysning oddiy ta'rifini ko'rib chiqaylik:
@FunctionalInterface
public interface Functional {
void method();
}
Bir narsani yodda tutish kerak: standart usullar va statik usullar funktsional interfeys printsipini buzmaydi va e'lon qilinishi mumkin:
@FunctionalInterface
public interface FunctionalDefaultMethods {
void method();
default void defaultMethod() {
}
}
Lambdalar Java 8 ning eng mashhur xususiyatidir. Ular ushbu ajoyib platformaga ko'proq ishlab chiquvchilarni jalb qilish va sof Java-dagi xususiyatlarni aqlli qo'llab-quvvatlash uchun barcha imkoniyatlarga ega. Batafsil ma'lumot uchun rasmiy hujjatlarga qarang .
2.2. Standart interfeyslar va statik usullar
Java 8 interfeyslar ta'rifini ikkita yangi tushuncha bilan kengaytirdi: standart usul va statik usul. Standart usullar interfeyslarni belgilarga biroz o'xshash qiladi, lekin biroz boshqacha maqsadga xizmat qiladi. Ular ushbu interfeyslarning ilgari yozilgan versiyalari uchun orqaga qarab muvofiqlikni buzmasdan mavjud interfeyslarga yangi usullarni qo'shish imkonini beradi. Standart usullar va mavhum usullar o'rtasidagi farq shundaki, mavhum usullar amalga oshirilishi kerak, ammo standart usullar mavjud emas. Buning o'rniga, har bir interfeys standart dastur deb ataladigan narsani ta'minlashi kerak va barcha avlodlar uni sukut bo'yicha qabul qilishadi (agar kerak bo'lsa, ushbu standart dasturni bekor qilish imkoniyati bilan). Keling, quyidagi misolni ko'rib chiqaylik.private interface Defaulable {
// Интерфейсы теперь разрешают методы по умолчанию,
// клиент может реализовывать (переопределять)
// or не реализовывать его
default String notRequired() {
return "Default implementation";
}
}
private static class DefaultableImpl implements Defaulable {
}
private static class OverridableImpl implements Defaulable {
@Override
public String notRequired() {
return "Overridden implementation";
}
}
Interfeys usul ta'rifining bir qismi sifatida kalit so'z yordamida Defaulable
standart usulni e'lon qiladi . Sinflardan biri, , standart usulni qoldirib, ushbu interfeysni amalga oshiradi. Boshqa sinf, , standart amalga oshirishni bekor qiladi va o'zini ta'minlaydi. Java 8-da taqdim etilgan yana bir qiziqarli xususiyat shundaki, interfeyslar statik usullarni e'lon qilishi (va ularni amalga oshirishni taklif qilishi) mumkin. Mana bir misol: notRequired()
default
DefaultableImpl
OverridableImpl
private interface DefaulableFactory {
// Interfaces now allow static methods
static Defaulable create( Supplier<Defaulable> supplier ) {
return supplier.get();
}
}
Kichik kod qismi yuqoridagi misoldagi standart usul va statik usulni birlashtiradi:
public static void main( String[] args ) {
Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );
System.out.println( defaulable.notRequired() );
defaulable = DefaulableFactory.create( OverridableImpl::new );
System.out.println( defaulable.notRequired() );
}
Ushbu dasturning konsol chiqishi quyidagicha ko'rinadi:
Default implementation
Overridden implementation
JVM-da standart usulni amalga oshirish juda samarali va usulni chaqirish bayt-kod ko'rsatmalari bilan qo'llab-quvvatlanadi. Standart usullar mavjud Java interfeyslarini kompilyatsiya jarayonini buzmasdan rivojlantirishga imkon berdi. Yaxshi misollar - interfeysga qo'shilgan ko'plab usullar java.util.Collection
: stream()
, parallelStream()
, forEach()
, removeIf()
, ... Garchi kuchli bo'lsa-da, standart usullardan ehtiyotkorlik bilan foydalanish kerak: standart usulni e'lon qilishdan oldin, bu haqiqatan ham zarurmi yoki yo'qligini ikki marta o'ylab ko'rishingiz kerak, chunki bu sabab bo'lishi mumkin. murakkab ierarxiyalardagi noaniqliklar va xatolarni kompilyatsiya qilish. Batafsil ma'lumot olish uchun hujjatlarga qarang .
2.3. Malumot usullari
Yo'naltiruvchi usullar mavjud usullarga yoki Java sinflari yoki ob'ektlari (namsalari) konstruktorlariga murojaat qilish uchun foydali sintaksisni amalga oshiradi. Lambda iboralari bilan birgalikda mos yozuvlar usullari til konstruksiyalarini ixcham va ixcham qilib, uni shablonga asoslangan qiladi. Quyida turli metod ta'riflariga misol sifatida sinf berilganCar
, keling, mos yozuvlar usullarining to'rtta qo'llab-quvvatlanadigan turini ajratib ko'rsatamiz:
public static class Car {
public static Car create( final Supplier<Car> supplier ) {
return supplier.get();
}
public static void collide( final Car car ) {
System.out.println( "Collided " + car.toString() );
}
public void follow( final Car another ) {
System.out.println( "Following the " + another.toString() );
}
public void repair() {
System.out.println( "Repaired " + this.toString() );
}
}
Birinchi mos yozuvlar usuli sintaksisi bo'lgan konstruktorga havola Class::new
yoki generiklar uchun muqobildir Class< T >::new
. E'tibor bering, konstruktorda argumentlar yo'q.
final Car car = Car.create( Car::new );
final List<Car> cars = Arrays.asList( car );
Ikkinchi variant - sintaksis bilan statik usulga havola Class::static_method
. E'tibor bering, usul aniq bir turdagi parametrni oladi Car
.
cars.forEach( Car::collide );
Uchinchi tur - sintaksis bilan ma'lum turdagi ixtiyoriy ob'ektning namunasi usuliga havola Class::method
. Usul tomonidan hech qanday argumentlar qabul qilinmasligini unutmang.
cars.forEach( Car::repair );
Va oxirgi, to'rtinchi tur - sintaksis bilan ma'lum bir sinf misolining usuliga havola instance::method
. E'tibor bering, usul faqat bitta turdagi parametrni qabul qiladi Car
.
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
Ushbu misollarning barchasini Java dasturlari sifatida ishga tushirish quyidagi konsol natijasini beradi (sinf ma'lumotnomasi Car
farq qilishi mumkin):
Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Repaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Following the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Batafsil ma'lumot va mos yozuvlar usullari haqida batafsil ma'lumot olish uchun rasmiy hujjatlarga qarang .
2.4. Ikki nusxadagi izohlar
Java 5 izohlarni qo'llab-quvvatlashni joriy qilganligi sababli , bu xususiyat juda mashhur va juda keng qo'llaniladi. Biroq, annotatsiyalardan foydalanishdagi cheklovlardan biri shundaki, bir xil izohni bir joyda bir necha marta e'lon qilish mumkin emas. Java 8 bu qoidani buzadi va takroriy izohlarni kiritadi. Bu bir xil izohlarni ular e'lon qilingan joyda bir necha marta takrorlash imkonini beradi. Takroriy izohlar izoh yordamida o'zini izohlashi kerak@Repeatable
. Aslida, bu tilning o'zgarishi emas, balki kompilyatorning hiyla-nayrangidir, ammo texnika bir xil bo'lib qoladi. Keling, oddiy misolni ko'rib chiqaylik:
package com.javacodegeeks.java8.repeatable.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class RepeatingAnnotations {
@Target( ElementType.TYPE )
@Retention( RetentionPolicy.RUNTIME )
public @interface Filters {
Filter[] value();
}
@Target( ElementType.TYPE )
@Retention( RetentionPolicy.RUNTIME )
@Repeatable( Filters.class )
public @interface Filter {
String value();
};
@Filter( "filter1" )
@Filter( "filter2" )
public interface Filterable {
}
public static void main(String[] args) {
for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
System.out.println( filter.value() );
}
}
}
Ko'rib turganimizdek, sinf @Repeatable ( Filtrlar ) Filter
bilan izohlanadi . oddiygina izohlarning egasidir , lekin Java kompilyatori ularning mavjudligini ishlab chiquvchilardan yashirishga harakat qiladi. Shunday qilib, interfeys ikki marta e'lon qilingan izohlarni o'z ichiga oladi (eslatmasiz ). Reflection API shuningdek, ba'zi turdagi takroriy izohlarni qaytarishning yangi usulini taqdim etadi (esda tutingki, Filterable. .getAnnotation( Filtrlar. ) kompilyator tomonidan kiritilgan misolni qaytaradi ). Dasturning chiqishi quyidagicha ko'rinadi: class
Filters
Filter
Filterable
Filter
Filters
getAnnotationsByType()
class
class
Filters
filter1
filter2
Batafsil ma'lumot uchun rasmiy hujjatlarga qarang .
2.5. Yaxshilangan turdagi xulosa
Java 8 kompilyatori ko'plab turdagi xulosalarni yaxshilashga erishdi. Ko'pgina hollarda, aniq turdagi parametrlar kompilyator tomonidan aniqlanishi mumkin va shu bilan kodni tozalaydi. Keling, bitta misolni ko'rib chiqaylik:package com.javacodegeeks.java8.type.inference;
public class Value<T> {
public static<T> T defaultValue() {
return null;
}
public T getOrDefault( T value, T defaultValue ) {
return ( value != null ) ? value : defaultValue;
}
}
Va bu erda type bilan foydalanish Value<String>
:
package com.javacodegeeks.java8.type.inference;
public class TypeInference {
public static void main(String[] args) {
final Value<String> value = new Value<>();
value.getOrDefault( "22", Value.defaultValue() );
}
}
Tur parametri Value.defaultValue()
avtomatik ravishda aniqlanadi va uni aniq ko'rsatish shart emas. Java 7 da bir xil misol kompilyatsiya qilinmaydi va uni <NOBR>Value.<String>defaultValue()</NOBR> sifatida qayta yozish kerak.
2.6. Kengaytirilgan izohni qo'llab-quvvatlash
Java 8 izohlardan foydalanish mumkin bo'lgan kontekstni kengaytiradi. Hozirgi kunda deyarli hamma narsa izohga ega bo'lishi mumkin: mahalliy o'zgaruvchilar, umumiy turlar, superklasslar va amalga oshirilgan interfeyslar, hatto usul istisnolari. Quyida bir nechta misollar keltirilgan:package com.javacodegeeks.java8.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;
public class Annotations {
@Retention( RetentionPolicy.RUNTIME )
@Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )
public @interface NonEmpty {
}
public static class Holder<@NonEmpty T> extends @NonEmpty Object {
public void method() throws @NonEmpty Exception {
}
}
@SuppressWarnings( "unused" )
public static void main(String[] args) {
final Holder<String> holder = new @NonEmpty Holder<String>();
@NonEmpty Collection<@NonEmpty String> strings = new ArrayList<>();
}
}
ElementType.TYPE_USE
va ElementType.TYPE_PARAMETER
tegishli izoh kontekstini tavsiflash uchun ikkita yangi element turi. Annotation Processing API
Java-da yangi izoh turlarini tanib olish uchun kichik o'zgarishlar ham amalga oshirildi.
3. Java kompilyatoridagi yangi funksiyalar
3.1. Parametr nomlari
Vaqt o'tishi bilan Java ishlab chiquvchilari metod parametr nomlarini Java baytekodida saqlashning turli usullarini ixtiro qilishdi, ularni ish vaqtida foydalanish mumkin (masalan, Paranamer kutubxonasi ). Nihoyat, Java 8 ushbu qiyin funktsiyani tilda (Reflection API va usuli yordamidaParameter.getName()
) va baytekodda (yangi kompilyator argumentidan foydalangan holda javac
:) yaratadi –parameters
.
package com.javacodegeeks.java8.parameter.names;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class ParameterNames {
public static void main(String[] args) throws Exception {
Method method = ParameterNames.class.getMethod( "main", String[].class );
for( final Parameter parameter: method.getParameters() ) {
System.out.println( "Parameter: " + parameter.getName() );
}
}
}
Agar siz ushbu sinfni argumentdan foydalanmasdan kompilyatsiya qilsangiz –parameters
va dasturni ishga tushirsangiz, siz shunday narsani ko'rasiz:
Parameter: arg0
Parametr –parameters
kompilyatorga uzatilganda, dastur chiqishi boshqacha bo'ladi (parametrning haqiqiy nomi ko'rsatiladi):
Parameter: args
Ilg'or Maven foydalanuvchilari uchun -parameters argumentini kompilyatsiyaga bo'lim yordamida qo'shish mumkin maven-compiler-plugin
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<compilerArgument>-parameters</compilerArgument>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
Parametr nomlarining mavjudligini tekshirish uchun isNamePresent()
sinf tomonidan taqdim etilgan qulay usul mavjud Parameter
.
4. Yangi Java vositalari
Java 8 yangi buyruq qatori vositalari bilan birga keladi. Ushbu bo'limda biz ulardan eng qiziqarlilarini ko'rib chiqamiz.4.1. Nashorn dvigateli: jjs
jjs - bu buyruq qatoriga asoslangan mustaqil Nashorn dvigatelidir. U JavaScript manba kodi fayllari ro'yxatini oladi va ularni ishga tushiradi. Masalan, quyidagi tarkibga ega func.js faylini yaratamiz :function f() {
return 1;
};
print( f() + 1 );
Ushbu faylni ishga tushirish uchun uni jjs ga argument sifatida topshiramiz :
jjs func.js
Konsol chiqishi quyidagicha bo'ladi:
2
Qo'shimcha ma'lumot olish uchun hujjatlarga qarang .
4.2. Sinfga bog'liqlik tahlilchisi: jdeps
jdeps - bu juda ajoyib buyruq qatori vositasi. U Java sinflari uchun paket yoki sinf darajasidagi bog'liqliklarni ko'rsatadi. U kirish sifatida .class fayl, papka yoki JAR faylni qabul qiladi. Odatiy bo'lib , jdeps bog'liqliklarni standart chiqishga (konsol) chiqaradi. Misol sifatida, keling, mashhur Spring Framework kutubxonasining bog'liqlik hisobotini ko'rib chiqaylik . Misolni qisqa tutish uchun keling, faqat JAR fayliga bog'liqliklarni ko'rib chiqaylikorg.springframework.core-3.0.5.RELEASE.jar
.
jdeps org.springframework.core-3.0.5.RELEASE.jar
Ushbu buyruq juda ko'p natijalar beradi, shuning uchun biz chiqishning faqat bir qismini tahlil qilamiz. Bog'liqlar paketlar bo'yicha guruhlangan. Agar bog'liqliklar bo'lmasa, topilmadi ko'rsatiladi .
org.springframework.core-3.0.5.RELEASE.jar -> C:\Program Files\Java\jdk1.8.0\jre\lib\rt.jar
org.springframework.core (org.springframework.core-3.0.5.RELEASE.jar)
-> java.io
-> java.lang
-> java.lang.annotation
-> java.lang.ref
-> java.lang.reflect
-> java.util
-> java.util.concurrent
-> org.apache.commons.logging not found
-> org.springframework.asm not found
-> org.springframework.asm.commons not found
org.springframework.core.annotation (org.springframework.core-3.0.5.RELEASE.jar)
-> java.lang
-> java.lang.annotation
-> java.lang.reflect
-> java.util
Batafsil ma'lumot uchun rasmiy hujjatlarga qarang .
GO TO FULL VERSION