ส่วนที่สองของการแปลบทความคุณสมบัติ Java 8 – The ULTIMATE Guide ส่วนแรกอยู่ที่นี่ (ลิงก์อาจมีการเปลี่ยนแปลง)
5. คุณสมบัติใหม่ในไลบรารี Java 8
Java 8 ได้เพิ่มคลาสใหม่มากมายและขยายคลาสที่มีอยู่เพื่อรองรับการทำงานพร้อมกันสมัยใหม่ การเขียนโปรแกรมเชิงฟังก์ชัน วันที่/เวลา และอื่นๆ ได้ดียิ่งขึ้น5.1. คลาสเสริม
NullPointerExceptionที่มีชื่อเสียงเป็นสาเหตุที่พบบ่อยที่สุดของความล้มเหลวของแอปพลิเคชัน Java เมื่อนานมาแล้ว โครงการGuava ที่ยอดเยี่ยมของ Google นำเสนอOptional
เป็นวิธีแก้ปัญหาNullPointerException
ซึ่งช่วยป้องกันโค้ดจากการถูกตรวจสอบด้วยค่าว่าง และเป็นผลให้สนับสนุนการเขียนโค้ดที่สะอาดยิ่งขึ้น คลาส Guava ที่ได้รับแรงบันดาลใจจาก Google Optional
ตอนนี้เป็นส่วนหนึ่งของ Java 8 แล้ว Optional
มันเป็นเพียงคอนเทนเนอร์: มันสามารถมีค่าหรือบางประเภทТ
หรือเพียงแค่เป็นโมฆะ มีวิธีการที่เป็นประโยชน์มากมายเพื่อให้การตรวจสอบค่าว่างที่ชัดเจนไม่สมเหตุสมผลอีกต่อไป โปรดดูเอกสารอย่างเป็นทางการสำหรับข้อมูลโดยละเอียดเพิ่มเติม ลองดูตัวอย่างการใช้งานเล็กๆ สองตัวอย่างOptional
: มีและไม่มีค่าว่าง
Optional<String> fullName = Optional.ofNullable( null );
System.out.println( "Full Name is set? " + fullName.isPresent() );
System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) );
System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
วิธีการisPresent()
คืนค่าจริงหากอินสแตนซ์Optional
มีค่าที่ไม่ใช่ค่าว่างและเป็นเท็จมิฉะนั้น วิธีการนี้orElseGet()
มีกลไกทางเลือกสำหรับผลลัพธ์หากOptional
มีค่าว่าง ซึ่งจะยอมรับฟังก์ชันเพื่อสร้างค่าเริ่มต้น แผนที่ () วิธีการแปลงค่าปัจจุบันOptional
และส่งกลับอินสแตนซ์Optional
ใหม่ วิธีการนี้orElse()
คล้ายกับorElseGet()
แต่แทนที่จะใช้ฟังก์ชัน กลับใช้ค่าเริ่มต้น นี่คือผลลัพธ์ของโปรแกรมนี้:
Full Name is set? false
Full Name: [none]
Hey Stranger!
ลองมาดูตัวอย่างอื่นโดยเร็ว:
Optional<String> firstName = Optional.of( "Tom" );
System.out.println( "First Name is set? " + firstName.isPresent() );
System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) );
System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
System.out.println();
ผลลัพธ์จะเป็นดังนี้:
First Name is set? true
First Name: Tom
Hey Tom!
สำหรับข้อมูลโดยละเอียดเพิ่มเติม โปรดดูเอกสารอย่างเป็นทางการ
5.2. สตรีม
Stream API ที่เพิ่มเข้ามาใหม่(java.util.stream
) แนะนำการเขียนโปรแกรมสไตล์การใช้งานจริงใน Java เป็นส่วนเสริมที่ครอบคลุมมากที่สุดในไลบรารี Java และช่วยให้นักพัฒนา Java มีประสิทธิภาพมากขึ้นอย่างเห็นได้ชัด และยังช่วยให้พวกเขาสร้างโค้ดที่มีประสิทธิภาพ สะอาด และกระชับได้อีกด้วย Stream API ทำให้การประมวลผลคอลเลกชันง่ายขึ้นมาก (แต่ไม่จำกัดเพียงคอลเลกชัน ดังที่เราจะได้เห็นในภายหลัง) ลองมาดูคลาสง่ายๆเป็นTask
ตัวอย่าง
public class Streams {
private enum Status {
OPEN, CLOSED
};
private static final class Task {
private final Status status;
private final Integer points;
Task( final Status status, final Integer points ) {
this.status = status;
this.points = points;
}
public Integer getPoints() {
return points;
}
public Status getStatus() {
return status;
}
@Override
public String toString() {
return String.format( "[%s, %d]", status, points );
}
}
}
Task มีความรู้สึกบางอย่าง (หรือความยากลำบากหลอก) และสามารถเป็นได้ทั้งOPENหรือCLOSE ขอแนะนำชุดปัญหาเล็กๆ น้อยๆ ที่จะเล่นด้วย
final Collection<Task> tasks = Arrays.asList(
new Task( Status.OPEN, 5 ),
new Task( Status.OPEN, 13 ),
new Task( Status.CLOSED, 8 )
);
คำถามแรกที่เราตั้งใจจะค้นหาคือปัจจุบัน งาน OPEN มีกี่คะแนน? foreach
ก่อน Java 8 วิธีแก้ปัญหาปกติสำหรับสิ่ง นี้คือการใช้ตัววนซ้ำ แต่ใน Java 8 คำตอบคือสตรีม: ลำดับขององค์ประกอบที่รองรับการดำเนินการรวมตามลำดับและแบบขนาน
// Подсчет общего количества очков всех активных задач с использованием sum()
final long totalPointsOfOpenTasks = tasks
.stream()
.filter( task -> task.getStatus() == Status.OPEN )
.mapToInt( Task::getPoints )
.sum();
System.out.println( "Total points: " + totalPointsOfOpenTasks );
และเอาต์พุตคอนโซลจะมีลักษณะดังนี้:
Total points: 18
มาดูกันว่าเกิดอะไรขึ้นที่นี่ ขั้นแรก คอลเลกชันงานจะถูกแปลงเป็นรูปแบบการสตรีม จากนั้นการดำเนินการfilter
จะกรองงานทั้งหมดที่มีสถานะปิด ในขั้นตอน ถัดไป การดำเนินการmapToInt
แปลง stream Task
s เป็น stream Integer
s โดยใช้วิธีTask::getPoints
สำหรับแต่ละอินสแตนซ์ Task
สุดท้าย คะแนนทั้งหมดจะถูกรวมเข้าด้วยกันโดยใช้วิธีsum
ซึ่งให้ผลลัพธ์สุดท้าย ก่อนที่จะไปยังตัวอย่างถัดไป มีหมายเหตุบางประการเกี่ยวกับชุดข้อความที่ควรคำนึงถึง (รายละเอียดเพิ่มเติมที่นี่ ) การดำเนินงานstream
จะแบ่งออกเป็นการดำเนินงาน ขั้นกลางและขั้นสุดท้าย การดำเนินการระดับกลางจะส่งคืนสตรีมใหม่ พวกเขาขี้เกียจเสมอ เมื่อดำเนินการกลาง เช่นfilter
พวกเขาไม่ได้ทำการกรองจริงๆ แต่จะสร้างสตรีมใหม่แทน ซึ่งเมื่อเสร็จสิ้นแล้ว จะมีองค์ประกอบของสตรีมดั้งเดิมที่ตรงกับภาคแสดงที่กำหนด การดำเนินการที่มีขอบเขตจำกัดเช่นforEach
และsum
สามารถส่งผ่านกระแสข้อมูลเพื่อสร้างผลลัพธ์หรือผลข้างเคียงได้ เมื่อการดำเนินการขั้นสุดท้ายเสร็จสิ้น จะถือว่าสตรีมถูกใช้และไม่สามารถนำมาใช้อีกได้ ในเกือบทุกกรณี การดำเนินการสิ้นสุดมีแนวโน้มที่จะดำเนินการสำรวจผ่านแหล่งข้อมูลที่สำคัญ คุณสมบัติอันมีค่าอีกประการหนึ่งของเธรดคือการรองรับกระบวนการแบบขนานนอกกรอบ ลองดูตัวอย่างนี้ ซึ่งจะค้นหาผลรวมของคะแนนของปัญหาทั้งหมด
// Calculate total points of all tasks
final double totalPoints = tasks
.stream()
.parallel()
.map( task -> task.getPoints() ) // or map( Task::getPoints )
.reduce( 0, Integer::sum );
System.out.println( "Total points (all tasks): " + totalPoints );
สิ่งนี้คล้ายกับตัวอย่างแรกมาก ยกเว้นว่าเราพยายามประมวลผลงานทั้งหมดแบบขนานและคำนวณผลลัพธ์สุดท้ายโดยใช้วิธีreduce
การ นี่คือเอาต์พุตคอนโซล:
Total points (all tasks): 26.0
บ่อยครั้งจำเป็นต้องจัดกลุ่มองค์ประกอบตามเกณฑ์ที่กำหนด ตัวอย่างนี้แสดงให้เห็นว่าเธรดสามารถช่วยในเรื่องนี้ได้อย่างไร
// Группировка задач по их статусу
final Map<Status, List<Task>> map = tasks
.stream()
.collect( Collectors.groupingBy( Task::getStatus ) );
System.out.println( map );
เอาต์พุตคอนโซลจะเป็นดังนี้:
{CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]}
เพื่อจบตัวอย่างปัญหา เราจะคำนวณเปอร์เซ็นต์โดยรวม (หรือน้ำหนัก) ของแต่ละปัญหาในคอลเลกชันตามคะแนนรวม:
// Подсчет веса каждой задачи (How процент от общего количества очков)
final Collection<String> result = tasks
.stream() // Stream<String>
.mapToInt( Task::getPoints ) // IntStream
.asLongStream() // LongStream
.mapToDouble( points -> points / totalPoints ) // DoubleStream
.boxed() // Stream<Double>
.mapToLong( weigth -> ( long )( weigth * 100 ) ) // LongStream
.mapToObj( percentage -> percentage + "%" ) // Stream<String>
.collect( Collectors.toList() ); // List<String>
System.out.println( result );
เอาต์พุตคอนโซลจะเป็นดังนี้:
[19%, 50%, 30%]
สุดท้ายนี้ ดังที่เราได้กล่าวไว้ก่อนหน้านี้ Stream API ไม่ได้มีไว้สำหรับคอลเลกชัน Java เท่านั้น การดำเนินการ I/O ทั่วไป เช่น การอ่านไฟล์ข้อความทีละบรรทัด เป็นตัวเลือกที่ดีมากสำหรับการใช้การประมวลผลสตรีม นี่เป็นตัวอย่างเล็กๆ น้อยๆ ที่จะพิสูจน์เรื่องนี้
final Path path = new File( filename ).toPath();
try( Stream<String> lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {
lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println );
}
เมธอดonConsole
ซึ่งถูกเรียกบนเธรด จะส่งคืนเธรดที่เทียบเท่ากับตัวจัดการส่วนตัวเพิ่มเติม ตัวจัดการส่วนตัวจะถูกเรียกเมื่อมีการclose()
เรียกใช้เมธอดบนเธรด Stream API พร้อมด้วยlambdasและวิธีการอ้างอิงตลอดจนวิธีการเริ่มต้นและแบบคงที่ใน Java 8 คือคำตอบสำหรับกระบวนทัศน์การพัฒนาซอฟต์แวร์สมัยใหม่ สำหรับข้อมูลโดยละเอียดเพิ่มเติม โปรดดูเอกสารอย่างเป็นทางการ
5.3. วันที่/เวลา API (JSR 310)
Java 8 นำรูปลักษณ์ใหม่มาสู่การจัดการวันที่และเวลาโดยจัดให้มีDate and Time API (JSR 310)ใหม่ การปรับเปลี่ยนวันที่และเวลาเป็นหนึ่งในปัญหาที่เลวร้ายที่สุดสำหรับนักพัฒนา Javajava.util.Date
โดยทั่วไป การปฏิบัติตามมาตรฐานjava.util.Calendar
ไม่ได้ช่วยให้สถานการณ์ดีขึ้น (อาจทำให้สับสนมากขึ้นด้วยซ้ำ) นั่นคือที่ มาของ Joda-Time : ทางเลือก API วันที่/เวลาที่ยอดเยี่ยมสำหรับ Java API วันที่/เวลาใหม่ใน Java 8 (JSR 310) ได้รับอิทธิพลอย่างมากจากJoda-Timeและใช้ประโยชน์สูงสุดจากมัน แพ็คเกจใหม่java.time
ประกอบด้วยคลาสทั้งหมดสำหรับวันที่ เวลา วันที่/เวลา โซนเวลา ระยะเวลา และการจัดการเวลา การออกแบบ API ให้ความสำคัญกับความไม่เปลี่ยนรูปเป็นอย่างมาก: ไม่อนุญาตให้มีการเปลี่ยนแปลง (บทเรียนที่ยากที่เรียนรู้จากjava.util.Calendar
) หากจำเป็นต้องมีการแก้ไข อินสแตนซ์ใหม่ของคลาสที่เกี่ยวข้องจะถูกส่งกลับ ลองดูคลาสหลักและตัวอย่างการใช้งาน คลาสแรกClock
ซึ่งให้การเข้าถึงทันที วันที่และเวลาปัจจุบันโดยใช้เขตเวลา Clock
สามารถใช้แทนSystem.currentTimeMillis()
และTimeZone.getDefault()
.
// Получить системное время How смещение UTC
final Clock clock = Clock.systemUTC();
System.out.println( clock.instant() );
System.out.println( clock.millis() );
ตัวอย่างเอาต์พุตคอนโซล:
2014-04-12T15:19:29.282Z
1397315969360
คลาสใหม่อื่น ๆ ที่เราจะดูคือLocaleDate
และLocalTime
. LocaleDate
มีเพียงส่วนวันที่ที่ไม่มีเขตเวลาในระบบปฏิทิน ISO-8601 ดังนั้นจึงLocalTime
มีเพียงส่วนหนึ่งของรหัสเวลา>
// получить местную date и время время
final LocalDate date = LocalDate.now();
final LocalDate dateFromClock = LocalDate.now( clock );
System.out.println( date );
System.out.println( dateFromClock );
// получить местную date и время время
final LocalTime time = LocalTime.now();
final LocalTime timeFromClock = LocalTime.now( clock );
System.out.println( time );
System.out.println( timeFromClock );
ตัวอย่างเอาต์พุตคอนโซล:
2014-04-12
2014-04-12
11:25:54.568
15:25:54.568
LocalDateTime
เชื่อมต่อLocaleDate
และLocalTime
และประกอบด้วยวันที่และเวลา แต่ไม่มีเขตเวลา ในระบบปฏิทิน ISO-8601 ตัวอย่างง่ายๆได้รับด้านล่าง
// Get the local date/time
final LocalDateTime datetime = LocalDateTime.now();
final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );
System.out.println( datetime );
System.out.println( datetimeFromClock );
ตัวอย่างเอาต์พุตคอนโซล:
2014-04-12T11:37:52.309
2014-04-12T15:37:52.309
ในกรณีที่คุณต้องการวันที่/เวลาสำหรับเขตเวลาที่ZonedDateTime
ระบุ ประกอบด้วยวันที่และเวลาในระบบปฏิทิน ISO-8601 ต่อไปนี้คือตัวอย่างบางส่วนสำหรับเขตเวลาต่างๆ
// Получение даты/времени для временной зоны
final ZonedDateTime zonedDatetime = ZonedDateTime.now();
final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );
final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) );
System.out.println( zonedDatetime );
System.out.println( zonedDatetimeFromClock );
System.out.println( zonedDatetimeFromZone );
ตัวอย่างเอาต์พุตคอนโซล:
2014-04-12T11:47:01.017-04:00[America/New_York]
2014-04-12T15:47:01.017Z
2014-04-12T08:47:01.017-07:00[America/Los_Angeles]
และสุดท้าย เรามาดูคลาสกันDuration
: ช่วงเวลาในหน่วยวินาทีและนาโนวินาที ทำให้การคำนวณระหว่างวันที่สองวันง่ายมาก มาดูวิธีการทำเช่นนี้:
// Получаем разницу между двумя датами
final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 );
final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 );
final Duration duration = Duration.between( from, to );
System.out.println( "Duration in days: " + duration.toDays() );
System.out.println( "Duration in hours: " + duration.toHours() );
ตัวอย่างด้านบนคำนวณระยะเวลา (เป็นวันและชั่วโมง) ระหว่างวันที่ 2 วัน คือ16 เมษายน 2014ถึง16 เมษายน 2015 นี่คือตัวอย่างของเอาต์พุตคอนโซล:
Duration in days: 365
Duration in hours: 8783
ความประทับใจโดยรวมของวันที่/เวลาใหม่ใน Java 8 นั้นเป็นไปในเชิงบวกอย่างมาก ส่วนหนึ่งเป็นเพราะการเปลี่ยนแปลงนั้นขึ้นอยู่กับรากฐานที่ผ่านการทดสอบการต่อสู้แล้ว (Joda-Time) ส่วนหนึ่งเป็นเพราะในครั้งนี้ปัญหาได้รับการแก้ไขอย่างจริงจังและได้ยินเสียงของผู้พัฒนา สำหรับรายละเอียด โปรดดูเอกสารอย่างเป็นทางการ
5.4. เอ็นจิ้น Nashorn JavaScript
Java 8 มาพร้อมกับเอ็นจิ้น Nashorn JavaScript ใหม่ซึ่งช่วยให้คุณพัฒนาและรันแอปพลิเคชัน JavaScript บางประเภทบน JVM เอ็นจิ้น Nashorn JavaScript เป็นเพียงการใช้งาน javax.script.ScriptEngine อีกรูปแบบหนึ่งที่เป็นไปตามกฎชุดเดียวกันเพื่อให้ Java และ JavaScript สามารถโต้ตอบได้ นี่เป็นตัวอย่างเล็กๆ น้อยๆScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName( "JavaScript" );
System.out.println( engine.getClass().getName() );
System.out.println( "Result:" + engine.eval( "function f() { return 1; }; f() + 1;" ) );
ตัวอย่างเอาต์พุตคอนโซล:
jdk.nashorn.api.scripting.NashornScriptEngine
Result: 2
5.5. ฐาน64
ในที่สุดการสนับสนุนการเข้ารหัส Base64ก็พบได้ในไลบรารีมาตรฐาน Java ด้วยการเปิดตัว Java 8 มันใช้งานง่ายมาก ตัวอย่างนี้แสดงให้เห็นpackage com.javacodegeeks.java8.base64;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class Base64s {
public static void main(String[] args) {
final String text = "Base64 finally in Java 8!";
final String encoded = Base64
.getEncoder()
.encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );
System.out.println( encoded );
final String decoded = new String(
Base64.getDecoder().decode( encoded ),
StandardCharsets.UTF_8 );
System.out.println( decoded );
}
}
เอาต์พุตคอนโซลของโปรแกรมแสดงทั้งข้อความที่เข้ารหัสและถอดรหัส:
QmFzZTY0IGZpbmFsbHkgaW4gSmF2YSA4IQ==
Base64 finally in Java 8!
นอกจากนี้ยังมีคลาสสำหรับตัวเข้ารหัส/ตัวถอดรหัสที่เป็นมิตรกับ URL รวมถึงตัวเข้ารหัส/ตัวถอดรหัสที่เป็นมิตรกับ MIME ( Base64.getUrlEncoder()
/ Base64.getUrlDecoder()
, Base64.getMimeEncoder()
/ Base64.getMimeDecoder()
)
5.6. อาร์เรย์ขนาน
Java 8 release เพิ่มวิธีการใหม่ๆ มากมายสำหรับการประมวลผลอาร์เรย์แบบขนาน บางทีสิ่งที่สำคัญที่สุดคือparallelSort()
ซึ่งสามารถเร่งการเรียงลำดับบนเครื่องแบบมัลติคอร์ได้อย่างมาก ตัวอย่างเล็กๆ น้อยๆ ด้านล่างแสดงให้เห็นถึงกลุ่มวิธีการใหม่ ( parallelXxx
) ที่ใช้งานจริง
package com.javacodegeeks.java8.parallel.arrays;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
public class ParallelArrays {
public static void main( String[] args ) {
long[] arrayOfLong = new long [ 20000 ];
Arrays.parallelSetAll( arrayOfLong,
index -> ThreadLocalRandom.current().nextInt( 1000000 ) );
Arrays.stream( arrayOfLong ).limit( 10 ).forEach(
i -> System.out.print( i + " " ) );
System.out.println();
Arrays.parallelSort( arrayOfLong );
Arrays.stream( arrayOfLong ).limit( 10 ).forEach(
i -> System.out.print( i + " " ) );
System.out.println();
}
}
โค้ดเล็กๆ นี้ใช้วิธีparallelSetAll()
การเติมอาร์เรย์ด้วยค่าสุ่ม 20,000 ค่า หลังจากนั้นก็นำไปparallelSort()
ใช้ โปรแกรมจะพิมพ์ 10 องค์ประกอบแรกก่อนและหลังการเรียงลำดับเพื่อแสดงว่าอาร์เรย์ถูกจัดเรียงจริง ตัวอย่างเอาต์พุตของโปรแกรมอาจมีลักษณะเช่นนี้ (โปรดทราบว่าองค์ประกอบของอาร์เรย์เป็นแบบสุ่ม)
Unsorted: 591217 891976 443951 424479 766825 351964 242997 642839 119108 552378
Sorted: 39 220 263 268 325 607 655 678 723 793
5.7. ความเท่าเทียม
มีการเพิ่มวิธีการใหม่ในคลาสjava.util.concurrent.ConcurrentHashMap
เพื่อรองรับการดำเนินการแบบรวมโดยอิงตามออบเจ็กต์สตรีมที่เพิ่มใหม่และนิพจน์แลมบ์ดา นอกจากนี้ยังมีการเพิ่มวิธีการใหม่ในคลาสjava.util.concurrent.ForkJoinPool
เพื่อรองรับการรวมกลุ่มที่ใช้ร่วมกัน (ดูหลักสูตรฟรีของเราเกี่ยวกับการทำงานพร้อมกันของ Java ) มีการเพิ่ม คลาสใหม่java.util.concurrent.locks.StampedLock
เพื่อให้การล็อคตามความสามารถด้วยโหมดการเข้าถึงสามโหมดสำหรับการควบคุมการอ่าน/เขียน (ถือได้ว่าเป็นทางเลือกที่ดีกว่าสำหรับโหมดที่ไม่ค่อยดีนักjava.util.concurrent.locks.ReadWriteLock
) คลาสใหม่ที่เพิ่มเข้ามาในแพ็คเกจjava.util.concurrent.atomic
:
- DoubleAccumulator
- ดับเบิลแอดเดอร์
- LongAccumulator
- ลองแอดเดอร์
6. คุณสมบัติใหม่ในสภาพแวดล้อมรันไทม์ Java (JVM)
พื้นที่PermGen
ดังกล่าวถูกยกเลิกและแทนที่ด้วย Metaspace (JEP 122) ตัวเลือก JVM -XX:PermSize
และ-XX:MaxPermSize
ถูกแทนที่ด้วย-XX:MetaSpaceSize
และ-XX:MaxMetaspaceSize
ตามลำดับ
7. บทสรุป
อนาคตอยู่ที่นี่: Java 8 ได้ขยับแพลตฟอร์มไปข้างหน้าด้วยการนำเสนอฟีเจอร์ที่ช่วยให้นักพัฒนามีประสิทธิผลมากขึ้น ยังเร็วเกินไปที่จะย้ายระบบการผลิตไปยัง Java 8 แต่การนำไปใช้น่าจะเริ่มเติบโตอย่างช้าๆ ในอีกไม่กี่เดือนข้างหน้า อย่างไรก็ตาม ตอนนี้เป็นเวลาที่จะเริ่มเตรียมฐานโค้ดของคุณสำหรับความเข้ากันได้ของ Java 8 และพร้อมที่จะรวมการเปลี่ยนแปลงของ Java 8 เมื่อมีความปลอดภัยและเสถียรเพียงพอ เพื่อเป็นข้อพิสูจน์ถึงการยอมรับของชุมชนต่อ Java 8 Pivotal เพิ่งเปิดตัว Spring Framework พร้อมการสนับสนุนการผลิตสำหรับ Java 8 คุณสามารถให้ข้อมูลของคุณเกี่ยวกับคุณสมบัติใหม่ที่น่าตื่นเต้นใน Java 8 ได้ในความคิดเห็น8. แหล่งที่มา
แหล่งข้อมูลเพิ่มเติมบางส่วนที่กล่าวถึงแง่มุมต่างๆ ของคุณสมบัติ Java 8 ในเชิงลึก:- มีอะไรใหม่ใน JDK 8
- บทช่วยสอน Java
- WildFly 8, JDK 8, NetBeans 8, Java EE 7
- บทช่วยสอน Java 8
- JDK 8 ตัวตรวจสอบการพึ่งพาแบบคงที่ของบรรทัดคำสั่ง
- Javadoc ที่ส่องสว่างของ JDK 8
- ด้านมืดของ Java 8
- การติดตั้งการสนับสนุน Java™ 8 ใน Eclipse Kepler SR2
- จาวา 8
- ออราเคิล นาชอน. เอ็นจิ้น JavaScript ยุคถัดไปสำหรับ JVM
GO TO FULL VERSION