JavaRush /Java blogi /Random-UZ /Java 8 da standart usullar: ular nima qila oladi va nima ...
Spitfire
Daraja

Java 8 da standart usullar: ular nima qila oladi va nima qila olmaydi?

Guruhda nashr etilgan
Piter Verxas tomonidan 2014 yil aprelda yozilgan maqolaning tarjimasi . Java 8 da standart usullar: ular nima qila oladi va nima qila olmaydi?  - 1Tarjimondan: " standart usul " atamasi Java-da hozirgina paydo bo'ldi va men uning rus tiliga o'rnatilgan tarjimasi bor-yo'qligiga ishonchim komil emas. Men "standart usul" atamasini ishlataman, garchi bu ideal deb o'ylamayman. Men sizni yanada muvaffaqiyatli tarjimani muhokama qilishga taklif qilaman.

Standart usul nima

Endi, Java 8-ning chiqarilishi bilan siz interfeyslarga yangi usullarni qo'shishingiz mumkin, shunda interfeys uni amalga oshiradigan sinflarga mos keladi. Agar siz Kievdan Nyu-Yorkgacha bo'lgan ko'plab dasturchilar tomonidan foydalaniladigan kutubxonani ishlab chiqayotgan bo'lsangiz, bu juda muhim. Java 8-dan oldin, agar siz kutubxonada interfeysni aniqlagan bo'lsangiz, interfeysingiz bilan ishlaydigan ba'zi ilovalar yangilanganda ishdan chiqishi xavfisiz unga usullar qo'sha olmaysiz. Xo'sh, Java 8 da endi bundan qo'rqolmaysizmi? Mumkin emas. Interfeysga standart usulni qo'shish ba'zi sinflarni yaroqsiz holga keltirishi mumkin. Keling, avvalo standart usullarning yaxshi tomonlarini ko'rib chiqaylik. Java 8 da usul to'g'ridan-to'g'ri interfeysda amalga oshirilishi mumkin. (Interfeysdagi statik usullar endi amalga oshirilishi mumkin, lekin bu boshqa gap.) Interfeysda amalga oshirilgan usul standart usul deb ataladi va standart kalit so'zi bilan belgilanadi . Agar sinf interfeysni amalga oshirsa, u interfeysda amalga oshirilgan usullarni amalga oshirishi mumkin, lekin talab qilinmaydi. Sinf standart amalga oshirishni meros qilib oladi. Shuning uchun ular amalga oshiradigan interfeysni o'zgartirganda sinflarni o'zgartirish shart emas.

Ko'p meros?

Agar sinf bir nechta (aytaylik, ikkita) interfeyslarni qo'llasa va ular bir xil standart usulni qo'llasa, ishlar yanada murakkablashadi. Sinf qaysi usulni meros qilib oladi? Javob yo'q. Bunday holda, sinf metodni o'zi amalga oshirishi kerak (to'g'ridan-to'g'ri yoki uni boshqa sinfdan meros qilib olish orqali). Vaziyat o'xshash, agar faqat bitta interfeys standart usulga ega bo'lsa, ikkinchisida esa xuddi shu usul mavhum bo'lsa. Java 8 intizomli bo'lishga va noaniq vaziyatlardan qochishga harakat qiladi. Agar usullar bir nechta interfeysda e'lon qilingan bo'lsa, u holda hech qanday standart dastur sinf tomonidan meros qilib olinmaydi - siz kompilyatsiya xatosini olasiz. Agar sinfingiz allaqachon tuzilgan bo'lsa-da, siz kompilyatsiya xatosiga duch kelmasligingiz mumkin. Java 8 bu borada etarlicha mustahkam emas. Buning sabablari bor, men ularni muhokama qilishni istamayman (masalan: Java versiyasi allaqachon chiqarilgan va muhokama qilish vaqti allaqachon o'tgan va umuman olganda, bu ular uchun joy emas).
  • Aytaylik, sizda ikkita interfeys bor va sinf ikkalasini ham amalga oshiradi.
  • Interfeyslardan biri standart m() usulini amalga oshiradi.
  • Siz barcha interfeyslarni va sinfni kompilyatsiya qilasiz.
  • Siz m() usuliga ega bo'lmagan interfeysni mavhum usul sifatida e'lon qilish orqali o'zgartirasiz.
  • Siz faqat o'zgartirilgan interfeysni tuzasiz.
  • Sinfni boshlang.
Java 8 da standart usullar: ular nima qila oladi va nima qila olmaydi?  - 2Bunday holda, sinf ishlaydi. Siz uni yangilangan interfeyslar bilan kompilyatsiya qila olmaysiz, lekin u eski versiyalar bilan tuzilgan va shuning uchun ishlaydi. Hozir
  • mavhum m() usuli bilan interfeysni o'zgartiring va standart dasturni qo'shing.
  • O'zgartirilgan interfeysni kompilyatsiya qiling.
  • Sinfni ishga tushirish: xato.
Usulning sukut bo'yicha amalga oshirilishini ta'minlaydigan ikkita interfeys mavjud bo'lganda, bu usulni sinfning o'zi (yana o'z-o'zidan yoki boshqa sinfdan meros bo'lib qolgan) amalga oshirmasa, sinfda chaqirib bo'lmaydi. Java 8 da standart usullar: ular nima qila oladi va nima qila olmaydi?  - 3Sinfga mos. Uni o'zgartirilgan interfeys bilan yuklash mumkin. U hatto ikkala interfeysda ham standart dasturga ega bo'lgan usul chaqirilmaguncha ishlashi mumkin.

Misol kod

Java 8 da standart usullar: ular nima qila oladi va nima qila olmaydi?  - 4Yuqoridagilarni ko'rsatish uchun men C.java sinfi uchun test katalogini va I1.java va I2.java fayllaridagi interfeyslar uchun 3 ta kichik katalog yaratdim. Sinov uchun asosiy katalog C.java sinfi uchun manba kodini o'z ichiga oladi. Asosiy katalog interfeyslarning bajarish va kompilyatsiya qilish uchun mos bo'lgan versiyasini o'z ichiga oladi: I1 interfeysida standart usul m(); I2 interfeysi hali hech qanday usullarga ega emas. Sinfda metod bor main, shuning uchun uni sinab ko'rishimiz mumkin. U buyruq qatori argumentlari mavjudligini tekshiradi, shuning uchun biz uni chaqirmasdan yoki chaqirmasdan osongina bajarishimiz mumkin m().
~/github/test$ cat C.java
public class C implements I1, I2 {
  public static void main(String[] args) {
    C c = new C();
    if( args.length == 0 ){
      c.m();
    }
  }
}
~/github/test$ cat base/I1.java
public interface I1 {
  default void m(){
    System.out.println("hello interface 1");
  }
}
~/github/test$ cat base/I2.java
public interface I2 {
}
Siz sinfni buyruq satridan kompilyatsiya qilishingiz va ishga tushirishingiz mumkin.
~/github/test$ javac -cp .:base C.java
~/github/test$ java -cp .:base C
hello interface 1
Mos keladigan katalog I2 interfeysining m() usulini mavhum deb e'lon qiladigan versiyasini, shuningdek, texnik sabablarga ko'ra I1.java ning o'zgartirilmagan nusxasini o'z ichiga oladi.
~/github/test$ cat compatible/I2.java

public interface I2 {
  void m();
}
Bunday to'plamni C sinfini kompilyatsiya qilish uchun ishlatib bo'lmaydi:
~/github/test$ javac -cp .:compatible C.java
C.java:1: error: C is not abstract and does not override abstract method m() in I2
public class C implements I1, I2 {
       ^
1 error
Xato xabari juda aniq. Biroq, bizda avvalgi kompilyatsiyadan C.class bor va agar biz interfeyslarni mos keladigan katalogga kompilyatsiya qilsak, biz hali ham sinfni ishga tushirish uchun ishlatilishi mumkin bo'lgan ikkita interfeysga ega bo'lamiz:
~/github/test$ javac compatible/I*.java
~/github/test$ java -cp .:compatible C
hello interface 1
Uchinchi katalog - wrong- I2 versiyasini o'z ichiga oladi, u ham usulni e'lon qiladi m():
~/github/test$ cat wrong/I2.java
public interface I2 {
  default void m(){
    System.out.println("hello interface 2");
  }
}
Siz kompilyatsiya haqida tashvishlanishingiz shart emas. Usul ikki marta e'lon qilingan bo'lsa ham, sinfdan foydalanish va m() usuli chaqirilguncha ishlashi mumkin. Buning uchun bizga buyruq qatori argumenti kerak:
~/github/test$ javac wrong/*.java
~/github/test$ java -cp .:wrong C
Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: I1.m I2.m
    at C.m(C.java)
    at C.main(C.java:5)
~/github/test$ java -cp .:wrong C x
~/github/test$

Xulosa

Kutubxonangizni Java 8-ga o'tkazsangiz va interfeyslarni standart usullarni o'z ichiga olgan holda o'zgartirsangiz, ehtimol sizda hech qanday muammo bo'lmaydi. Hech bo'lmaganda, Java 8 kutubxonasi ishlab chiquvchilari funksionallikni qo'shishda umid qiladigan narsadir. Kutubxonangizdan foydalanadigan ilovalar uni hali ham Java 7 uchun ishlatmoqda, bu erda standart usullar mavjud emas. Agar bir nechta kutubxonalar birgalikda ishlatilsa, ziddiyat yuzaga kelishi mumkin. Qanday qilib undan qochish kerak? Kutubxonangiz API’sini avvalgidek loyihalashtiring. Standart usullarning imkoniyatlariga tayanib, xotirjam bo'lmang. Ular oxirgi chora hisoblanadi. Boshqa interfeyslar bilan to'qnashmaslik uchun nomlarni diqqat bilan tanlang. Keling, ushbu xususiyatdan foydalangan holda Java uchun rivojlanish qanday rivojlanishini ko'rib chiqaylik.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION