"لا يزال جافا غير ميت - وبدأ الناس في معرفة ذلك".
سيستخدم هذا البرنامج التعليمي رمزًا مشروحًا بسيطًا لوصف ميزات جديدة ، ولن ترى نصًا رائعًا.
1. الطريقة الافتراضية للواجهة
يسمح لنا Java 8 بإضافة تطبيق غير متجانس إلى الواجهة ، ما عليك سوى استخدام الكلمة الرئيسية الافتراضية.
نسخة الكود كما يلي:
صيغة الواجهة {
حساب مزدوج (int a) ؛
Double SQRT (int a) {
إرجاع Math.Sqrt (a) ؛
}
}
بالإضافة إلى وجود طريقة محسوبة ، تحدد واجهة الصيغة أيضًا طريقة SQRT.
نسخة الكود كما يلي:
صيغة الصيغة = Formula () {
@تجاوز
حساب مزدوج عام (int a) {
إرجاع sqrt (a * 100) ؛
}
} ؛
Formula.calculate (100) ؛
Formula.Sqrt (16) ؛
يتم تنفيذ الصيغة في المقالة كمثيل لفئة مجهولة. في القسم التالي ، سنرى نهجًا أبسط لتنفيذ واجهة طريقة واحدة.
ملاحظة المترجم: لا يوجد سوى ميراث واحد في Java. في لغات أخرى ، تسمى طريقة وجود فئة رمزًا آخر قابل لإعادة الاستخدام في نفس الوقت يسمى Mixin. هذا الخاص الجديد Java 8 الخاص هو أقرب إلى سمة سكالا من منظور تنفيذ التحويل البرمجي. هناك أيضًا مفهوم يسمى طريقة التمديد في C#، والذي يسمح بتمديد الأنواع الموجودة ، وهو ما يختلف بشكل دلالي عن هذا في Java 8.
2. تعبيرات لامدا
أولاً ، دعونا نلقي نظرة على كيفية ترتيب السلاسل في النسخة القديمة من Java:
نسخة الكود كما يلي:
قائمة <Tring> names = arrays.aslist ("Peter" ، "Anna" ، "Mike" ، "Xenia") ؛
collections.sort (أسماء ، مقارن جديد <string> () {
@تجاوز
Public Int Compare (String A ، String B) {
إرجاع b.compareto (a) ؛
}
}) ؛
ما عليك سوى تمرير كائن قائمة ومقارنة بمجموعة الأساليب الثابتة. عادة ما يتم ذلك لإنشاء كائن مقارن مجهول ونقله إلى طريقة الفرز.
في Java 8 ، لا تحتاج إلى استخدام هذه الطريقة التقليدية للكائنات المجهولة.
نسخة الكود كما يلي:
collections.sort (الأسماء ، (السلسلة A ، السلسلة B) -> {
إرجاع b.compareto (a) ؛
}) ؛
انظر ، يصبح الرمز أكثر تقسيمًا وقابلة للقراءة ، ولكن يمكن كتابته بالفعل أقصر:
نسخة الكود كما يلي:
collections.sort (الأسماء ، (السلسلة A ، السلسلة B) -> b.compareto (a)) ؛
بالنسبة لجسم الوظيفة مع سطر واحد فقط من التعليمات البرمجية ، يمكنك إزالة الأقواس {} وإرجاع الكلمات الرئيسية ، ولكن يمكنك كتابتها أقصر:
نسخة الكود كما يلي:
collections.sort (names ، (a ، b) -> b.compareto (a)) ؛
يمكن لمرجم Java استنتاج أنواع المعلمات تلقائيًا ، لذلك لا يتعين عليك كتابة النوع مرة أخرى. بعد ذلك ، دعونا نرى ما يمكن أن تفعله تعبيرات Lambda الأكثر ملاءمة:
3. الواجهة الوظيفية
كيف يتم تمثيل تعبيرات Lambda في نظام نوع Java؟ كل تعبير lambda يتوافق مع نوع ، وعادة ما يكون نوع واجهة. تشير "الواجهة الوظيفية" إلى واجهة تحتوي فقط على طريقة مجردة ، وسيتم مطابقة كل تعبير Lambda لهذا النوع مع هذه الطريقة التجريدية. لأن الطريقة الافتراضية ليست طريقة مجردة ، يمكنك أيضًا إضافة طرق افتراضية إلى الواجهة الوظيفية الخاصة بك.
يمكننا التعامل مع تعبيرات Lambda كأي نوع من الواجهة التي تحتوي على طريقة مجردة واحدة فقط للتأكد من أن الواجهة الخاصة بك يجب أن تفي بهذا المطلب. التعليقات التوضيحية ، سيجد المترجم أن الواجهة التي حددتها مع هذا التعليق الشرح.
الأمثلة على النحو التالي:
نسخة الكود كما يلي:
functionalInterface
محول الواجهة <f ، t> {
T تحويل (F من) ؛
}
المحول <string ، integer> converter = (from) -> integer.valueof (from) ؛
integer تحويل = converter.convert ("123") ؛
System.out.println (تم تحويله) ؛
تجدر الإشارة إلى أنه إذا لم يتم تحديد functionalInterface ، فإن الكود أعلاه صحيح أيضًا.
تعرّف المترجمات على تعبيرات Lambda إلى واجهة طريقة واحدة. الوظيفة المترجمة.
4. الطريقة ومرجع المنشئ
يمكن أيضًا تمثيل الرمز في القسم السابق من خلال مراجع الطريقة الثابتة:
نسخة الكود كما يلي:
المحول <string ، integer> converter = integer :: valueof ؛
integer تحويل = converter.convert ("123") ؛
System.out.println (تم تحويله) ؛
يسمح لك Java 8 باستخدام الكلمة الرئيسية لتمرير طريقة أو مرجع مُنشئ.
نسخة الكود كما يلي:
المحول = شيء :: startswith ؛
string ecoundted = converter.convert ("java") ؛
System.out.println (تم تحويله) ؛
دعنا نلقي نظرة على كيفية الرجوع إلى المُنشئين باستخدام الكلمة الأساسية:
نسخة الكود كما يلي:
فئة شخص {
سلسلة FirstName ؛
سلسلة العائلة ؛
شخص() {}
الشخص (سلسلة FirstName ، string lastName) {
this.firstName = firstName ؛
this.lastname = lastName ؛
}
}
بعد ذلك ، نحدد واجهة مصنع كائن لإنشاء كائنات شخص:
نسخة الكود كما يلي:
واجهة personfactory <p يمتد الشخص> {
P إنشاء (سلسلة FirstName ، string lastName) ؛
}
هنا نستخدم إشارات المنشئ لربطها بدلاً من تنفيذ مصنع كامل:
نسخة الكود كما يلي:
personfactory <Person> personfactory = شخص :: جديد ؛
الشخص = personfactory.create ("Peter" ، "Parker") ؛
نحتاج فقط إلى استخدام الشخص :: الجديد للحصول على مرجع إلى مُنشئ فئة الشخص.
5. نطاق لامدا
تشبه طريقة الوصول إلى النطاقات الخارجية في تعبيرات Lambda تلك الموجودة في الإصدارات القديمة من الأشياء المجهولة. يمكنك الوصول مباشرة إلى المتغيرات المحلية الخارجية التي تحمل علامة أو حقول ومتغيرات ثابتة للمثال.
6. الوصول إلى المتغيرات المحلية
يمكننا الوصول إلى المتغيرات المحلية الخارجية مباشرة في تعبيرات لامدا:
نسخة الكود كما يلي:
النهائي int num = 1 ؛
المحول <integer ، string> stringConverter =
(من) -> string.valueof (من + num) ؛
StringConverter.convert (2) ؛
ولكن على عكس الكائنات المجهولة ، يمكن الإعلان عن NUM المتغير هنا على أنه نهائي دون إعلانه على أنه نهائي ، والرمز صحيح أيضًا:
نسخة الكود كما يلي:
int num = 1 ؛
المحول <integer ، string> stringConverter =
(من) -> string.valueof (من + num) ؛
StringConverter.convert (2) ؛
ومع ذلك ، يجب عدم تعديل NUM هنا من خلال الكود اللاحق (أي ، ضمنيًا له دلالات نهائية) ، على سبيل المثال ، لا يمكن تجميع ما يلي:
نسخة الكود كما يلي:
int num = 1 ؛
المحول <integer ، string> stringConverter =
(من) -> string.valueof (من + num) ؛
num = 3 ؛
محاولة تعديل NUM في تعبيرات Lambda غير مسموح بها أيضًا.
7. حقول كائن الوصول والمتغيرات الثابتة
على عكس المتغيرات المحلية ، يمكن قراءة الحقول والمتغيرات الثابتة داخل Lambda. هذا السلوك يتسق مع الأشياء المجهولة:
انسخ الرمز كما يلي: الفئة lambda4 {
ثابت int outerstaticnum.
int outernum.
void testscopes () {
المحول <integer ، string> stringConverter1 = (من) -> {
Outernum = 23 ؛
إرجاع string.valueof (من) ؛
} ؛
المحول <integer ، string> stringConverter2 = (من) -> {
OuterStaticNum = 72 ؛
إرجاع string.valueof (من) ؛
} ؛
}
}
8. الطريقة الافتراضية للوصول إلى الواجهة
تذكر مثال الصيغة في القسم الأول.
لا يمكن الوصول إلى الطريقة الافتراضية في تعبير Lambda ، ولن يتم تجميع الكود التالي:
نسخة الكود كما يلي:
صيغة الصيغة = (أ) -> sqrt (a * 100) ؛
واجهات وظيفية مدمجة
يحتوي API JDK 1.8 على العديد من الواجهات الوظيفية المدمجة ، مثل المقارنة أو الواجهات القابلة للتشغيل بشكل شائع في Java القديم ، وقد أضافت هذه الواجهات التعليق التوضيحي FunctionalInterface لاستخدامه في Lambdas.
توفر Java 8 API أيضًا العديد من الواجهات الوظيفية الجديدة لجعل العمل أكثر ملاءمة.
واجهة مسند
تحتوي الواجهة المسند على معلمة واحدة فقط ، والتي تُرجع نوع Boolean. تحتوي هذه الواجهة على عدد من الطرق الافتراضية لدمج المسند في منطقات معقدة أخرى (مثل: مقابل ، أو غير):
نسخة الكود كما يلي:
المسند <String> estericy = (s) -> s.length ()> 0 ؛
Predict.test ("foo") ؛
التنبؤ. negate ()
المسند <Ololean> nonnull = objects :: nonnull ؛
المسند <Ololean> isNull = objects :: isnull ؛
مسند <string> isEmpty = String :: isEmpty ؛
المسند <string> isnotempty = isEmpty.Negate () ؛
واجهة وظيفة
تحتوي واجهة الوظيفة على معلمة وتُرجع نتيجة ، وتأتي مع بعض الطرق الافتراضية (Compose ، and then) التي يمكن دمجها مع وظائف أخرى:
نسخة الكود كما يلي:
دالة <string ، integer> toInteger = integer :: valueof ؛
دالة <string ، string> backtoString = tointeger.andthen (String :: valueof) ؛
backtostring.apply ("123") ؛
واجهة المورد
تقوم واجهة المورد بإرجاع قيمة من أي نوع.
نسخة الكود كما يلي:
المورد <Person> profonsupplier = شخص :: جديد ؛
profonsupplier.get () ؛
واجهة المستهلك
تمثل واجهة المستهلك العملية التي تم تنفيذها على معلمة واحدة.
نسخة الكود كما يلي:
المستهلك <Person> GEERTER = (P) -> System.out.println ("Hello ،" + P.FirstName) ؛
GEERTER.ACCEPT (شخص جديد ("Luke" ، "Skywalker")) ؛
واجهة المقارنة
المقارنة عبارة عن واجهة كلاسيكية في Java القديمة ، وقد أضافت Java 8 مجموعة متنوعة من الطرق الافتراضية على ذلك:
نسخة الكود كما يلي:
المقارنة <profer> المقارنة = (P1 ، p2) -> p1.firstname.compareto (p2.firstName) ؛
الشخص p1 = شخص جديد ("جون" ، "doe") ؛
الشخص p2 = شخص جديد ("أليس" ، "بلاد العجائب") ؛
Comparator.compare (p1 ، p2) ؛
المقارنة
واجهة اختيارية
الاختياري ليس دالة ولكن هذا هو نوع من الاستثناءات من Nullpointerexce
يتم تعريف اختياري على أنه حاوية بسيطة قد تكون قيمتها فارغة أم لا. قبل Java 8 ، يجب أن تعيد الوظيفة عمومًا كائنًا غير فارغ ، ولكن في بعض الأحيان قد تعود خالية.
نسخة الكود كما يلي:
اختياري <string> اختياري = اختياري. من ("bam") ؛
اختياري
اختياري () ؛
اختياري.
اختياري.
دفق واجهة
يمثل java.util.stream سلسلة من العمليات التي يمكن تطبيقها على مجموعة من العناصر في وقت واحد. تنقسم عمليات الدفق إلى نوعين: العمليات المتوسطة أو العمليات النهائية. يتطلب إنشاء دفق تحديد مصدر بيانات ، مثل الفئة الفرعية من java.util.collection أو قائمة أو مجموعة ، والتي لا تدعمها الخريطة. يمكن تنفيذ عمليات الدفق تسلسليًا أو بالتوازي.
أولاً ، دعنا نرى كيف يتم استخدام الدفق أولاً.
نسخة الكود كما يلي:
قائمة <Tring> StringCollection = new ArrayList <> () ؛
StringCollection.add ("DDD2") ؛
StringCollection.add ("AAA2") ؛
StringCollection.add ("BBB1") ؛
StringCollection.add ("AAA1") ؛
StringCollection.add ("BBB3") ؛
StringCollection.add ("CCC") ؛
StringCollection.add ("BBB2") ؛
StringCollection.add ("DDD1") ؛
Java 8 يمتد فئة التجميع ، ويمكنه إنشاء دفق من خلال collection.stream () أو collection.parallelstream (). ستشرح الأقسام التالية عمليات الدفق الشائعة الاستخدام بالتفصيل:
مرشح مرشح
يتم ترشيح التصفية من خلال واجهة مسند وعناصر فقط تفي بالمعايير يتم الاحتفاظ بها. يتطلب Foreach وظيفة لتنفيذ العناصر المصفاة بالتسلسل. Foreach هي عملية نهائية ، لذلك لا يمكننا إجراء عمليات دفق أخرى بعد foreach.
نسخة الكود كما يلي:
StringCollection
.تدفق()
.filter ((S) -> S.Startswith ("A"))
. for (system.out :: println) ؛
// "AAA2" ، "AAA1"
فرز الفرز
الفرز عبارة عن عملية وسيطة ، ويتم إرجاع الدفق الذي تم إرجاعه بعد الفرز. إذا لم تحدد مقارنة مخصصة ، فسيتم استخدام الفرز الافتراضي.
نسخة الكود كما يلي:
StringCollection
.تدفق()
.sorted ()
.filter ((S) -> S.Startswith ("A"))
. for (system.out :: println) ؛
// "AAA1" ، "AAA2"
تجدر الإشارة إلى أن الفرز ينشئ دفقًا مرتبة فقط ، ولن يؤثر على مصدر البيانات الأصلي.
نسخة الكود كما يلي:
System.out.println (StringCollection) ؛
// DDD2 ، AAA2 ، BBB1 ، AAA1 ، BBB3 ، CCC ، BBB2 ، DDD1
رسم الخرائط
تقوم خريطة التشغيل الوسيطة بتحويل عناصر إلى كائنات إضافية بالتسلسل وفقًا لواجهة الوظيفة المحددة. يمكنك أيضًا استخدام الخريطة لتحويل الكائنات إلى أنواع أخرى.
نسخة الكود كما يلي:
StringCollection
.تدفق()
.map (سلسلة :: touppercase)
.
. for (system.out :: println) ؛
// "DDD2" ، "DDD1" ، "CCC" ، "BBB3" ، "BBB2" ، "AAA2" ، "AAA1"
مباراة
يوفر Stream مجموعة متنوعة من عمليات المطابقة ، مما يتيح اكتشاف ما إذا كان مسند محدد يتطابق مع الدفق بأكمله. جميع العمليات المطابقة هي العمليات النهائية وإرجاع قيمة نوع Boolean.
نسخة الكود كما يلي:
منطقية anystartswitha =
StringCollection
.تدفق()
.anymatch ((S) -> S.Startswith ("A")) ؛
System.out.println (anystartswitha) ؛
منطقية allstartswitha =
StringCollection
.تدفق()
.lallmatch ((S) -> S.Startswith ("A")) ؛
system.out.println (allstartswitha) ؛
منطقية nonstswithz =
StringCollection
.تدفق()
.nonematch ((S) -> S.Startswith ("Z")) ؛
System.out.println (nonstartswithz) ؛
عدد
يعد العد عملية نهائية ، تُرجع عدد العناصر في الدفق ، ونوع قيمة الإرجاع طويل.
نسخة الكود كما يلي:
startswithb طويلة =
StringCollection
.تدفق()
.filter ((S) -> S.Startswith ("B"))
.عدد()؛
System.out.println (StartSwithb) ؛
تقليل اللوائح
هذه عملية نهائية ، تسمح بتعريف عناصر متعددة في الدفق كعنصر واحد من خلال الوظيفة المحددة ، ويتم تمثيل نتيجة الأهلية بالواجهة الاختيارية:
نسخة الكود كما يلي:
اختياري <string> مخفض =
StringCollection
.تدفق()
.sorted ()
.Reduce ((S1 ، S2) -> S1 + "#" + S2) ؛
lowuced.Ifpresent (System.out :: println) ؛
// "AAA1#AAA2#BB1#BB2#BB3#CCC#DDD1#DDD2"
تدفقات موازية
كما ذكرنا سابقًا ، يحتوي Stream على نوعين: يتم الانتهاء من العمليات المسلسل والمتوازي.
يوضح المثال التالي كيفية تحسين الأداء من خلال الدفق المتوازي:
أولاً ، نقوم بإنشاء جدول كبير بدون عناصر مكررة:
نسخة الكود كما يلي:
int max = 1000000 ؛
قائمة <Tring> القيم = ArrayList New ArrayList <> (Max) ؛
لـ (int i = 0 ؛ i <max ؛ i ++) {
uuid uuid = uuid.randomuuid () ؛
القيم. add (uuid.toString ()) ؛
}
ثم نحسب المدة التي يستغرقها لفرز هذا الدفق.
النوع التسلسلي:
نسخة الكود كما يلي:
طويل T0 = system.nanotime () ؛
العد الطويل = القيم.
system.out.println (count) ؛
طويل T1 = system.nanotime () ؛
long millis = timeUnit.nanoseconds.tomillis (t1 - t0) ؛
System.out.println (string.format ("sequential sort take: ٪ d ms" ، millis)) ؛
// الوقت التسلسلي: 899 مللي ثانية
فرز متوازي:
نسخة الكود كما يلي:
طويل T0 = system.nanotime () ؛
العد الطويل = القيم. parallelstream (). sorted (). count () ؛
system.out.println (count) ؛
طويل T1 = system.nanotime () ؛
long millis = timeUnit.nanoseconds.tomillis (t1 - t0) ؛
System.out.println (string.format ("take take take: ٪ d ms" ، millis)) ؛
// الفرز الموازي يستغرق وقتًا: 472 مللي ثانية
الرموز المذكورة أعلاه هي نفسها تقريبًا ، لكن النسخة المتوازية تصل إلى 50 ٪.
رسم خريطة
كما ذكرنا سابقًا ، لا يدعم نوع الخريطة الدفق ، لكن الخريطة توفر بعض الطرق الجديدة والمفيدة للتعامل مع بعض المهام اليومية.
نسخة الكود كما يلي:
الخريطة <integer ، string> map = new HashMap <> () ؛
لـ (int i = 0 ؛ i <10 ؛ i ++) {
map.putifabsent (i ، "val" + i) ؛
}
map.foreach ((id ، val) -> system.out.println (val)) ؛
الرمز أعلاه سهل الفهم.
يوضح المثال التالي وظائف مفيدة أخرى على الخريطة:
نسخة الكود كما يلي:
map.computeifpresent (3 ، (num ، val) -> val + num) ؛
map.get (3) ؛
map.computeifpresent (9 ، (num ، val) -> null) ؛
map.containskey (9) ؛
map.computeifabsent (23 ، num -> "val" + num) ؛
map.containskey (23) ؛
map.computeifabsent (3 ، num -> "bam") ؛
map.get (3) ؛
بعد ذلك ، أظهر كيفية حذف عنصر في الخريطة التي تتطابق مع جميع المفاتيح:
نسخة الكود كما يلي:
map.remove (3 ، "Val3") ؛
map.get (3) ؛
map.remove (3 ، "Val33") ؛
map.get (3) ؛
طريقة أخرى مفيدة:
نسخة الكود كما يلي:
map.getordefault (42 ، "لم يتم العثور عليها") ؛
من السهل أيضًا دمج عناصر الخريطة:
نسخة الكود كما يلي:
Map.merge (9 ، "Val9" ، (value ، newValue) -> value.concat (newValue)) ؛
map.get (9) ؛
map.merge (9 ، "concat" ، (value ، newValue) -> value.concat (newValue)) ؛
map.get (9) ؛
ما يفعله دمج هو إدراج إذا لم يكن اسم المفتاح موجودًا ، وإلا قم بدمج القيمة المقابلة للمفتاح الأصلي وإعادة إدخالها في الخريطة.
9. تاريخ API
يحتوي Java 8 على مجموعة جديدة من APIs و APIs للتاريخ ضمن حزمة Java.time. يشبه API الجديد API مكتبة Joda Open Open ، ولكن ليس بالضبط.
الساعة
توفر فئة الساعة طريقة للوصول إلى التاريخ والوقت الحاليين. يمكن أيضًا تمثيل نقطة محددة من خلال الفئة الفورية ، والتي يمكن استخدامها أيضًا لإنشاء كائنات java.util.date القديمة.
نسخة الكود كما يلي:
ساعة على مدار الساعة = clock.systemdefaultzone () ؛
millis طويلة = clock.millis () ؛
لحظة = clock.instant () ؛
Date LegacyDate = Date.from (Fore) ؛
المنطقة الزمنية المنطقة الزمنية
في واجهة برمجة التطبيقات الجديدة ، يتم تمثيل المنطقة الزمنية بواسطة ZoneID. يمكن الحصول على المنطقة الزمنية بسهولة باستخدام الطريقة الثابتة لـ. تحدد المنطقة الزمنية الفرق الزمني لوقت UTS ، وهو أمر مهم للغاية عند التحويل بين كائن النقطة الزمنية الفورية وكائن التاريخ المحلي.
نسخة الكود كما يلي:
System.out.println (ZoneId.getAvailableable ()) ؛
// يطبع جميع معرفات المنطقة الزمنية المتاحة
ZoneId Zone1 = ZoneId.of ("Europe/Berlin") ؛
ZoneId Zone2 = ZoneId.of ("البرازيل/الشرق") ؛
System.out.println (Zone1.GetRules ()) ؛
System.out.println (Zone2.GetRules ()) ؛
// Zonerules [CurrentStandardOffset =+01: 00]
// Zonerules [CurrentStandardOffset = -03: 00]
التوقيت المحلي المحلي
يحدد LocalTime وقتًا بدون معلومات المنطقة الزمنية ، مثل 10 مساءً ، أو 17:30:15. المثال التالي ينشئ مرتين محليتين باستخدام المنطقة الزمنية التي تم إنشاؤها بواسطة الكود السابق. ثم تتم مقارنة الوقت ويتم حساب الفرق الزمني بين المرتين في ساعات ودقائق:
نسخة الكود كما يلي:
localtime now1 = localtime.now (Zone1) ؛
localtime now2 = localtime.now (Zone2) ؛
System.out.println (now1.isbefore (now2)) ؛
ساعات طويلة بين = chronounit.hours.between (now1 ، now2) ؛
دقائق طويلة = chronounit.minutes.between (now1 ، now2) ؛
System.out.println (HOURSBENTEN) ؛
System.out.println (minittersen) ؛
يوفر LocalTime مجموعة متنوعة من أساليب المصنع لتبسيط إنشاء الكائنات ، بما في ذلك سلاسل وقت التحليل.
نسخة الكود كما يلي:
localtime في وقت متأخر = localtime.of (23 ، 59 ، 59) ؛
System.out.println (متأخرا) ؛
dateTimeFormatter GermanFormatter =
DateTimeFormatter
.OflocalizedTime (FormatStyle.Short)
. withlocale (locale.german) ؛
LocalTime Leettime = localtime.parse ("13:37" ، GermanFormatter) ؛
System.out.println (Leettime) ؛
التاريخ المحلي المحلي
يمثل LocalDate تاريخًا دقيقًا ، مثل 2014-03-11. قيمة هذا الكائن غير قابلة للتغيير وهي في الأساس نفس قيمة الوقت المحلي. يوضح المثال التالي كيفية إضافة/القمر/سنة إلى كائن تاريخ. لاحظ أيضًا أن هذه الكائنات غير قابلة للتغيير ، وأن العملية تُرجع مثيلًا جديدًا.
نسخة الكود كما يلي:
LocalDate اليوم = localDate.Now () ؛
LocalDate غدًا = اليوم.
localdate أمس = غدا. minusdays (2) ؛
localdate inferenday = localdate.of (2014 ، month.july ، 4) ؛
dayofweek dayofweek = ependenday.getdayofweek () ؛
System.out.println (DayOfWeek) ؛
يعد تحليل نوع LocalDate من السلسلة أمرًا بسيطًا مثل تحليل الوقت المحلي:
نسخة الكود كما يلي:
dateTimeFormatter GermanFormatter =
DateTimeFormatter
.oflocalizeddate (formatstyle.medium)
. withlocale (locale.german) ؛
LocalDate Xmas = localDate.Parse ("24.12.2014" ، GermanFormatter) ؛
System.out.println (XMAS) ؛
محلي DateTime المحلي
يمثل LocalDateTime الوقت والتاريخ ، وهو ما يعادل دمج محتويات القسمين الأولين في كائن واحد. LocalDateTime ، مثل LocalTime و LocalDate ، كلاهما غير قابل للتغيير. يوفر LocalDateTime بعض الطرق للوصول إلى حقول محددة.
نسخة الكود كما يلي:
LocalDateTime Sylvester = localDateTime.of (2014 ، month. December ، 31 ، 23 ، 59 ، 59) ؛
dayofweek dayofweek = sylvester.getdayofweek () ؛
System.out.println (DayOfWeek) ؛
شهر الشهر = sylvester.getMonth () ؛
System.out.println (شهر) ؛
long minuteOfday = sylvester.getlong (chronofield.minute_of_day) ؛
System.out.println (MinuteOfday) ؛
ما عليك سوى إرفاق معلومات المنطقة الزمنية ويمكن تحويلها إلى كائن فوري من الوقت.
نسخة الكود كما يلي:
لحظة = سيلفستر
.atZone (Zoneid.SystemDefault ())
.toinstant () ؛
تاريخ LegacyDate = date.from (لحظة) ؛
System.out.println (LegacyDate) ؛
التنسيق المحلي هو نفس الوقت والتاريخ.
نسخة الكود كما يلي:
DateTimeFormatter formatter =
DateTimeFormatter
.ofpattern ("mmm dd ، yyyy - hh: mm") ؛
محلية محلية = localDateTime.parse ("03 نوفمبر ، 2014 - 07:13" ، formatter) ؛
سلسلة السلسلة = formatter.format (تحليل) ؛
System.out.println (سلسلة) ؛
على عكس java.text.numberformat ، فإن الإصدار الجديد من DateTimeFormatter غير قابل للتغيير ، لذلك فهو آمن مؤشر الترابط.
معلومات مفصلة عن تنسيق الوقت والتاريخ: http://download.java.net/jdk8/docs
10. ملاحظات التعليق
يتم دعم التعليقات التوضيحية المتعددة في Java 8. دعونا نلقي نظرة أولاً على مثال لفهم ما يعنيه.
أولاً ، حدد تعليقات تلميحات معبأة لوضع مجموعة محددة من التعليقات التوضيحية تلميح:
نسخة الكود كما يلي:
interface تلميحات {
تلميح [] القيمة () ؛
}
repeatable (تلميحات)
interface تلميح {
قيمة السلسلة () ؛
}
تتيح لنا Java 8 استخدام التعليقات التوضيحية لنفس النوع عدة مرات ، فقط قم بتسمية التعليق التوضيحي.
مثال 1: استخدم فئة Wrapper كحاوية لتخزين التعليقات التوضيحية المتعددة (الطريقة القديمة)
نسخة الكود كما يلي:
hints ({ @ @تلميح ("hint1") ، hint ("hint2")})
فئة شخص {}
مثال 2: استخدام التعليقات التوضيحية المتعددة (طريقة جديدة)
نسخة الكود كما يلي:
HINT ("Hint1")
hint ("Hint2")
فئة شخص {}
في المثال الثاني ، سيقوم برنامج التحويل البرمجي Java ضمنيًا بتحديد تعليقات HINTS لك.
نسخة الكود كما يلي:
تلميح تلميح = person.class.getAnnotation (hint.class) ؛
System.out.println (تلميح) ؛
تلميحات تلميحات 1 = person.class.getAnnotation (Hints.Class) ؛
System.out.println (Hints1.value (). الطول) ؛
تلميح [] HINTS2 = person.class.getAnnotationsByType (hint.class) ؛
System.out.println (Hints2.Length) ؛
حتى إذا لم نحدد التعليقات التوضيحية على فئة الشخص ، فلا يزال بإمكاننا الحصول على التعليقات التوضيحية من خلال getAnnotation (تلميحات).
بالإضافة إلى ذلك ، تمت إضافة تعليقات Java 8 إلى هدفين جديدين:
نسخة الكود كما يلي:
target ({elementType.type_parameter ، elementType.type_use})
interface myannotation {}
هذا كله يتعلق بالميزات الجديدة لـ Java 8 ، وهناك بالتأكيد المزيد من الميزات التي تنتظر اكتشافها. هناك العديد من الأشياء المفيدة في JDK 1.8 ، مثل المصفوفات. parallelsort و stampedlock و examblefuture.