portaldacalheta.pt
  • หลัก
  • การจัดการโครงการ
  • การเพิ่มขึ้นของระยะไกล
  • การบริหารโครงการ
  • เครื่องมือและบทช่วยสอน
ส่วนหน้าของเว็บ

ทำไมคุณต้องอัพเกรดเป็น Java 8 อยู่แล้ว



เวอร์ชันใหม่ล่าสุดของแพลตฟอร์ม Java จาวา 8 เปิดตัวมานานกว่าหนึ่งปีแล้ว หลาย บริษัท และ นักพัฒนา ยังคงใช้งานได้กับเวอร์ชันก่อนหน้าซึ่งเป็นที่เข้าใจได้เนื่องจากมีปัญหามากมายในการย้ายจากเวอร์ชันแพลตฟอร์มหนึ่งไปยังอีกเวอร์ชันหนึ่ง ถึงกระนั้นนักพัฒนาจำนวนมากก็ยังคงเริ่มต้น ใหม่ แอปพลิเคชันที่มี Java เวอร์ชันเก่า มีเหตุผลที่ดีน้อยมากที่จะทำเช่นนี้เนื่องจาก Java 8 ได้นำการปรับปรุงที่สำคัญบางอย่างมาสู่ภาษา

มีมากมาย คุณสมบัติใหม่ ใน Java 8 ฉันจะแสดงสิ่งที่มีประโยชน์และน่าสนใจที่สุดให้คุณดู:



  • นิพจน์แลมบ์ดา
  • Stream API สำหรับการทำงานกับ Collections
  • การเชื่อมโยงงานแบบอะซิงโครนัสกับ CompletableFuture
  • Time API ใหม่ล่าสุด

แลมบ์ดานิพจน์

ถึง แลมด้า เป็นบล็อกรหัสที่สามารถอ้างอิงและส่งผ่านไปยังส่วนของรหัสอื่นสำหรับการดำเนินการในอนาคตอย่างน้อยหนึ่งครั้ง ตัวอย่างเช่นฟังก์ชันที่ไม่ระบุชื่อในภาษาอื่นคือแลมบ์ดา เช่นเดียวกับฟังก์ชัน lambdas สามารถส่งผ่านอาร์กิวเมนต์ในขณะที่ดำเนินการแก้ไขผลลัพธ์ได้ แนะนำ Java 8 นิพจน์แลมบ์ดา ซึ่งนำเสนอไวยากรณ์ง่ายๆในการสร้างและใช้ lambdas



มาดูตัวอย่างวิธีการปรับปรุงโค้ดของเรา ที่นี่เรามีตัวเปรียบเทียบง่ายๆซึ่งเปรียบเทียบสอง Integer ค่าตามโมดูโล 2:



class BinaryComparator implements Comparator{ @Override public int compare(Integer i1, Integer i2) { return i1 % 2 - i2 % 2; } }

ในอนาคตอาจมีการเรียกอินสแตนซ์ของคลาสนี้ในโค้ดซึ่งจำเป็นต้องใช้ตัวเปรียบเทียบนี้เช่นนี้:

... List list = ...; Comparator comparator = new BinaryComparator(); Collections.sort(list, comparator); ...

ไวยากรณ์แลมบ์ดาใหม่ช่วยให้เราทำสิ่งนี้ได้ง่ายขึ้น นี่คือนิพจน์แลมบ์ดาที่เรียบง่ายซึ่งทำสิ่งเดียวกับ compare วิธีการจาก BinaryComparator:



(Integer i1, Integer i2) -> i1 % 2 - i2 % 2;

โครงสร้างมีความคล้ายคลึงกันมากกับฟังก์ชัน ในวงเล็บเราตั้งค่ารายการอาร์กิวเมนต์ ไวยากรณ์ -> แสดงว่านี่คือแลมด้า และในส่วนทางขวามือของนิพจน์นี้เราตั้งค่าพฤติกรรมของแลมด้า

Java 8 LAMBDA EXPRESSION



ตอนนี้เราสามารถปรับปรุงตัวอย่างก่อนหน้าของเรา:

