JavaRush /Blog Jawa /Random-JV /Fitur Java 8 – Pandhuan Ultimate (Bagian 1)
0xFF
tingkat
Донецк

Fitur Java 8 – Pandhuan Ultimate (Bagian 1)

Diterbitake ing grup
Pérangan pisanan terjemahan artikel Java 8 Features – The ULTIMATE Guide . Bagian kapindho ana ing kene (link bisa diganti). Fitur Java 8 – The Ultimate Guide (Bagian 1) - 1 Cathetan Editor : Artikel iki diterbitake nalika Java 8 kasedhiya kanggo umum lan kabeh indikasi yen iki pancen versi utama. Ing kene kita wis nyedhiyakake pandhuan Java Code Geeks kanthi akeh kayata Playing with Java 8 – Lambdas and Concurrency , Java 8 Date and Time API Guide: LocalDateTime lan Abstract Class vs Interface in the Java 8 Era . Kita uga nyambung menyang 15 tutorial Java 8 sing kudu diwaca saka sumber liyane . Mesthi wae dideleng sawetara kekurangane, kayata Sisih Peteng Jawa 8 . Dadi, wektune kanggo ngumpulake kabeh fitur utama Java 8 ing sak panggonan kanggo penak. Sekeca!

1. Pambuka

Tanpa mangu-mangu, rilis Java 8 minangka acara paling gedhe wiwit Jawa 5 (dirilis cukup suwe, taun 2004). Iku nggawa akeh fitur anyar kanggo Jawa ing basa, compiler, perpustakaan, alat lan JVM (Java Virtual Machine). Ing tutorial iki, kita bakal nliti owah-owahan kasebut lan nduduhake kasus panggunaan sing beda karo conto ing donya nyata. Pandhuan kasebut kalebu sawetara bagean, sing saben-saben nyathet aspek tartamtu saka platform:
  • Basa
  • Compiler
  • Pustaka
  • piranti
  • Lingkungan Runtime (JVM)

2. Fitur anyar ing Jawa 8

Ing kasus apa wae, Java 8 minangka rilis utama. Kita bisa ujar manawa butuh wektu suwe amarga implementasine fitur sing digoleki saben pangembang Java. Ing bagean iki kita bakal nutupi paling akeh.

2.1. Lambdas lan Antarmuka Fungsional

Lambdas (uga dikenal minangka metode pribadi utawa anonim) minangka owah-owahan basa sing paling gedhe lan paling diantisipasi ing kabeh rilis Java 8. Iki ngidini kita nemtokake fungsi minangka argumen metode (kanthi nyatakake fungsi ing sakubenge), utawa nemtokake kode minangka data. : konsep sing dikenal saben pangembang fungsional. pemrograman _ Akeh basa ing platform JVM (Groovy, Scala , ...) duwe lambdas wiwit dina pisanan, nanging pangembang Jawa ora duwe pilihan kajaba makili lambdas liwat kelas anonim. Debat desain lambda njupuk akeh wektu lan gaweyan umum. Nanging pungkasane kompromi ditemokake, sing nyebabake muncule desain ringkes anyar. Ing wangun sing paling gampang, lambda bisa diwakili minangka dhaptar parameter sing dipisahake koma, simbol -> simbol , lan awak. Tuladhane:
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) )
Elinga yen jinis argumen e ditemtokake dening compiler. Kajaba iku, sampeyan bisa kanthi tegas nemtokake jinis parameter kanthi mbungkus parameter kasebut ing kurung. Tuladhane:
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );
Yen awak lambda luwih rumit, bisa dibungkus nganggo kurung kriting, padha karo definisi fungsi biasa ing Jawa. Tuladhane:
Arrays.asList( "a", "b", "d" ).forEach( e -< {
    System.out.print( e );
    System.out.print( e );
} );
A lambda bisa ngrujuk marang anggota kelas lan variabel lokal (implicitly nggawe telpon efektif preduli saka apa finallapangan diakses utawa ora). Contone, 2 cuplikan iki padha karo:
String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
    ( String e ) -> System.out.print( e + separator ) );
LAN:
final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
    ( String e ) -> System.out.print( e + separator ) );
Lambdas bisa ngasilake nilai. Jinis bali bakal ditemtokake dening compiler. Pranyatan returnora dibutuhake yen awak lambda kasusun saka siji baris. Loro cuplikan kode ing ngisor iki padha karo:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
LAN:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
    int result = e1.compareTo( e2 );
    return result;
} );
Pangembang basa wis suwe mikir babagan carane nggawe fungsi sing wis ana sing ramah lambda. Akibaté, konsep antarmuka fungsional muncul. Antarmuka fungsional minangka antarmuka kanthi mung siji cara. Akibaté, bisa diowahi sacara implisit dadi ekspresi lambda. java.lang.Runnablelan java.util.concurrent.Callableloro conto gedhe saka antarmuka fungsi. Ing praktik, antarmuka fungsional banget rapuh: yen ana wong sing nambahake siji cara liyane menyang definisi antarmuka, mula ora bisa digunakake maneh lan proses kompilasi ora bakal rampung. Kanggo ngindhari fragility iki lan kanthi jelas nemtokake maksud antarmuka minangka fungsional, anotasi khusus ditambahake ing Jawa 8 @FunctionalInterface(kabeh antarmuka sing ana ing perpustakaan Jawa nampa anotasi @FunctionalInterface). Ayo goleki definisi prasaja antarmuka fungsional iki:
@FunctionalInterface
public interface Functional {
    void method();
}
Ana siji bab sing kudu dieling-eling: metode standar lan metode statis ora nglanggar prinsip antarmuka fungsional lan bisa diumumake:
@FunctionalInterface
public interface FunctionalDefaultMethods {
    void method();

    default void defaultMethod() {
    }
}
Lambdas minangka fitur sing paling populer ing Jawa 8. Dheweke duwe kabeh potensi kanggo narik luwih akeh pangembang menyang platform sing apik iki lan nyedhiyakake dhukungan cerdas kanggo fitur ing Jawa murni. Kanggo informasi sing luwih rinci, waca dokumentasi resmi .

2.2. Antarmuka Default lan Metode Statis

Java 8 ngembangake definisi antarmuka kanthi rong konsep anyar: metode standar lan metode statis. Cara standar nggawe antarmuka rada padha karo sipat, nanging nduweni tujuan sing rada beda. Iki ngidini sampeyan nambahake cara anyar menyang antarmuka sing wis ana tanpa ngrusak kompatibilitas mundur kanggo versi antarmuka kasebut sing wis ditulis sadurunge. Bedane metode standar lan metode abstrak yaiku metode abstrak kudu dileksanakake nalika metode standar ora. Nanging, saben antarmuka kudu nyedhiyakake implementasine sing diarani standar, lan kabeh turunane bakal nampa kanthi gawan (kanthi kemampuan kanggo ngatasi implementasi standar iki yen perlu). Coba deleng conto ing ngisor iki.
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";
    }
}
Antarmuka Defaulablengumumake metode standar notRequired()nggunakake tembung kunci defaultminangka bagean saka definisi metode. Salah sawijining kelas, DefaultableImpl, ngleksanakake antarmuka iki ninggalake cara standar minangka. kelas liyane, OverridableImpl, overrides implementasine gawan lan menehi dhewe. Fitur menarik liyane sing dikenalake ing Jawa 8 yaiku antarmuka bisa ngumumake (lan nawakake implementasine) metode statis. Iki contone:
private interface DefaulableFactory {
    // Interfaces now allow static methods
    static Defaulable create( Supplier<Defaulable> supplier ) {
        return supplier.get();
    }
}
Sepotong kode cilik nggabungake metode standar lan metode statis saka conto ing ndhuwur:
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() );
}
Output console saka program iki katon kaya iki:
Default implementation
Overridden implementation
Implementasi metode standar ing JVM efisien banget lan invocation metode didhukung dening instruksi bytecode. Cara standar ngidini antarmuka Jawa sing wis ana bisa berkembang tanpa ngrusak proses kompilasi. Conto sing apik yaiku akeh metode sing ditambahake ing antarmuka java.util.Collection: stream(), parallelStream(), forEach(), removeIf(), ... Sanajan kuat, metode standar kudu digunakake kanthi ati-ati: sadurunge nyatakake metode standar, sampeyan kudu mikir kaping pindho apa iki pancene perlu amarga iki bisa nyebabake. kanggo kompilasi ambiguitas lan kesalahan ing hirarki kompleks. Kanggo informasi sing luwih rinci, waca dokumentasi .

2.3. Metode referensi

Metode referensi ngleksanakake sintaksis sing migunani kanggo ngrujuk metode utawa konstruktor kelas utawa obyek Jawa sing wis ana. Bebarengan karo ekspresi lambda, metode referensi nggawe konstruksi basa sing kompak lan ringkes, dadi basis cithakan. Ing ngisor iki kelas Carminangka conto definisi metode sing beda-beda, ayo nyorot papat jinis metode referensi sing didhukung:
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() );
    }
}
Cara referensi pisanan minangka referensi kanggo konstruktor kanthi sintaks Class::newutawa alternatif kanggo generik Class< T >::new. Elinga yen konstruktor ora duwe argumen.
final Car car = Car.create( Car::new );
final List<Car> cars = Arrays.asList( car );
Opsi kapindho yaiku referensi kanggo metode statis kanthi sintaks Class::static_method. Elinga yen cara njupuk persis siji parameter saka jinis Car.
cars.forEach( Car::collide );
Jinis kaping telu minangka referensi kanggo metode instance saka obyek arbitrer saka jinis tartamtu kanthi sintaks Class::method. Elinga yen ora ana argumen sing ditampa kanthi metode kasebut.
cars.forEach( Car::repair );
Lan pungkasan, jinis kaping papat minangka referensi kanggo metode conto kelas tartamtu kanthi sintaks instance::method. Wigati dimangerteni manawa metode kasebut mung nampa siji jinis parameter Car.
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
Nglakokake kabeh conto iki minangka program Java ngasilake output konsol ing ngisor iki (referensi kelas Carbisa beda-beda):
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
Kanggo informasi sing luwih rinci lan rincian cara referensi, waca dokumentasi resmi .

2.4. Anotasi duplikat

Wiwit Java 5 ngenalake dhukungan kanggo anotasi , fitur iki dadi populer lan akeh digunakake. Nanging, salah sawijining watesan nggunakake anotasi yaiku kasunyatan manawa anotasi sing padha ora bisa diumumake luwih saka sepisan ing panggonan sing padha. Java 8 nglanggar aturan iki lan ngenalake anotasi duplikat. Iki ngidini anotasi sing padha bisa diulang kaping pirang-pirang ing lokasi sing diumumake. Anotasi duplikat kudu menehi anotasi kanthi nggunakake anotasi @Repeatable. Ing kasunyatan, iki ora dadi luwih owah-owahan ing basa minangka trick compiler, nalika technique tetep padha. Ayo katon ing conto prasaja:
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() );
        }
    }
}
Kaya sing kita deleng, kelas kasebut Filterdianotasi karo @Repeatable ( Filters. class). Filtersiku mung pemilik saka anotasi Filter, nanging compiler Jawa nyoba kanggo ndhelikake ngarsane saka pangembang. Mangkono, antarmuka Filterablengemot anotasi Filtersing diumumake kaping pindho (tanpa nyebutake Filters). Reflection API uga menehi cara anyar getAnnotationsByType()kanggo bali duplikat anotasi saka sawetara jinis (elinga sing Filterable. class.getAnnotation ( Filter. class) bakal ngasilake conto compiler-nyuntikaken Filters). Output saka program bakal katon kaya iki:
filter1
filter2
Kanggo informasi sing luwih rinci, waca dokumentasi resmi .

2.5. Inferensi jinis apik

Compiler Java 8 wis nampa akeh dandan inferensi jinis. Ing sawetara kasus, paramèter jinis eksplisit bisa ditetepake dening compiler, saéngga nggawe kode luwih resik. Ayo ndeleng siji conto:
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;
    }
}
Lan iki nggunakake jinis 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() );
    }
}
Parameter jinis Value.defaultValue()ditemtokake kanthi otomatis lan ora perlu diwenehake kanthi jelas. Ing Jawa 7, conto sing padha ora bakal dikompilasi lan kudu ditulis maneh minangka <NOBR>Value.<String>defaultValue()</NOBR>.

2.6. Dhukungan anotasi sing ditambahi

Java 8 ngembangake konteks ing ngendi anotasi bisa digunakake. Saiki, meh kabeh bisa duwe anotasi: variabel lokal, jinis umum, superclass lan antarmuka sing diimplementasikake, malah pengecualian metode. Sawetara conto ditampilake ing ngisor iki:
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_USElan ElementType.TYPE_PARAMETERrong jinis unsur anyar kanggo njlèntrèhaké konteks anotasi sing cocog. Annotation Processing APIuga ngalami owah-owahan cilik kanggo ngenali jinis anotasi anyar ing Jawa.

3. Fitur anyar ing compiler Jawa

3.1. Jeneng parameter

Saindhenging wektu, pangembang Jawa wis nemokke macem-macem cara kanggo nyimpen jeneng parameter metode ing bytecode Jawa supaya kasedhiya ing runtime (contone, perpustakaan Paranamer ). Pungkasan, Java 8 nggawe fungsi sing angel iki ing basa (nggunakake Reflection API lan metode Parameter.getName()) lan bytecode (nggunakake argumen kompiler anyar javac:) –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() );
        }
    }
}
Yen sampeyan ngumpulake kelas iki tanpa nggunakake argumen –parameterslan banjur mbukak program, sampeyan bakal weruh kaya iki:
Parameter: arg0
Kanthi parameter –parameterssing diterusake menyang kompiler, output program bakal beda-beda (jeneng parameter sing bener bakal ditampilake):
Parameter: args
Kanggo pangguna Maven sing luwih maju, argumen -parameter bisa ditambahake menyang kompilasi nggunakake bagean 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>
Kanggo mriksa kasedhiyan jeneng parameter ana isNamePresent()cara trep sing diwenehake dening kelas Parameter.

4. Piranti Jawa Anyar

Java 8 dilengkapi piranti baris printah anyar. Ing bagean iki kita bakal katon ing paling menarik saka wong-wong mau.

4.1. Nashorn engine: js

jjs minangka mesin Nashorn mandiri sing adhedhasar baris printah. Butuh dhaptar file kode sumber JavaScript lan mbukak. Contone, ayo nggawe file func.js kanthi isi ing ngisor iki:
function f() {
     return 1;
};

print( f() + 1 );
Kanggo mbukak file iki, ayo ngirim minangka argumen menyang jjs :
jjs func.js
Output konsol bakal kaya iki:
2
Kanggo rincian liyane ndeleng dokumentasi .

4.2. Analyzer Ketergantungan Kelas: jdeps

jdeps minangka alat baris perintah sing apik banget. Iki nuduhake dependensi tingkat paket utawa kelas kanggo kelas Jawa. Iku nampa file .class , folder utawa file JAR minangka input. Kanthi gawan , jdeps ngasilake dependensi menyang output standar (konsol). Minangka conto, ayo ndeleng laporan dependensi saka perpustakaan Spring Framework sing populer . Supaya contone tetep cendhak, ayo goleki dependensi kanggo file JAR mung org.springframework.core-3.0.5.RELEASE.jar.
jdeps org.springframework.core-3.0.5.RELEASE.jar
Printah iki ngasilake cukup akeh, mula kita mung bakal nganalisa bagean saka output kasebut. Dependensi diklompokaké miturut paket. Yen ora ana dependensi, ora ditemokake bakal ditampilake .
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
Kanggo informasi sing luwih rinci, waca dokumentasi resmi .
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION