ส่วนแรกของการแปลบทความคุณสมบัติJava 8 – The ULTIMATE Guide ตอนที่ 2 มาแล้ว (ลิงค์อาจมีการเปลี่ยนแปลง)
หมายเหตุบรรณาธิการ : บทความนี้เผยแพร่ในขณะที่ Java 8 เผยแพร่สู่สาธารณะ และข้อบ่งชี้ทั้งหมดคือนี่เป็นเวอร์ชันหลักจริงๆ ที่นี่เราได้ให้คำแนะนำ Java Code Geeks มากมาย เช่นPlaying with Java 8 – Lambdas and Concurrency , Java 8 Date and Time API Guide: LocalDateTimeและAbstract Class vs. Interface in the Java 8 Era นอกจากนี้เรายังลิงก์ไปยังบทช่วยสอน Java 8 ที่ต้องอ่าน 15 รายการจากแหล่งอื่น แน่นอนว่าเราพิจารณาข้อเสียบางประการ เช่นด้านมืดของ Java 8 ถึงเวลารวบรวมคุณสมบัติหลักทั้งหมดของ Java 8 ไว้ในที่เดียวเพื่อความสะดวกของคุณ สนุก!
1. บทนำ
ไม่ต้องสงสัยเลยว่าการเปิดตัว Java 8ถือเป็นเหตุการณ์ที่ยิ่งใหญ่ที่สุดนับตั้งแต่ Java 5 (เปิดตัวเมื่อนานมาแล้วในปี 2547) มันนำคุณสมบัติใหม่มากมายมาสู่ Java ทั้งในภาษา คอมไพเลอร์ ไลบรารี เครื่องมือ และ JVM (Java Virtual Machine) ในบทช่วยสอนนี้ เราจะดูการเปลี่ยนแปลงเหล่านี้และสาธิตกรณีการใช้งานต่างๆ พร้อมตัวอย่างในชีวิตจริง คู่มือนี้ประกอบด้วยหลายส่วน โดยแต่ละส่วนจะกล่าวถึงแง่มุมเฉพาะของแพลตฟอร์ม:- ภาษา
- คอมไพเลอร์
- ห้องสมุด
- เครื่องมือ
- สภาพแวดล้อมรันไทม์ (JVM)
2. คุณสมบัติใหม่ใน Java 8
ไม่ว่าในกรณีใด Java 8 จะเป็นเวอร์ชันหลัก เราสามารถพูดได้ว่ามันใช้เวลานานมากเนื่องจากการปรับใช้คุณสมบัติที่นักพัฒนา Java ทุกคนกำลังมองหา ในส่วนนี้เราจะครอบคลุมส่วนใหญ่2.1. Lambdas และอินเทอร์เฟซเชิงฟังก์ชัน
Lambdas (หรือที่รู้จักกันในชื่อวิธีการส่วนตัวหรือแบบไม่ระบุชื่อ) คือการเปลี่ยนแปลงภาษาที่ใหญ่ที่สุดและเป็นที่คาดหวังมากที่สุดใน Java 8 ทั้งหมด ซึ่งช่วยให้เราระบุฟังก์ชันการทำงานเป็นอาร์กิวเมนต์ของ method ได้ (โดยการประกาศฟังก์ชันที่อยู่รอบๆ) หรือระบุโค้ดเป็นข้อมูล : แนวคิดที่นักพัฒนาฟังก์ชั่นทุกคนคุ้นเคย การเขียนโปรแกรม _ หลายภาษาบนแพลตฟอร์ม JVM (Groovy, Scala , ... ) มี lambdas ตั้งแต่วันแรก แต่นักพัฒนา Java ไม่มีทางเลือกอื่นนอกจากต้องเป็นตัวแทนของ lambdas ผ่านคลาสที่ไม่ระบุชื่อ การถกเถียงเรื่องการออกแบบแลมบ์ดาใช้เวลาและความพยายามอย่างมากต่อสาธารณชน แต่ในที่สุดก็พบการประนีประนอมซึ่งนำไปสู่การเกิดการออกแบบที่กระชับใหม่ ในรูปแบบที่ง่ายที่สุด แลมบ์ดาสามารถแสดงเป็นรายการพารามิเตอร์ที่คั่นด้วยเครื่องหมายจุลภาค สัญลักษณ์ –>และเนื้อหา ตัวอย่างเช่น:Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) )
โปรดทราบว่าประเภทของอาร์กิวเมนต์eถูกกำหนดโดยคอมไพเลอร์ นอกจากนี้ คุณยังระบุประเภทของพารามิเตอร์ได้อย่างชัดเจนโดยใส่พารามิเตอร์ไว้ในวงเล็บ ตัวอย่างเช่น:
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );
ในกรณีที่ตัวแลมบ์ดามีความซับซ้อนมากขึ้น ก็สามารถใช้วงเล็บปีกกาได้ คล้ายกับคำจำกัดความฟังก์ชันทั่วไปใน Java ตัวอย่างเช่น:
Arrays.asList( "a", "b", "d" ).forEach( e -< {
System.out.print( e );
System.out.print( e );
} );
แลมบ์ดาสามารถอ้างถึงสมาชิกคลาสและตัวแปรท้องถิ่น (โดยปริยายทำให้การโทรมีผลไม่ว่าfinal
ฟิลด์นั้นจะเข้าถึงหรือไม่ก็ตาม) ตัวอย่างเช่น ข้อมูลโค้ด 2 รายการนี้เทียบเท่ากัน:
String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
( String e ) -> System.out.print( e + separator ) );
และ:
final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
( String e ) -> System.out.print( e + separator ) );
Lambdas สามารถคืนค่าได้ ประเภทการส่งคืนจะถูกกำหนดโดยคอมไพเลอร์ ไม่จำเป็นต้องมี การประกาศreturn
หากเนื้อความของแลมบ์ดาประกอบด้วยบรรทัดเดียว ข้อมูลโค้ดทั้งสองด้านล่างนี้เทียบเท่ากัน:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
และ:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
int result = e1.compareTo( e2 );
return result;
} );
นักพัฒนาภาษาคิดมานานแล้วว่าจะทำให้ฟังก์ชันที่มีอยู่เป็นมิตรกับแลมบ์ดาได้อย่างไร เป็นผลให้แนวคิดของอินเทอร์เฟซการทำงานเกิดขึ้น อินเทอร์เฟซการทำงานคืออินเทอร์เฟซที่มีวิธีเดียวเท่านั้น ด้วยเหตุนี้จึงสามารถแปลงเป็นนิพจน์แลมบ์ดาโดยปริยายได้ java.lang.Runnable
และjava.util.concurrent.Callable
สองตัวอย่างที่ดีของอินเทอร์เฟซการทำงาน ในทางปฏิบัติ อินเทอร์เฟซการทำงานมีความเปราะบางมาก หากมีใครเพิ่มวิธีอื่นแม้แต่วิธีเดียวในการกำหนดอินเทอร์เฟซ ก็จะใช้งานไม่ได้อีกต่อไป และกระบวนการคอมไพล์จะไม่สมบูรณ์ เพื่อหลีกเลี่ยงความเปราะบางนี้และกำหนดจุดประสงค์ของอินเทอร์เฟซอย่างชัดเจนว่าใช้งานได้ จึงได้เพิ่มคำอธิบายประกอบพิเศษใน Java 8 @FunctionalInterface
(อินเทอร์เฟซที่มีอยู่ทั้งหมดในไลบรารี Java ได้รับคำอธิบายประกอบ @FunctionalInterface) ลองดูคำจำกัดความง่ายๆ ของอินเทอร์เฟซการทำงาน:
@FunctionalInterface
public interface Functional {
void method();
}
มีสิ่งหนึ่งที่ต้องจำไว้: วิธีการเริ่มต้นและวิธีการแบบคงที่ไม่ละเมิดหลักการของอินเทอร์เฟซการทำงานและสามารถประกาศได้:
@FunctionalInterface
public interface FunctionalDefaultMethods {
void method();
default void defaultMethod() {
}
}
Lambdas เป็นคุณสมบัติที่ได้รับความนิยมมากที่สุดของ Java 8 พวกเขามีศักยภาพทั้งหมดในการดึงดูดนักพัฒนาให้มาที่แพลตฟอร์มที่ยอดเยี่ยมนี้มากขึ้น และให้การสนับสนุนอย่างชาญฉลาดสำหรับคุณสมบัติต่างๆ ใน Java ล้วนๆ สำหรับข้อมูลโดยละเอียดเพิ่มเติม โปรดดูเอกสารอย่างเป็นทางการ
2.2. อินเทอร์เฟซเริ่มต้นและวิธีการแบบคงที่
Java 8 ขยายคำจำกัดความของอินเทอร์เฟซด้วยสองแนวคิดใหม่: วิธีการเริ่มต้นและวิธีคงที่ วิธีการเริ่มต้นทำให้อินเทอร์เฟซค่อนข้างคล้ายกับลักษณะ แต่มีจุดประสงค์ที่แตกต่างกันเล็กน้อย ช่วยให้คุณสามารถเพิ่มวิธีการใหม่ให้กับอินเทอร์เฟซที่มีอยู่ได้โดยไม่ทำลายความเข้ากันได้แบบย้อนหลังสำหรับอินเทอร์เฟซเวอร์ชันที่เขียนไว้ก่อนหน้านี้ ความแตกต่างระหว่างวิธีเริ่มต้นและวิธีนามธรรมคือต้องใช้วิธีนามธรรมในขณะที่วิธีเริ่มต้นไม่ได้เป็นเช่นนั้น แต่ละอินเทอร์เฟซจะต้องจัดเตรียมสิ่งที่เรียกว่าการใช้งานเริ่มต้นแทน และผู้สืบทอดทั้งหมดจะได้รับตามค่าเริ่มต้น (โดยมีความสามารถในการแทนที่การใช้งานเริ่มต้นนี้ หากจำเป็น) ลองดูตัวอย่างด้านล่าง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";
}
}
อินเทอร์เฟซDefaulable
ประกาศวิธีการเริ่มต้นnotRequired()
โดยใช้คำสำคัญdefault
เป็นส่วนหนึ่งของคำจำกัดความของวิธีการ หนึ่งในคลาส , DefaultableImpl
ใช้อินเทอร์เฟซนี้โดยปล่อยให้วิธีการเริ่มต้นเหมือนเดิม คลาสอื่น , OverridableImpl
แทนที่การใช้งานเริ่มต้นและจัดเตรียมคลาสของตัวเอง คุณสมบัติที่น่าสนใจอีกประการหนึ่งที่นำมาใช้ใน Java 8 ก็คืออินเทอร์เฟซสามารถประกาศ (และเสนอการใช้งาน) วิธีการคงที่ได้ นี่คือตัวอย่าง:
private interface DefaulableFactory {
// Interfaces now allow static methods
static Defaulable create( Supplier<Defaulable> supplier ) {
return supplier.get();
}
}
โค้ดชิ้นเล็กๆ รวมวิธีการเริ่มต้นและวิธีการแบบคงที่จากตัวอย่างด้านบน:
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() );
}
ผลลัพธ์คอนโซลของโปรแกรมนี้มีลักษณะดังนี้:
Default implementation
Overridden implementation
การใช้วิธีการเริ่มต้นใน JVM นั้นมีประสิทธิภาพมาก และการเรียกใช้เมธอดได้รับการสนับสนุนโดยคำสั่ง bytecode วิธีการเริ่มต้นอนุญาตให้อินเทอร์เฟซ Java ที่มีอยู่พัฒนาโดยไม่ทำลายกระบวนการคอมไพล์ ตัวอย่างที่ดีคือวิธีการต่างๆ มากมายที่เพิ่มเข้าไปในอินเทอร์เฟซjava.util.Collection
: stream()
, parallelStream()
, forEach()
, removeIf()
, ... แม้ว่าจะมีประสิทธิภาพ แต่วิธีการเริ่มต้นควรใช้ด้วยความระมัดระวัง ก่อนที่จะประกาศวิธีการเริ่มต้น คุณควรคิดให้รอบคอบก่อนว่าสิ่งนี้จำเป็นจริงๆ หรือไม่ เนื่องจากสิ่งนี้สามารถนำไปสู่ เพื่อรวบรวมความคลุมเครือและข้อผิดพลาดในลำดับชั้นที่ซับซ้อน สำหรับข้อมูลโดยละเอียดเพิ่มเติม โปรดดูที่เอกสารประกอบ
2.3. วิธีการอ้างอิง
วิธีการอ้างอิงใช้ไวยากรณ์ที่มีประโยชน์เพื่ออ้างอิงวิธีการที่มีอยู่หรือตัวสร้างของคลาสหรืออ็อบเจ็กต์ Java (อินสแตนซ์) เมื่อใช้ร่วมกับนิพจน์แลมบ์ดา วิธีการอ้างอิงจะทำให้โครงสร้างภาษามีขนาดกะทัดรัดและกระชับ ทำให้เป็นแบบตามเทมเพลต ด้านล่างนี้คือคลาสCar
ที่เป็นตัวอย่างของคำจำกัดความของวิธีการต่างๆ เรามาเน้นวิธีการอ้างอิงสี่ประเภทที่รองรับ:
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() );
}
}
วิธีอ้างอิงวิธีแรกคือการอ้างอิงถึงตัวสร้างที่มีไวยากรณ์หรือClass::new
ทางเลือกอื่นสำหรับยาชื่อสามัญ Class< T >::new
โปรดทราบว่าตัวสร้างไม่มีข้อโต้แย้ง
final Car car = Car.create( Car::new );
final List<Car> cars = Arrays.asList( car );
Class::static_method
ตัวเลือกที่สองคือการอ้างอิงถึงวิธีการแบบสแต ติก ที่มีไวยากรณ์ โปรดทราบว่าวิธีการนี้รับพารามิเตอร์ประเภทเดียวCar
เท่านั้น
cars.forEach( Car::collide );
ประเภทที่สามคือการอ้างอิงถึงวิธีการของอินสแตนซ์ของวัตถุที่กำหนดเองในประเภทใดประเภทหนึ่งที่มีClass::method
ไวยากรณ์ โปรดทราบว่าวิธีการนี้ไม่ยอมรับข้อโต้แย้ง
cars.forEach( Car::repair );
และประเภทสุดท้ายที่สี่คือการอ้างอิงถึงวิธีการของอินสแตนซ์ของคลาสเฉพาะที่มีinstance::method
ไวยากรณ์ Car
โปรดทราบว่าวิธีการ นี้ ยอมรับพารามิเตอร์ประเภทเดียวเท่านั้น
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
การรันตัวอย่างทั้งหมดเหล่านี้ในขณะที่โปรแกรม Java สร้างเอาต์พุตคอนโซลต่อไปนี้ (การอ้างอิงคลาสCar
อาจแตกต่างกัน):
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
สำหรับข้อมูลโดยละเอียดเพิ่มเติมและรายละเอียดเกี่ยวกับวิธีการอ้างอิง โปรด ดูเอกสารอย่างเป็นทางการ
2.4. คำอธิบายประกอบที่ซ้ำกัน
เนื่องจาก Java 5 เปิดตัวการรองรับคำอธิบายประกอบคุณลักษณะนี้จึงได้รับความนิยมอย่างมากและใช้กันอย่างแพร่หลาย อย่างไรก็ตาม ข้อจำกัดประการหนึ่งของการใช้คำอธิบายประกอบคือข้อเท็จจริงที่ว่าคำอธิบายประกอบเดียวกันไม่สามารถประกาศมากกว่าหนึ่งครั้งในที่เดียวกันได้ Java 8 ฝ่าฝืนกฎนี้และแนะนำคำอธิบายประกอบที่ซ้ำกัน ซึ่งช่วยให้สามารถทำซ้ำคำอธิบายประกอบเดียวกันได้หลายครั้งในตำแหน่งที่ประกาศไว้ คำอธิบายประกอบที่ซ้ำกันควรใส่คำอธิบายประกอบด้วยตนเองโดยใช้คำอธิบาย@Repeatable
ประกอบ อันที่จริง นี่ไม่ใช่การเปลี่ยนแปลงภาษามากนักเนื่องจากเป็นเคล็ดลับของคอมไพเลอร์ ในขณะที่เทคนิคยังคงเหมือนเดิม ลองดูตัวอย่างง่ายๆ:
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() );
}
}
}
ดังที่เราเห็นแล้วว่าคลาสนั้นFilter
ถูกใส่คำอธิบายประกอบด้วย @Repeatable( Filters. class
) Filters
เป็นเพียงเจ้าของคำอธิบายประกอบFilter
แต่คอมไพเลอร์ Java พยายามซ่อนการแสดงตนจากนักพัฒนา ดังนั้นอินเทอร์เฟซจึงFilterable
มีคำอธิบายประกอบFilter
ที่ถูกประกาศสองครั้ง (โดยไม่กล่าวถึงFilters
) Reflection API ยังมีวิธีการใหม่getAnnotationsByType()
ในการส่งคืนคำอธิบายประกอบที่ซ้ำกันบางประเภท (โปรดจำไว้ว่า Filterable. class
.getAnnotation( Filters. class
) จะส่งคืนอินสแตนซ์ที่คอมไพเลอร์ฉีดFilters
) ผลลัพธ์ของโปรแกรมจะมีลักษณะดังนี้:
filter1
filter2
สำหรับข้อมูลโดยละเอียดเพิ่มเติม โปรดดูเอกสารอย่างเป็นทางการ
2.5. ปรับปรุงการอนุมานประเภท
คอมไพเลอร์ Java 8 ได้รับการปรับปรุงการอนุมานหลายประเภท ในหลายกรณี คอมไพลเลอร์สามารถกำหนดพารามิเตอร์ประเภทที่ชัดเจนได้ ดังนั้นจึงทำให้โค้ดสะอาดขึ้น ลองดูตัวอย่างหนึ่ง: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;
}
}
และนี่คือการใช้งานกับ type 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() );
}
}
พารามิเตอร์ type Value.defaultValue()
ถูกกำหนดโดยอัตโนมัติ และไม่จำเป็นต้องระบุอย่างชัดเจน ใน Java 7 ตัวอย่างเดียวกันนี้จะไม่คอมไพล์และจะต้องเขียนใหม่เป็น <NOBR>Value.<String>defaultValue()</NOBR>
2.6. การสนับสนุนคำอธิบายประกอบแบบขยาย
Java 8 ขยายบริบทที่สามารถใช้คำอธิบายประกอบได้ ทุกวันนี้ เกือบทุกอย่างสามารถมีคำอธิบายประกอบได้: ตัวแปรท้องถิ่น, ประเภททั่วไป, ซูเปอร์คลาสและอินเทอร์เฟซที่นำไปใช้ แม้กระทั่งข้อยกเว้นของเมธอด ตัวอย่างบางส่วนแสดงไว้ด้านล่าง: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
และElementType.TYPE_PARAMETER
องค์ประกอบใหม่สองประเภทเพื่ออธิบายบริบทคำอธิบายประกอบที่เกี่ยวข้อง Annotation Processing API
ยังได้รับการเปลี่ยนแปลงเล็กน้อยเพื่อรับรู้ประเภทคำอธิบายประกอบใหม่ใน Java
3. คุณสมบัติใหม่ในคอมไพเลอร์ Java
3.1. ชื่อพารามิเตอร์
ตลอดเวลาที่ผ่านมา นักพัฒนา Java ได้คิดค้นวิธีการต่างๆ มากมายในการจัดเก็บชื่อพารามิเตอร์ของเมธอดใน Java bytecodeเพื่อให้สามารถใช้งานได้ในขณะรันไทม์ (เช่นไลบรารี Paranamer ) ในที่สุด Java 8 จะสร้างฟังก์ชันที่ยากลำบากนี้ในภาษา (โดยใช้ Reflection API และ methodParameter.getName()
) และ bytecode (โดยใช้อาร์กิวเมนต์คอมไพเลอร์ใหม่ 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() );
}
}
}
หากคุณคอมไพล์คลาสนี้โดยไม่ใช้อาร์กิวเมนต์–parameters
แล้วรันโปรแกรม คุณจะเห็นสิ่งนี้:
Parameter: arg0
เมื่อพารามิเตอร์–parameters
ส่งผ่านไปยังคอมไพเลอร์ ผลลัพธ์ของโปรแกรมจะแตกต่างออกไป (ชื่อจริงของพารามิเตอร์จะแสดง):
Parameter: args
สำหรับผู้ใช้ Maven ขั้นสูงสามารถเพิ่มอาร์กิวเมนต์ –parameters ลงในการคอมไพล์ได้โดยใช้ส่วน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>
เพื่อตรวจสอบความพร้อมของ ชื่อ พารามิเตอร์มีisNamePresent()
วิธีที่สะดวกในคลาสParameter
4. เครื่องมือ Java ใหม่
Java 8 มาพร้อมกับชุดเครื่องมือบรรทัดคำสั่งใหม่ ในส่วนนี้เราจะดูสิ่งที่น่าสนใจที่สุด4.1. เครื่องยนต์ Nashorn: jjs
jjsเป็นเอ็นจิ้น Nashorn แบบสแตนด์อโลนที่ใช้บรรทัดคำสั่ง ใช้รายการไฟล์ซอร์สโค้ด JavaScript และเรียกใช้งาน ตัวอย่างเช่น เรามาสร้าง ไฟล์ func.jsที่มีเนื้อหาดังต่อไปนี้:function f() {
return 1;
};
print( f() + 1 );
หากต้องการเรียกใช้ไฟล์นี้ ให้ส่งผ่านเป็นอาร์กิวเมนต์ไปที่jjs :
jjs func.js
เอาต์พุตคอนโซลจะเป็นดังนี้:
2
สำหรับรายละเอียดเพิ่มเติมโปรดดูเอกสารประกอบ
4.2. ตัววิเคราะห์การพึ่งพาคลาส: jdeps
jdepsเป็นเครื่องมือบรรทัดคำสั่งที่ยอดเยี่ยมจริงๆ มันแสดงการพึ่งพาระดับแพ็คเกจหรือคลาสสำหรับคลาส Java โดยยอมรับ ไฟล์ .classโฟลเดอร์ หรือไฟล์ JARเป็นอินพุต ตามค่าเริ่มต้นjdepsส่งออกการพึ่งพาไปยังเอาต์พุตมาตรฐาน (คอนโซล) ตามตัวอย่าง ลองดูรายงานการขึ้นต่อกันของไลบรารีSpring Framework ยอดนิยม เพื่อให้ตัวอย่างกระชับ ลองดูที่การขึ้นต่อกันของไฟล์ JARorg.springframework.core-3.0.5.RELEASE.jar
เท่านั้น
jdeps org.springframework.core-3.0.5.RELEASE.jar
คำสั่งนี้ให้ผลลัพธ์ค่อนข้างมาก ดังนั้นเราจะวิเคราะห์ผลลัพธ์เพียงบางส่วนเท่านั้น การขึ้นต่อกันจะถูกจัดกลุ่มตามแพ็คเกจ หากไม่มีการอ้างอิงไม่พบ จะปรากฏ ขึ้น
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
สำหรับข้อมูลโดยละเอียดเพิ่มเติม โปรดดูเอกสารอย่างเป็นทางการ
GO TO FULL VERSION