... List list = ...; Collections.sort(list, (Integer i1, Integer i2) -> i1 % 2 - i2 % 2); ...

เราอาจกำหนดตัวแปรด้วยวัตถุนี้ มาดูกันว่าหน้าตาเป็นอย่างไร:



ข้อใดต่อไปนี้ถือเป็นปัญหาด้านความปลอดภัยทั่วไป (เลือกทุกข้อที่ใช่)
Comparator comparator = (Integer i1, Integer i2) -> i1 % 2 - i2 % 2;

ตอนนี้เราสามารถใช้ฟังก์ชันนี้ซ้ำได้ดังนี้:

... List list1 = ...; List list2 = ...; Collections.sort(list1, comparator); Collections.sort(list2, comparator); ...

สังเกตว่าในตัวอย่างเหล่านี้แลมด้าจะถูกส่งต่อไปยัง sort() วิธีเดียวกับอินสแตนซ์ของ BinaryComparator ถูกส่งผ่านในตัวอย่างก่อนหน้านี้ JVM รู้ได้อย่างไรว่าจะตีความแลมด้าอย่างถูกต้อง?



เพื่อให้ฟังก์ชันใช้ lambdas เป็นอาร์กิวเมนต์ Java 8 จึงแนะนำแนวคิดใหม่: อินเตอร์เฟซที่ใช้งานได้ . อินเทอร์เฟซที่ใช้งานได้คืออินเทอร์เฟซที่มีวิธีนามธรรมเพียงวิธีเดียว ในความเป็นจริง Java 8 ถือว่านิพจน์แลมบ์ดาเป็นการใช้งานอินเทอร์เฟซการทำงานแบบพิเศษ ซึ่งหมายความว่าในการรับแลมบ์ดาเป็นอาร์กิวเมนต์เมธอดประเภทที่ประกาศของอาร์กิวเมนต์นั้นจะต้องเป็นอินเทอร์เฟซที่ใช้งานได้เท่านั้น

เมื่อเราประกาศอินเทอร์เฟซที่ใช้งานได้เราอาจเพิ่ม @FunctionalInterface สัญกรณ์เพื่อแสดงให้นักพัฒนาเห็นว่ามันคืออะไร:



@FunctionalInterface private interface DTOSender { void send(String accountId, DTO dto); } void sendDTO(BisnessModel object, DTOSender dtoSender) { //some logic for sending... ... dtoSender.send(id, dto); ... }

ตอนนี้เราสามารถเรียก method sendDTO โดยส่งผ่าน lambdas ที่แตกต่างกันเพื่อให้ได้พฤติกรรมที่แตกต่างกันดังนี้:

sendDTO(object, ((accountId, dto) -> sendToAndroid(accountId, dto))); sendDTO(object, ((accountId, dto) -> sendToIos(accountId, dto)));

การอ้างอิงวิธีการ

อาร์กิวเมนต์แลมบ์ดาช่วยให้เราสามารถปรับเปลี่ยนพฤติกรรมของฟังก์ชันหรือวิธีการได้ ดังที่เราเห็นในตัวอย่างสุดท้ายบางครั้งแลมด้าทำหน้าที่เรียกวิธีอื่นเท่านั้น (sendToAndroid หรือ sendToIos) สำหรับกรณีพิเศษนี้ Java 8 แนะนำชวเลขที่สะดวก: การอ้างอิงวิธีการ . ไวยากรณ์แบบย่อนี้แสดงถึงแลมบ์ดาที่เรียกเมธอดและมีรูปแบบ objectName::methodName สิ่งนี้ช่วยให้เราทำให้ตัวอย่างก่อนหน้านี้กระชับและอ่านง่ายยิ่งขึ้น:

sendDTO(object, this::sendToAndroid); sendDTO(object, this::sendToIos);

ในกรณีนี้วิธีการ sendToAndroid และ sendToIos ถูกนำไปใช้ใน this ชั้นเรียน. เรายังอาจอ้างอิงวิธีการของวัตถุหรือคลาสอื่น

สตรีม API

Java 8 นำความสามารถใหม่มาใช้กับ Collections ในรูปแบบของ Stream API ใหม่ล่าสุด ฟังก์ชันใหม่นี้มีให้โดย java.util.stream และมุ่งเป้าไปที่การเปิดใช้งาน การทำงาน แนวทางการเขียนโปรแกรมด้วยคอลเล็กชัน ดังที่เราจะเห็นสิ่งนี้เป็นไปได้มากเนื่องจากไวยากรณ์แลมบ์ดาใหม่ที่เราเพิ่งพูดถึง

Stream API นำเสนอการกรองการนับและการแมปคอลเลคชันที่ง่ายดายรวมถึงวิธีต่างๆในการดึงข้อมูลชิ้นส่วนและชุดย่อยออกจากข้อมูลเหล่านี้ ด้วยไวยากรณ์รูปแบบการทำงานทำให้ Stream API อนุญาตให้ใช้โค้ดที่สั้นและสวยงามมากขึ้นสำหรับการทำงานกับคอลเลกชัน

เริ่มต้นด้วยตัวอย่างสั้น ๆ เราจะใช้โมเดลข้อมูลนี้ในตัวอย่างทั้งหมด:

class Author { String name; int countOfBooks; } class Book { String name; int year; Author author; }

ลองนึกภาพว่าเราต้องพิมพ์ผู้เขียนทั้งหมดใน a books คอลเลกชันที่เขียนหนังสือหลังปี 2005 เราจะทำอย่างไรใน Java 7?

for (Book book : books) { if (book.author != null && book.year > 2005){ System.out.println(book.author.name); } }

แล้วเราจะทำอย่างไรใน Java 8?

books.stream() .filter(book -> book.year > 2005) // filter out books published in or before 2005 .map(Book::getAuthor) // get the list of authors for the remaining books .filter(Objects::nonNull) // remove null authors from the list .map(Author::getName) // get the list of names for the remaining authors .forEach(System.out::println); // print the value of each remaining element

เป็นเพียงสำนวนเดียวเท่านั้น! เรียกเมธอด stream() เมื่อใด ๆ Collection ส่งคืน a Stream วัตถุที่ห่อหุ้มองค์ประกอบทั้งหมดของคอลเลกชันนั้น สิ่งนี้สามารถจัดการได้ด้วยตัวปรับแต่งต่างๆจาก Stream API เช่น filter() และ map(). ตัวปรับแต่งแต่ละตัวจะส่งคืน Stream ใหม่ วัตถุที่มีผลการปรับเปลี่ยนซึ่งสามารถจัดการเพิ่มเติมได้ .forEach() วิธีการช่วยให้เราดำเนินการบางอย่างสำหรับแต่ละอินสแตนซ์ของสตรีมที่เป็นผลลัพธ์

ตัวอย่างนี้ยังแสดงให้เห็นถึงความสัมพันธ์ที่ใกล้ชิดระหว่างการเขียนโปรแกรมเชิงฟังก์ชันและนิพจน์แลมบ์ดา สังเกตว่าอาร์กิวเมนต์ที่ส่งไปยังแต่ละเมธอดในสตรีมอาจเป็นแลมด้าที่กำหนดเองหรือการอ้างอิงเมธอด ในทางเทคนิคตัวปรับแต่งแต่ละตัวสามารถรับอินเทอร์เฟซที่ใช้งานได้ตามที่อธิบายไว้ในส่วนก่อนหน้า

Stream API ช่วยให้นักพัฒนาดูคอลเลกชัน Java จากมุมมองใหม่ ลองนึกภาพตอนนี้ว่าเราต้องได้รับ Map ของภาษาที่ใช้ได้ในแต่ละประเทศ สิ่งนี้จะนำไปใช้ใน Java 7 ได้อย่างไร?

Map countryToSetOfLanguages = new HashMap(); for (Locale locale : Locale.getAvailableLocales()){ String country = locale.getDisplayCountry(); if (!countryToSetOfLanguages.containsKey(country)){ countryToSetOfLanguages.put(country, new HashSet()); } countryToSetOfLanguages.get(country).add(locale.getDisplayLanguage()); }

ใน Java 8 สิ่งต่าง ๆ ค่อนข้างดีกว่า:

import java.util.stream.*; import static java.util.stream.Collectors.*; ... Map countryToSetOfLanguages = Stream.of(Locale.getAvailableLocales()) .collect(groupingBy(Locale::getDisplayCountry, mapping(Locale::getDisplayLanguage, toSet())));

วิธีการ collect() ช่วยให้เรารวบรวมผลลัพธ์ของสตรีมในรูปแบบต่างๆ ที่นี่เราจะเห็นว่าอันดับแรกจัดกลุ่มตามประเทศจากนั้นจึงจับคู่แต่ละกลุ่มตามภาษา (groupingBy() และ toSet() เป็นวิธีการคงที่จากคลาส Collectors)

วิธีเขียน unit test java

JAVA 8 STREAM API

Stream API มีความสามารถอื่น ๆ อีกมากมาย สามารถดูเอกสารฉบับสมบูรณ์ได้ ที่นี่ . ฉันขอแนะนำให้อ่านเพิ่มเติมเพื่อทำความเข้าใจอย่างลึกซึ้งยิ่งขึ้นเกี่ยวกับเครื่องมืออันทรงพลังทั้งหมดที่แพ็คเกจนี้มีให้

Asynchronous Task Chaining กับ CompletableFuture

ใน Java 7’s java.util.concurrent แพคเกจมีอินเทอร์เฟซ Future ซึ่งช่วยให้เราได้รับสถานะหรือผลลัพธ์ของงานอะซิงโครนัสบางอย่างในอนาคต ในการใช้ฟังก์ชันนี้เราต้อง:

  1. สร้างไฟล์ ExecutorService ซึ่งจัดการการดำเนินการของงานอะซิงโครนัสและสามารถสร้าง Future วัตถุเพื่อติดตามความคืบหน้า
  2. สร้างแบบอะซิงโครนัส Runnable งาน.
  3. เรียกใช้งานใน ExecutorService ซึ่งจะให้ Future ให้สิทธิ์เข้าถึงสถานะหรือผลลัพธ์

ในการใช้ผลลัพธ์ของงานแบบอะซิงโครนัสจำเป็นต้องติดตามความคืบหน้าจากภายนอกโดยใช้วิธีการของ Future อินเทอร์เฟซและเมื่อพร้อมแล้วให้ดึงผลลัพธ์อย่างชัดเจนและดำเนินการเพิ่มเติมกับพวกเขา สิ่งนี้ค่อนข้างซับซ้อนในการนำไปใช้โดยไม่มีข้อผิดพลาดโดยเฉพาะอย่างยิ่งในแอปพลิเคชันที่มีงานพร้อมกันจำนวนมาก

อย่างไรก็ตามใน Java 8 นั้น Future แนวคิดถูกนำไปใช้เพิ่มเติมด้วย CompletableFuture อินเทอร์เฟซซึ่งอนุญาตให้สร้างและดำเนินการโซ่ของงานอะซิงโครนัส เป็นกลไกที่มีประสิทธิภาพในการสร้างแอปพลิเคชันแบบอะซิงโครนัสใน Java 8 เนื่องจากช่วยให้เราประมวลผลผลลัพธ์ของแต่ละงานโดยอัตโนมัติเมื่อเสร็จสิ้น

ลองดูตัวอย่าง:

import java.util.concurrent.CompletableFuture; ... CompletableFuture voidCompletableFuture = CompletableFuture.supplyAsync(() -> blockingReadPage()) .thenApply(this::getLinks) .thenAccept(System.out::println);

วิธีการ CompletableFuture.supplyAsync สร้างงานอะซิงโครนัสใหม่ในค่าเริ่มต้น Executor (โดยทั่วไป ForkJoinPool ). เมื่องานเสร็จสิ้นผลลัพธ์จะถูกจัดให้เป็นอาร์กิวเมนต์โดยอัตโนมัติสำหรับฟังก์ชัน this::getLinks ซึ่งรันในงานอะซิงโครนัสใหม่ สุดท้ายผลลัพธ์ของขั้นตอนที่สองนี้จะถูกพิมพ์ไปที่ System.out โดยอัตโนมัติ thenApply() และ thenAccept() เป็นเพียงสองในหลาย ๆ วิธีการที่มีประโยชน์ พร้อมที่จะช่วยคุณสร้างงานพร้อมกันโดยไม่ต้องใช้ Executors ด้วยตนเอง

CompletableFuture ทำให้ง่ายต่อการจัดการลำดับของการดำเนินการแบบอะซิงโครนัสที่ซับซ้อน สมมติว่าเราจำเป็นต้องสร้างการดำเนินการทางคณิตศาสตร์หลายขั้นตอนโดยมีงานสามอย่าง ภารกิจที่ 1 และ ภารกิจที่ 2 ใช้อัลกอริทึมที่แตกต่างกันเพื่อค้นหาผลลัพธ์สำหรับขั้นตอนแรกและเรารู้ว่ามีเพียงหนึ่งในนั้นเท่านั้นที่จะทำงานได้ในขณะที่อีกขั้นจะล้มเหลว อย่างไรก็ตามการทำงานใดขึ้นอยู่กับข้อมูลอินพุตซึ่งเราไม่ทราบล่วงหน้า ผลลัพธ์จากงานเหล่านี้จะต้องรวมกับผลลัพธ์ของ งาน 3 . ดังนั้นเราต้องหาผลลัพธ์ของอย่างใดอย่างหนึ่ง งาน 1 หรือ ภารกิจที่ 2 , และ ผลของ งาน 3 . เพื่อให้บรรลุเป้าหมายนี้เราสามารถเขียนสิ่งนี้:

ไฟล์ส่วนหัว c ++ ตัวอย่าง
import static java.util.concurrent.CompletableFuture.*; ... Supplier task1 = (...) -> { ... // some complex calculation return 1; // example result }; Supplier task2 = (...) -> { ... // some complex calculation throw new RuntimeException(); // example exception }; Supplier task3 = (...) -> { ... // some complex calculation return 3; // example result }; supplyAsync(task1) // run task1 .applyToEither( // use whichever result is ready first, result of task1 or supplyAsync(task2), // result of task2 (Integer i) -> i) // return result as-is .thenCombine( // combine result supplyAsync(task3), // with result of task3 Integer::sum) // using summation .thenAccept(System.out::println); // print final result after execution

หากเราตรวจสอบว่า Java 8 จัดการกับสิ่งนี้อย่างไรเราจะเห็นว่าทั้งสามงานจะทำงานพร้อมกันแบบอะซิงโครนัส อย่างไรก็ตาม ภารกิจที่ 2 หากล้มเหลวโดยมีข้อยกเว้นผลลัพธ์สุดท้ายจะถูกคำนวณและพิมพ์สำเร็จ

JAVA 8 ASYNCHRONOUS PROGRAMMING with CompletableFuture

CompletableFuture ทำให้การสร้างงานแบบอะซิงโครนัสที่มีหลายขั้นตอนง่ายขึ้นมากและทำให้เรามีอินเทอร์เฟซที่ง่ายสำหรับการกำหนดสิ่งที่ควรดำเนินการเมื่อเสร็จสิ้นแต่ละขั้นตอน

Java Date and Time API

ตามที่ระบุไว้โดย Java’s การรับเข้าของตัวเอง :

ก่อนรีลีส Java SE 8 กลไกวันที่และเวลาของ Java ได้รับการจัดเตรียมโดย java.util.Date , java.util.Calendar และ java.util.TimeZone คลาสเช่นเดียวกับคลาสย่อยเช่น java.util.GregorianCalendar ชั้นเรียนเหล่านี้มีข้อบกพร่องหลายประการ ได้แก่

  • คลาสปฏิทินไม่ใช่ประเภทที่ปลอดภัย
  • เนื่องจากคลาสนั้นไม่แน่นอนจึงไม่สามารถใช้ในแอพพลิเคชั่นมัลติเธรดได้
  • ข้อบกพร่องในรหัสแอปพลิเคชันเป็นเรื่องปกติเนื่องจากจำนวนเดือนที่ผิดปกติและการขาดความปลอดภัยประเภท '

ในที่สุด Java 8 ก็แก้ปัญหาที่มีมายาวนานเหล่านี้ด้วย java.time แพ็คเกจซึ่งมีคลาสสำหรับการทำงานกับวันที่และเวลา ทั้งหมดนี้ไม่เปลี่ยนรูปและมี API คล้ายกับเฟรมเวิร์กยอดนิยม Joda-Time ซึ่งนักพัฒนา Java เกือบทั้งหมดใช้ในแอปพลิเคชันของตนแทนที่จะเป็น Date, Calendar และ TimeZone

นี่คือคลาสที่มีประโยชน์บางส่วนในแพ็คเกจนี้:

  • Clock - นาฬิกาบอกเวลาปัจจุบันรวมถึงปัจจุบันวันที่และเวลาพร้อมเขตเวลา
  • Duration และ Period - ระยะเวลา Duration ใช้ค่าตามเวลาเช่น“ 76.8 วินาทีและ Period ตามวันที่เช่น“ 4 ปี 6 เดือนและ 12 วัน”
  • Instant - จุดในเวลาทันทีในหลายรูปแบบ
  • LocalDate , LocalDateTime , LocalTime , Year , YearMonth - วันที่เวลาปีเดือนหรือบางอย่างรวมกันโดยไม่มีเขตเวลาในระบบปฏิทิน ISO-8601
  • OffsetDateTime , OffsetTime - วันที่ - เวลาที่มีค่าชดเชยจาก UTC / Greenwich ในระบบปฏิทิน ISO-8601 เช่น“ 2015-08-29T14: 15: 30 + 01: 00 น.”
  • ZonedDateTime - วันที่ - เวลาพร้อมเขตเวลาที่เกี่ยวข้องในระบบปฏิทิน ISO-8601 เช่น“ 1986-08-29T10: 15: 30 + 01: 00 ยุโรป / ปารีส”

Java 8 TIME FIRE

บางครั้งเราต้องหาวันที่สัมพันธ์กันเช่น“ วันอังคารแรกของเดือน” สำหรับกรณีเหล่านี้ java.time จัดให้มีชั้นเรียนพิเศษ TemporalAdjuster . TemporalAdjuster คลาสประกอบด้วยชุดตัวปรับมาตรฐานซึ่งมีให้เป็นวิธีการแบบคงที่ สิ่งเหล่านี้ช่วยให้เราสามารถ:

  • ค้นหาวันแรกหรือวันสุดท้ายของเดือน
  • ค้นหาวันแรกหรือวันสุดท้ายของเดือนถัดไปหรือเดือนก่อนหน้า
  • ค้นหาวันแรกหรือวันสุดท้ายของปี
  • ค้นหาวันแรกหรือวันสุดท้ายของปีถัดไปหรือปีก่อนหน้า
  • ค้นหาวันแรกหรือวันสุดท้ายของสัปดาห์ภายใน 1 เดือนเช่น“ วันพุธแรกของเดือนมิถุนายน”
  • ค้นหาวันถัดไปหรือก่อนหน้าของสัปดาห์เช่น“ วันพฤหัสบดีหน้า”

นี่คือตัวอย่างสั้น ๆ ในการรับวันอังคารแรกของเดือน:

LocalDate getFirstTuesday(int year, int month) { return LocalDate.of(year, month, 1) .with(TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY)); } ยังคงใช้ Java 7 อยู่หรือไม่? รับกับโปรแกรม! # Java8 ทวีต

Java 8 ในสรุป

อย่างที่เราเห็น Java 8 เป็นแพลตฟอร์ม Java รุ่นแรก มีการเปลี่ยนแปลงภาษาจำนวนมากโดยเฉพาะอย่างยิ่งเมื่อมีการเปิดตัว lambdas ซึ่งแสดงถึงการย้ายเพื่อนำความสามารถในการเขียนโปรแกรมที่ใช้งานได้มากขึ้นมาสู่ Java Stream API เป็นตัวอย่างที่ดีว่า lambdas สามารถเปลี่ยนวิธีการทำงานกับเครื่องมือ Java มาตรฐานที่เราคุ้นเคยอยู่แล้วได้อย่างไร

นอกจากนี้ Java 8 ยังนำเสนอคุณสมบัติใหม่ ๆ สำหรับการทำงานกับไฟล์ การเขียนโปรแกรมแบบอะซิงโครนัส และการยกเครื่องเครื่องมือวันที่และเวลาที่จำเป็นมาก

การเปลี่ยนแปลงเหล่านี้ถือเป็นการก้าวไปข้างหน้าครั้งใหญ่สำหรับภาษา Java การพัฒนา Java น่าสนใจและมีประสิทธิภาพมากขึ้น

วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ

การออกแบบ Ui

วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ
Python Multithreading และ Multiprocessing Tutorial

Python Multithreading และ Multiprocessing Tutorial

แบ็คเอนด์

โพสต์ยอดนิยม
ตลาด Crowdfunding Equity ของสหรัฐมีการเติบโตขึ้นตามความคาดหวังหรือไม่?
ตลาด Crowdfunding Equity ของสหรัฐมีการเติบโตขึ้นตามความคาดหวังหรือไม่?
คู่มือสำคัญสำหรับ Qmake
คู่มือสำคัญสำหรับ Qmake
หลักการออกแบบ Mobile UX
หลักการออกแบบ Mobile UX
MIDI Tutorial: การสร้างแอปพลิเคชั่นเสียงบนเบราว์เซอร์ที่ควบคุมโดยฮาร์ดแวร์ MIDI
MIDI Tutorial: การสร้างแอปพลิเคชั่นเสียงบนเบราว์เซอร์ที่ควบคุมโดยฮาร์ดแวร์ MIDI
Init.js: คำแนะนำเกี่ยวกับสาเหตุและวิธีการใช้ JavaScript แบบ Full-Stack
Init.js: คำแนะนำเกี่ยวกับสาเหตุและวิธีการใช้ JavaScript แบบ Full-Stack
 
Splash of EarlGrey - UI การทดสอบแอพ ApeeScape Talent
Splash of EarlGrey - UI การทดสอบแอพ ApeeScape Talent
จาก Node.js ไปจนถึงการจ่ายภาษีอิสระของคุณ: บทสัมภาษณ์กับ Developer ที่ประสบความสำเร็จ
จาก Node.js ไปจนถึงการจ่ายภาษีอิสระของคุณ: บทสัมภาษณ์กับ Developer ที่ประสบความสำเร็จ
ขายธุรกิจของคุณ? หยุดทิ้งเงินไว้บนโต๊ะ
ขายธุรกิจของคุณ? หยุดทิ้งเงินไว้บนโต๊ะ
บทช่วยสอนเกี่ยวกับส่วนขยายแอป iOS 8
บทช่วยสอนเกี่ยวกับส่วนขยายแอป iOS 8
ผู้จัดการการเติบโต
ผู้จัดการการเติบโต
โพสต์ยอดนิยม
  • สถาปัตยกรรมสารสนเทศคืออะไร?
  • google doks สำหรับรายละเอียดบัตรเครดิต 2018
  • s vs c corp llc
  • ราง 4 กับราง 5
  • วิธีแฮ็คบัตรเครดิตของใครบางคนออนไลน์
  • โดยทั่วไปแล้วเว็บแอปบนมือถือจะถูกสร้างขึ้นโดยใช้ html5 และ java
หมวดหมู่
  • การจัดการโครงการ
  • การเพิ่มขึ้นของระยะไกล
  • การบริหารโครงการ
  • เครื่องมือและบทช่วยสอน
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt