JavaRush /Java блогу /Random-KY /8ден 13кө чейин: Java версияларына толук сереп салуу. 1-б...
Константин
Деңгээл

8ден 13кө чейин: Java версияларына толук сереп салуу. 1-бөлүк

Группада жарыяланган
Мышыктар, баарына салам)) Ошентип, бүгүн биз 2020-жылыбыз жана Java 14 чыгарууга аз калды. Сиз даяр versionны 17-мартта күтүшүңүз керек, биз ал жерде эмне жаңы жана кызыктуу экенин талдап чыгабыз, бирок бүгүн мен Javaнын мурунку versionларында эс тутумумду жаңырткым келет. Алар бизге эмне жаңылык алып келишти? Келгиле, карап көрөлү. Келгиле, карап чыгууну Java 8ден баштайлы, анткени ал дагы эле актуалдуу жана көпчүлүк долбоорлордо колдонулат. 8ден 13кө чейин: Java versionларына толук сереп салуу.  1-1-бөлүкБуга чейин жаңы versionлар ар бир 3-5 жылда чыгарылчу, бирок жакында Oracle башкача мамилени колго алды - “жаңы Java ар бир алты айда”. Ошентип, алты ай сайын биз функциялардын чыгарылышын көрөбүз. Жакшыбы, жаманбы, аны ар ким ар кандай көрөт. Мисалы, мага бул абдан жаккан жок, анткени жаңы versionларда көптөгөн жаңы функциялар жок, бирок ошол эле учурда versionлар жаандан кийинки козу карындай өсүп жатат. Мен Java 8 менен бир долбоордо бир нече жолу көзүн ирмедим, жана Java 16 мурунтан эле чыгарылган (бирок ал сейрек чыкканда, жаңы функциялар топтолуп, аягында бул окуя майрам сыяктуу көптөн күтүлөт: бардыгы талкуулап жатышат. жаңы жакшылыктар жана сиз анын жанынан өтө албайсыз). Ошентип, баштайлы!

Java 8

Функционалдык интерфейс

Бул эмне? Функционалдык интерфейс – бул бир аткарылбаган (абстрактуу) методду камтыган интерфейс. @FunctionalInterface мындай интерфейстин үстүнө жайгаштырылган кошумча annotation. Функционалдык интерфейстин талаптарына жооп берерин текшерүү үчүн керек (бир гана абстракттуу ыкмасы бар). Бирок, адаттагыдай эле, бизде кээ бир эскертүүлөр бар: демейки жана статикалык методдор бул талаптарга төп келбейт. Ошондуктан, мындай ыкмалар бир нече болушу мүмкүн + бир абстракттуу, жана интерфейс функционалдуу болот. Ал ошондой эле функционалдык интерфейстин аныктамасына таасирин тийгизбеген Object классынын ыкмаларын камтышы мүмкүн. Мен демейки жана статикалык ыкмалар жөнүндө бир нече сөздү кошом:
  1. Демейки модификатору бар методдор интерфейстерге жаңы методдорду кошууга мүмкүндүк берет, алардын учурдагы аткарылышын бузбастан.

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

    Ооба, ооба, биз ишке ашырылган ыкманы интерфейске кошобуз жана бул ыкманы ишке ашырууда сиз аны жокко чыгара албайсыз, бирок аны мурас катары колдонуңуз. Бирок эгер класс берилген метод менен эки интерфейсти ишке ашырса, анда бизде компиляция катасы пайда болот жана ал интерфейстерди ишке ашырып, классты белгилүү окшош метод менен мурастап алса, ата-эне класстын ыкмасы интерфейстин ыкмаларын кайталайт жана өзгөчө кырдаал иштебейт.

  2. Интерфейстеги статикалык методдор класстагы статикалык методдордой эле иштейт. Унутпаңыз: статикалык методдорду тукум куума класстан чакыра албагандай эле, сиз статикалык ыкмаларды мурастай албайсыз.

Ошентип, функционалдык интерфейстер жөнүндө дагы бир нече сөз жана уланталы. Бул жерде FI негизги тизмеси (калганы алардын сорттору болуп саналат):

    Предикат - аргумент катары кандайдыр бир T маанисин алат, логикалык маанини кайтарат.

    Мисал:boolean someMethod(T t);

  • Керектөөчү - T түрүндөгү аргументти алат, эч нерсе кайтарbyte (жараксыз).

    Мисал:void someMethod(T t);

  • Жабдуучу - киргизүү катары эч нерсени кабыл алbyte, бирок T маанисин кайтарат.

    Мисал:T someMethod();

  • Функция - киргизүү катары T түрүндөгү параметрди алат, R түрүндөгү маанини кайтарат.

    Мисал:R someMethod(T t);

  • UnaryOperator - T аргументин алат жана T түрүндөгү маанини кайтарат.

    Мисал:T someMethod(T t);

Агым

Агымдар функционалдык стилде маалымат структураларын иштетүүнүн бир жолу. Эреже катары, бул жыйнактар ​​(бирок сиз аларды башка, азыраак таралган учурларда колдоно аласыз). Түшүнүктүү тил менен айтканда, Stream – бул ар бири үчүн колдонулгандай катаал күч эмес, бир эле учурда бардык маалыматтар менен иштегендей иштеткен маалымат агымы. Келгиле, кичинекей бир мисалды карап көрөлү. Бизде чыпкалоону каалаган (50дөн аз) сандар топтому бар дейли, 5ке көбөйтүп, калгандарынан биринчи 4 санды консолго чыгарабыз. Муну мурда кантип кылмакпыз:
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);

}
Код көп эмес окшойт жана логика бир аз баш аламан. Келгиле, агым менен ал кандай болорун карап көрөлү:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
Агымдар codeдун көлөмүн азайтуу жана аны окууга ыңгайлуу кылуу менен жашоону абдан жөнөкөйлөтөт. Бул теманы кененирээк изилдегиси келгендер үчүн, бул тема боюнча жакшы (жакшы деп айтаар элем) макала .

Ламбда

Балким, эң маанилүү жана көптөн күткөн өзгөчөлүк - бул ламбдалардын пайда болушу. lambda деген эмне? Бул codeдун блогу, аны ар кайсы жерлерге өткөрүүгө болот, андыктан аны кийинчерээк керек болсо көп жолу аткарууга болот. Абдан түшүнүксүз угулат, туурабы? Жөнөкөй сөз менен айтканда, ламбдаларды колдонуу менен, сиз функционалдык интерфейстин ыкмасын (анонимдүү классты ишке ашыруунун бир түрү) ишке ашыра аласыз:
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
Биз run() ыкмасын тез жана керексиз бюрократиясыз ишке ашырдык. Жана ооба: Runnable - бул функционалдык интерфейс. Мен агымдар менен иштегенде ламбдаларды да колдоном (жогоруда агым менен мисалдардагыдай). Биз өтө тереңге барбайбыз, анткени биз бир топ тереңдей алабыз, мен дагы эле жүрөгүн казуучу балдар тереңирээк казышы үчүн бир нече шилтеме калтырам:

ар бирине

Java 8де жаңы foreach бар, ал агым сыяктуу маалымат агымы менен иштейт. Бул жерде бир мисал:
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(someList.stream().foreach(...)га окшош)

Метод шилтемеси

Шилтеме методдору - бул Java класстарынын же an objectтеринин учурдагы ыкмаларына же конструкторлоруна шилтеме жасоо үчүн иштелип чыккан жаңы, пайдалуу синтаксис :: Метод шилтемелери төрт түргө бөлүнөт:
  1. Дизайнерге шилтеме:

    SomeObject obj = SomeObject::new

  2. Статикалык ыкма шилтемеси:

    SomeObject::someStaticMethod

  3. Белгилүү бир типтеги an objectтин статикалык эмес ыкмасына шилтеме:

    SomeObject::someMethod

  4. Белгилүү бир an objectтин кадимки (статикалык эмес) ыкмасына шилтеме

    obj::someMethod

Көбүнчө метод шилтемелери ламбдалардын ордуна агымдарда колдонулат (маалымдама ыкмалары ламбдаларга караганда ылдамыраак, бирок окулушу жагынан төмөн).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
Шилтеме ыкмалары жөнүндө көбүрөөк маалымат алууну каалагандар үчүн:

API убакыты

Даталар жана убакыттар менен иштөө үчүн жаңы китепкана бар - java.time. 8ден 13кө чейин: Java versionларына толук сереп салуу.  1-2-бөлүкЖаңы API ар кандай Joda-Time окшош. Бул API эң маанилүү бөлүмдөрү:
  • LocalDate - белгилүү бир дата, мисалы - 2010-01-09;
  • LocalTime - убакыт алкагын эске алуу менен убакыт - 19:45:55 (LocalDate аналогу);
  • LocalDateTime - айкалыштырылган LocalDate + LocalTime - 2020-01-04 15:37:47;
  • ZoneId - убакыт алHowтарын билдирет;
  • Саат - бул түрүн колдонуу менен учурдагы убакыт жана датага кире аласыз.
Бул жерде бул тема боюнча бир нече кызыктуу макалалар бар:

Кошумча

Бул java.util топтомундагы жаңы класс , баалуулук орогуч, анын амалы нөлдү да камтышы мүмкүн . Кошумча кабыл алуу: Эгерде Optional.ofOptional<String> someOptional = Optional.of("Something"); ичинде null өтсө , биз сүйүктүү NullPointerException алабыз . Мындай учурларда алар төмөнкүлөрдү колдонушат: - бул ыкмада нөлдөн коркпошуңуз керек. Андан кийин, башында бош түзүңүз Кошумча: Анын бош экенин текшерүү үчүн: бизге чындыкты же жалганды кайтарып берет. Мааниси бар болсо, белгилүү бир аракетти аткарыңыз, ал эми маани жок болсо эч нерсе кылбаңыз: Кошумча бош болсо, өткөн маанини кайтаруучу тескери ыкма (резервдик пландын түрү): Сиз абдан, өтө узак убакытка уланта аласыз ( бактыга жараша, Кошумча эки берешен колдору менен ыкмаларды кошту), бирок биз бул жөнүндө токтолбойбуз. Баштоочулар үчүн бир нече шилтеме калтырганым жакшы: 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")); Биз Java 8деги эң белгилүү инновацияларды карап чыктык - бул баары эмес. Көбүрөөк билгиңиз келсе, анда мен муну сизге калтырдым:

Java 9

Ошентип, 2017-жылдын 21-сентябрында дүйнө JDK 9ду көрдү. Бул Java 9 көптөгөн мүмкүнчүлүктөргө ээ. Жаңы тил түшүнүктөрү жок болсо да, жаңы API'лер жана диагностикалык буйруктар иштеп чыгуучуларды кызыктырат. 8ден 13кө чейин: Java versionларына толук сереп салуу.  1-4-бөлүк

JShell (REPL - окуу-баалоо-басып чыгаруу цикли)

Бул интерфейстер, класстар, энумдар, операторлор ж.б. сыяктуу функцияларды текшерүү жана консолдо ар кандай конструкцияларды колдонуу үчүн колдонулган интерактивдүү консолдун Java ишке ашыруусу. JShellди ишке киргизүү үчүн терминалга jshell жазуу керек. Ошондо биз фантазиябыз кандай болсо ошону жаза алабыз: 8ден 13кө чейин: Java versionларына толук сереп салуу.  1-5-бөлүкJShell аркылуу сиз жогорку деңгээлдеги ыкмаларды түзүп, аларды ошол эле сессиянын ичинде колдоно аласыз. Методдор статикалык методдор сыяктуу иштейт, бирок статикалык ачкыч сөздү калтырып коюуга болот.Көбүрөөк Java 9 REPL (JShell) колдонмосунан окуңуз .

Жеке

Java versionсынын 9-versionсынан баштап, интерфейстерде жеке ыкмаларды колдонуу мүмкүнчүлүгүбүз бар (демейки жана статикалык ыкмалар, анткени биз жөн гана жеткorктүүлүктүн жетишсиздигинен башкаларды жокко чыгара албайбыз). private static void someMethod(){} try-with-resources "Ресурстар менен аракет кылуу" өзгөчөлүктөрүн иштетүү жөндөмү өркүндөтүлдү:
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

Модулярдуулук ( Jigsaw )

Модуль - бул жаңы модулдун дескриптор файлы менен байланышкан пакеттердин жана ресурстардын тобу. Бул ыкма codeдун байланышын бошотуу үчүн колдонулат. Бошоң туташтыруу codeдун туруктуулугу жана кеңейтилүүсү үчүн негизги фактор болуп саналат. Модулдуулук ар кандай деңгээлде ишке ашырылат:
  1. Программалоо тor.
  2. Виртуалдык машина.
  3. Стандарттык java API.
JDK 9 92 модуль менен келет: биз аларды колдоно алабыз же өзүбүздүн модулубузду түзө алабыз. Бул жерде тереңирээк карап чыгуу үчүн бир нече шилтемелер:

Immutable Collection

Java 9да коллекцияны бир сап менен түзүүгө жана толтурууга мүмкүн болуп калды, ошол эле учурда аны өзгөрүлгүс кылып (мурда өзгөрүлгүс коллекцияны түзүү үчүн коллекция түзүп, аны маалыматтар менен толтуруп, методду чакырышыбыз керек болчу, мисалы, Collections.unmodifiableList). Мындай жаратуунун мисалы: List someList = List.of("first","second","third");

Башка инновациялар:

  • кеңейтилген Кошумча (жаңы ыкмалар кошулган);
  • иштетүү тутумунун аракеттерин көзөмөлдөө үчүн ProcessHandle жана ProcessHandle интерфейстери пайда болду;
  • G1 - демейки таштанды жыйноочу;
  • HTTP/2 протоколдорун жана WebSocketти колдогон HTTP кардары;
  • кеңейтилген агым;
  • кошулган Reactive Streams API алкагы (реактивдүү программалоо үчүн);
Java 9га толук чөмүлүү үчүн мен сизге окууну сунуштайм:

Java 10

Ошентип, Java 9 чыккандан алты ай өткөндөн кийин, 2018-жылдын март айында (мен кечээгидей эсимде), Java 10 сахнага чыкты. 8ден 13кө чейин: Java versionларына толук сереп салуу.  1-6-бөлүк

var

Эми биз маалымат түрүн беришибиз керек эмес. Биз кабарды var деп белгилейбиз жана компилятор кабардын түрүн оң жактагы инициализатордун түрү боюнча аныктайт. Бул функция инициализатору бар локалдык өзгөрмөлөр үчүн гана жеткorктүү: аны метод аргументтери, кайтаруу түрлөрү ж.б. үчүн колдонууга болбойт, анткени түрүн аныктоо үчүн инициализатор жок. Мисал var (Стринг түрү үчүн):
var message = "Some message…..";
System.out.println(message);
var ачкыч сөз эмес: ал негизинен int сыяктуу сакталган типтин аталышы . Var'дын пайдасы чоң: типтеги декларациялар эч кандай пайда алып келбестен көп көңүл бурат жана бул функция убакытты үнөмдөйт. Бирок, ошол эле учурда, эгер өзгөрмө ыкмалардын узун тизмегинен алынса, code азыраак окула баштайт, анткени ал жерде кандай an object жатканы дароо түшүнүксүз. Бул функция менен көбүрөөк таанышууну каалагандарга арналган:

JIT компилятору (GraalVM)

Андан ары созбостон, javac буйругун иштеткенде, Java тиркемеси Java codeунан JVM byte codeуна түзүлөөрүн эсиңизге сала кетейин, бул тиркеменин бинардык өкүлчүлүгү болуп саналат. Бирок кадимки компьютер процессору JVM byte codeун жөн эле аткара алbyte. JVM программаңыз иштеши үчүн сизге бул byte code үчүн башка компилятор керек, ал процессор мурунтан эле колдоно алган машина codeуна айландырылат. Javac менен салыштырганда, бул компилятор алда канча татаал, бирок ошондой эле жогорку сапаттагы машина codeун чыгарат. Учурда OpenJDK HotSpot виртуалдык машинасын камтыйт, ал өз кезегинде эки негизги JIT компиляторуна ээ. Биринчиси, C1 ( кардар компилятору ), жогорку ылдамдыкта иштөө үчүн иштелип чыккан, бирок codeду оптималдаштыруу жабыркайт. Экинчиси C2 (server компилятору). Аткаруу ылдамдыгы азаят, бирок code көбүрөөк оптималдаштырылган. Кайсысы качан колдонулат? C1 узак JIT тыныгуусу жагымсыз болгон десктоп тиркемелери үчүн эң сонун, ал эми C2 компиляцияга көбүрөөк убакыт сарптоого мүмкүн болгон узакка созулган serverдик программалар үчүн сонун. Көп деңгээлдүү компиляция биринчи жолу компиляция C1 аркылуу өтүп, натыйжа C2 аркылуу өтөт (чоңураак оптималдаштыруу үчүн колдонулат). GraalVM толугу менен HotSpot алмаштыруу үчүн түзүлгөн долбоор болуп саналат. Биз Граалды бир нече окшош долбоорлор деп эсептесек болот: HotSpot үчүн жаңы JIT компилятору жана жаңы полиглоттук виртуалдык машина. Бул JIT компиляторунун өзгөчөлүгү анын Java тorнде жазылганында. Graal компиляторунун артыкчылыгы - коопсуздук, башкача айтканда, каталар эмес, бирок эс тутумдун агып кетиши эмес. Бизде ошондой эле жакшы IDE колдоосу болот жана биз мүчүлүштүктөрдү оңдоочуларды, профилдерди же башка ыңгайлуу куралдарды колдоно алабыз. Кошумчалай кетсек, компилятор HotSpot'тан көз карандысыз болушу мүмкүн жана ал өзүнүн тезирээк JIT-компиляцияланган versionсын түзө алат. казуучулар үчүн:

Параллель G1

G1 таштанды жыйноочу, албетте, сонун, бул жөнүндө эч кандай шек жок, бирок анын алсыз жери да бар: ал бир жиптүү толук GC циклин аткарат. Колдонулбаган an objectилерди табуу үчүн сиз чогулта турган аппараттык каражаттардын бардык күчү керек болгон учурда, биз бир жип менен чектелебиз. Java 10 муну оңдоду. Эми GC биз ага кошкон бардык ресурстар менен иштейт (башкача айтканда, ал көп жиптүү болуп калат). Буга жетишүү үчүн тилди иштеп чыгуучулар GC үчүн жакшы таза интерфейсти түзүп, негизги булактарды GCден изоляциялоону жакшыртышты. Бул сүйкүмдүүлүктүн иштеп чыгуучулары, OpenJDK, жаңы GC түзүүнү мүмкүн болушунча жөнөкөйлөштүрүү үчүн гана эмес, ошондой эле керексиз GCлерди чогулуштан тез өчүрүүгө мүмкүндүк берүү үчүн codeдогу таштандыны атайын тазалоо керек болчу. Ийгorктин негизги критерийлеринин бири - бул бардык жакшыртуулардан кийин иштөө ылдамдыгынын төмөндөшүнүн жоктугу. Ошондой эле карап көрөлү: Башка инновациялар:
  1. Таза таштанды жыйноочу интерфейси киргизилди. Бул ар кандай таштанды жыйноочулардан баштапкы codeдун изоляциясын жакшыртат, бул альтернативдик коллекторлорду тез жана оорутпай бириктирүүгө мүмкүндүк берет;
  2. JDK булактарын бир репозиторийге бириктирүү;
  3. Коллекциялар жаңы ыкманы алышты - copyOf (Collection) , бул коллекциянын өзгөрүлбөс көчүрмөсүн кайтарат;
  4. Кошумча (жана анын варианттарында) .orElseThrow() жаңы ыкмасы бар ;
  5. Мындан ары, JVMs алар Docker контейнеринде иштеп жатканын бorшет жана операциялык системанын өзүнө суроо салбастан, контейнерге тиешелүү конфигурацияны алышат.
Бул жерде Java 10 менен кеңири таанышуу үчүн дагы бир нече материалдар бар: Мурда Javaнын кээ бир versionлары 1.x деп аталып калганы мени аябай чаташтырчу. Мен ачык айткым келет: 9га чейинки Java versionларында жөн гана башка аталыш схемасы болгон. Мисалы, Java 8ди 1.8 , Java 5 - 1.5 ж.б. деп атаса да болот. Эми биз Java 9дан релиздерге өтүү менен аталыш схемасы да өзгөргөнүн жана Java versionлары мындан ары 1.x префикси менен коюлбай калганын көрүп жатабыз. . Бул биринчи бөлүктүн аягы: биз java 8-10 жаңы кызыктуу өзгөчөлүктөрүн карап чыктык. Келгиле, кийинки постто акыркысы менен таанышуубузду уланталы .
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION