بناء جملة جافا

مقتطف من كود جافا.

إن بناء جملة جافا هو مجموعة القواعد التي تحدد كيفية كتابة برنامج جافا وتفسيره.

يُستمد بناء الجملة في الغالب من لغتي C و C++ . على عكس C++، لا تحتوي Java على دوال أو متغيرات عامة، ولكنها تحتوي على أعضاء بيانات تُعتبر أيضًا متغيرات عامة . جميع التعليمات البرمجية تنتمي إلى فئات ، وجميع القيم عبارة عن كائنات . الاستثناء الوحيد هو أنواع البيانات الأولية ، التي لا تُعتبر كائنات لأسباب تتعلق بالأداء (مع أنه يمكن تحويلها تلقائيًا إلى كائنات والعكس صحيح عبر التحويل التلقائي ). تم حذف بعض الميزات، مثل تحميل المعاملات الزائد وأنواع بيانات الأعداد الصحيحة غير الموقعة ، لتبسيط اللغة وتجنب أخطاء البرمجة المحتملة.

تم توسيع بنية لغة جافا تدريجيًا عبر العديد من الإصدارات الرئيسية لـ JDK ، وهي تدعم الآن إمكانيات مثل البرمجة العامة والدوال المجهولة (القيم الحرفية للدوال، والتي تُسمى تعبيرات لامدا في جافا). ومنذ عام 2017، يتم إصدار نسخة جديدة من JDK مرتين سنويًا.

الأساسيات

برنامج "Hello, World!" المكتوب بلغة جافا هو كالتالي:

public class HelloWorld { public static void main ( String [] args ) { System . out . println ( "Hello World!" ); } }

منذ إصدار Java 25، أصبح من الممكن كتابة برنامج "Hello World" مبسط بدون فئة صريحة:

void main () { IO . println ( "Hello World!" ); }

المعرف

المعرّف هو اسم عنصر في الكود . توجد قواعد تسمية قياسية يجب اتباعها عند اختيار أسماء العناصر. المعرّفات في جافا حساسة لحالة الأحرف .

يمكن أن يحتوي المعرّف على ما يلي:

لا يمكن للمعرّف أن:

  • ابدأ برقم.
  • أن يكون مساوياً لكلمة محجوزة، أو قيمة فارغة، أو قيمة منطقية .

الكلمات المفتاحية

الكلمات المفتاحية

الكلمات التالية هي كلمات مفتاحية ولا يمكن استخدامها كمعرفات تحت أي ظرف من الظروف، ويبلغ عددها 47 كلمة.

  • abstract
  • assert
  • boolean
  • break
  • byte
  • case
  • catch
  • char
  • class
  • continue
  • default
  • do
  • double
  • else
  • enum
  • extends
  • final
  • finally
  • float
  • for
  • if
  • implements
  • import
  • instanceof
  • int
  • interface
  • long
  • native
  • new
  • package
  • private
  • protected
  • public
  • return
  • short
  • static
  • super
  • switch
  • synchronized
  • this
  • throw
  • throws
  • transient
  • try
  • void
  • volatile
  • while

المعرفات المحجوزة

الكلمات التالية هي كلمات مفتاحية سياقية، وهي مقيدة فقط في سياقات معينة، ويبلغ عددها 16 سياقًا.

  • exports
  • module
  • non-sealed
  • open
  • opens
  • permits
  • provides
  • record
  • requires
  • sealed
  • to
  • transitive
  • var
  • when
  • with
  • yield

الكلمات المحجوزة للقيم الحرفية

تشير الكلمات التالية إلى القيم الحرفية المستخدمة في اللغة، والتي يوجد منها 3.

  • true
  • false
  • null

غير مستخدم

الكلمات التالية محجوزة ككلمات مفتاحية، ولكن ليس لها حاليًا أي استخدام أو غرض، وعددها 4.

  • _
  • const
  • goto
  • strictfp

حرفيًا

الأعداد الصحيحة
ثنائي (تم تقديمه في Java SE 7)0b11110101 ( 0b متبوعًا برقم ثنائي)
ثماني0365 ( صفر متبوعًا برقم ثماني)
النظام الست عشري0xF5 ( 0x متبوعًا برقم سداسي عشري)
عشري245 (عدد عشري)
قيم الفاصلة العائمة
يطفو23.5F ، .5f ، 1.72E3F (كسر عشري مع مؤشر أس اختياري، متبوعًا بـ F )
0x.5FP0F ، 0x.5P-6f ( 0x متبوعًا بكسر سداسي عشري مع مؤشر أس إلزامي ولاحقة F )
مزدوج23.5D ، .5 ، 5 ، 1.72E3D (كسر عشري مع مؤشر أس اختياري، متبوعًا بـ D اختياري )
0x.5FP0 ، 0x.5P-6D ( 0x متبوعًا بكسر سداسي عشري مع مؤشر أس إلزامي ولاحقة اختيارية D )
الأحرف الحرفية
شخصية'a' ، 'Z' ، '\u0231' (حرف أو رمز هروب، محاط بعلامات اقتباس مفردة)
القيم المنطقية
منطقيصحيح ، خطأ
حرفي فارغ
مرجع فارغباطل
السلاسل النصية الحرفية
خيط"مرحباً بالعالم" (سلسلة من الأحرف ورموز الهروب محاطة بعلامات اقتباس مزدوجة)
رموز الهروب في السلاسل النصية
حرف يونيكود\u3876 ( \u متبوعًا بنقطة رمز يونيكود السداسي العشري حتى U+FFFF)
الهروب الثماني352 (رقم ثماني لا يتجاوز 377، مسبوق بشرطة مائلة عكسية)
تغذية السطر\n
إرجاع السطر\r
تغذية النموذج\f
رد فعل عكسي\\
اقتباس واحد\'
علامات اقتباس مزدوجة\"
فاتورة غير مدفوعة\t
مسافة للخلف\b

تكون القيم العددية الصحيحة من intالنوع الافتراضي ما لم longيتم تحديد النوع بإضافة لاحقة Lأو lامتداد إلى القيمة، على سبيل المثال 367L. منذ Java SE 7، أصبح من الممكن تضمين شرطات سفلية بين أرقام العدد لزيادة سهولة قراءته؛ على سبيل المثال، يمكن كتابة العدد 145608987 على النحو التالي: 145_608_987 .

المتغيرات

المتغيرات هي معرّفات مرتبطة بالقيم. يتم تعريفها بكتابة نوع المتغير واسمه، ويمكن تهيئتها اختيارياً في نفس العبارة عن طريق إسناد قيمة لها.

int count ; // تعريف متغير غير مهيأ باسم 'count'، من النوع 'int' count = 35 ; // تهيئة المتغير int count = 35 ; // تعريف المتغير وتهيئته في نفس الوقت

يمكن تعريف وتهيئات متغيرات متعددة من نفس النوع في عبارة واحدة باستخدام الفاصلة كفاصل.

int a , b ; // تعريف متغيرات متعددة من نفس النوع int a = 2 , b = 3 ; // تعريف وتهيئة متغيرات متعددة من نفس النوع

استنتاج النوع

منذ إصدار Java 10، أصبح من الممكن استنتاج أنواع المتغيرات تلقائيًا باستخدام var.

استيراد java.io.FileOutputStream ؛// سيكون للتدفق نوع FileOutputStream كما هو مستنتج من مُهيئه var stream = new FileOutputStream ( "file.txt" );// إعلان مكافئ بنوع صريح FileOutputStream stream = new FileOutputStream ( "file.txt" );

كتل التعليمات البرمجية

تشير الفواصل { و } إلى كتلة برمجية ونطاق جديد. أعضاء الفئة وجسم الدالة أمثلة على ما يمكن أن يوجد داخل هذه الأقواس في سياقات مختلفة.

داخل أجسام الأساليب، يمكن استخدام الأقواس لإنشاء نطاقات جديدة، كما يلي:

void doSomething () { int a ;{ int b ; a = 1 ; }a = 2 ; b = 3 ; // غير مسموح لأن المتغير b مُعلن في نطاق داخلي.. }

تعليقات

تحتوي لغة جافا على ثلاثة أنواع من التعليقات : التعليقات التقليدية ، وتعليقات نهاية السطر، وتعليقات التوثيق .

تبدأ التعليقات التقليدية، والمعروفة أيضًا بالتعليقات الكتلية، بـ /*وتنتهي بـ */، وقد تمتد على عدة أسطر. هذا النوع من التعليقات مشتق من لغتي C و C++.

/* هذا تعليق متعدد الأسطر. قد يشغل أكثر من سطر واحد. */

تبدأ التعليقات في نهاية السطر //وتمتد إلى نهاية السطر الحالي. هذا النوع من التعليقات موجود أيضًا في لغة C++ ولغة C الحديثة.

// هذا تعليق في نهاية السطر

تُعالج أداة Javadoc التعليقات الموجودة في ملفات المصدر لإنشاء التوثيق. هذا النوع من التعليقات مطابق للتعليقات التقليدية، باستثناء أنه يبدأ بـ /**ويتبع اصطلاحات محددة من قِبل أداة Javadoc. من الناحية التقنية، تُعد هذه التعليقات نوعًا خاصًا من التعليقات التقليدية، وهي غير مُحددة تحديدًا في مواصفات اللغة.

/** * هذا تعليق توثيقي. * * @author John Doe */

أنواع عالمية

يتم استيراد الفئات الموجودة في الحزمة java.lang(وليس الحزم الفرعية) ضمنيًا إلى كل برنامج، طالما لا توجد أنواع مستوردة صراحةً تحمل نفس الأسماء. ومن أهمها:

java.lang.System

java.lang.Systemتُعدّ هذه الفئة واحدة من أهم الفئات الأساسية في لغة جافا. وهي فئة مساعدة للتفاعل مع النظام، وتحتوي على مدخلات ومخرجات وتدفقات أخطاء قياسية، وخصائص النظام ومتغيرات البيئة، والوقت، وغير ذلك.

java.lang.Object

java.lang.Objectيُعدّ النوع الأعلى في لغة جافا . وهو ضمنيًا الفئة الأساسية لجميع الفئات التي لا تُصرّح عن أي فئة أصلية (وبالتالي، ترث جميع الفئات في جافا منه Object). يمكن تحويل جميع القيم إلى هذا النوع، مع العلم أن هذا يتطلب تحويل القيم الأولية إلى نوع آخر .

java.lang.Record

جميع السجلات ترث ضمنيًا من java.lang.Record. وبالتالي، فإن a record، على الرغم من معاملتها كـ a class، لا يمكنها أن ترث من أي فئة أخرى.

java.lang.Enum<E>

جميع الأنواع المُعدّدة (enums) في جافا ترث ضمنيًا من فئة أخرى java.lang.Enum<E>. لذا، enumعلى الرغم من أن النوع المُعدّد يُعامل كنوع مُعدّد ، إلا أنه لا يمكنه أن يرث من أي فئة أخرى. يتم تقييد classمُعامل النوع على أنه نوع مُعدّد .EEnum<EextendsEnum<E>>

java.lang.Class<T>

java.lang.Class<T>هي فئة تمثل عنصرًا classأو interfaceكائنًا في التطبيق أثناء التشغيل. لا يمكن إنشاؤها عبر إنشاء مثيل مباشر، بل يتم إنشاؤها بواسطة JVM عند اشتقاق فئة من بايتات .classملف . يمكن الحصول على قيمة حرفية للفئة من خلال استدعاء دالة X.classعلى هذه الفئة X. على سبيل المثال، String.classتُرجع الدالة Class<String>`. يمكن تمثيل فئة غير معروفة يتم نمذجتها على النحو التالي: Class<?>`(حيث ?يشير ` إلى حرف بدل ).`

بينما X.classيبدو أنه يصل إلى حقل باسم " class "، فإنه في الواقع لا يوجد حقل بهذا الاسم ؛ بل يقوم في الحقيقة بتنفيذ التعليمات التي تدفع قيمة ثابتة من مجموعة الثوابت الخاصة بوقت التشغيل للفئة إلى مكدس المعاملات. [ 1 ]ldc

java.lang.String

java.lang.Stringهو نوع السلسلة الأساسي في جافا. وهو غير قابل للتغيير . لا يُنفذ واجهة `for` Iterable<Character>، لذا لا يمكن تكراره في حلقة `for-each`، ولكن يمكن تحويله إلى `true` char[]. تتعامل بعض الطرق مع كل وحدة ترميز UTF-16 كسلسلة نصية، ولكن تتوفر أيضًا charطرق لتحويلها إلى سلسلة نصية int[]تُعتبر فعليًا UTF-32String . يُنفذ واجهة ` for` java.lang.CharSequence، لذا يمكن الوصول إلى عناصر السلسلة النصية باستخدام الطريقة `for` .charStringcharAt()

java.lang.Throwable

java.lang.Throwableهو النوع الأساسي لكل ما يمكن طرحه أو التقاطه باستخدام عبارات Java throwو catch. فئاته الفرعية المعروفة مباشرة هي java.lang.Error(للأخطاء الجسيمة التي لا يمكن إصلاحها) و java.lang.Exception(للاستثناءات التي قد تحدث بشكل طبيعي أثناء تنفيذ البرنامج).

java.lang.Error

java.lang.Errorهو النوع الأساسي لجميع فئات الأخطاء ويمتد منها Throwable. ويُستخدم للإشارة إلى الحالات التي لا ينبغي لتطبيق معقول أن يلتقطها.

java.lang.Exception

java.lang.Exceptionهو النوع الأساسي لجميع فئات الاستثناءات ويمتد منها Throwable. ويُستخدم للإشارة إلى الحالات التي قد يكون لدى تطبيق معقول سببٌ لمعالجتها.

java.lang.Math

java.lang.Mathهي فئة مساعدة تحتوي على وظائف رياضية وثوابت رياضية (مثل Math.sin()، Math.pow()، و Math.PI).

java.lang.IO

java.lang.IOهي فئة تم تقديمها في Java 25 (كانت موجودة سابقًا في java.io) java.io.IO. وهي تتيح الوصول بشكل أبسط إلى تدفقات الإدخال والإخراج القياسية عبر System.inو System.out.

البدائيون

لكل نوع بدائي فئة تغليف مرتبطة به (انظر الأنواع البدائية ).

هيكل البرنامج

تتكون تطبيقات جافا من مجموعات من الفئات. توجد الفئات في حزم، ولكن يمكن أيضًا تضمينها داخل فئات أخرى.

mainطريقة

يجب أن يحتوي كل تطبيق جافا على نقطة دخول. ينطبق هذا على تطبيقات الواجهة الرسومية وتطبيقات سطر الأوامر. نقطة الدخول هي الدالة main. يمكن أن يكون هناك أكثر من فئة تحتوي على mainدالة، ولكن يتم تعريف الفئة الرئيسية دائمًا خارجيًا (على سبيل المثال، في ملف البيان ). mainيجب تعريف الدالة مع الفئة الرئيسية public. يجب أن تكون الدالة من staticنوع `include` ويتم تمرير وسائط سطر الأوامر إليها كمصفوفة من السلاسل النصية. على عكس لغتي C++ أو C# ، لا تُرجع الدالة قيمة أبدًا، ويجب أن تُرجع `true` void. مع ذلك، يمكن تحديد رمز إرجاع لنظام التشغيل عن طريق استدعاء `return` System.exit().

public static void main ( String [] args ) { // ... }

الطرود

تُعدّ الحزم جزءًا من اسم الفئة، وتُستخدم لتجميع الكيانات المسماة و/أو تمييزها عن غيرها. ومن أغراض الحزم أيضًا تنظيم الوصول إلى التعليمات البرمجية باستخدام مُعدِّلات الوصول. على سبيل المثال، java.io.InputStreamيُعدّ اسم الفئة المؤهل بالكامل هو اسم الفئة InputStreamالموجودة في الحزمة java.io.

الحزمة هي في الأساس مساحة اسم . لا توجد تسلسلات هرمية للحزم، على الرغم من أن النقاط قد توحي بذلك. يمكن التحكم في إمكانية الوصول إلى الحزمة، سواءً من خارج المشروع أو من داخله، باستخدام الوحدات النمطية .

يتم تعريف الحزمة في بداية الملف بالتعريف packageالتالي:

package org.wikipedia.examples ;public class Foo { // ... }

يجب وضع الفئات التي تحمل publicالمُعدِّل في ملفات تحمل نفس الاسم والامتداد .java ، ووضعها في مجلدات فرعية تتوافق مع اسم الحزمة. سيكون مسار الفئة المذكورة أعلاه كما يلي: .org.wikipedia.examples.Fooorg/wikipedia/examples/Foo.java

الوحدات

تُستخدم البرمجة المعيارية (الوحدات) لتجميع الحزم والتحكم الدقيق في الحزم التي تنتمي إلى واجهة برمجة التطبيقات العامة. على عكس ملفات JAR ، تُعلن الوحدات صراحةً عن الوحدات التي تعتمد عليها، والحزم التي تُصدّرها. [ 2 ] تُحسّن إعلانات التبعية الصريحة سلامة الكود، من خلال تسهيل فهم التطبيقات الكبيرة والتبعيات بين مكونات البرمجيات.

يُوضع تعريف الوحدة في ملف باسم module-info.java في جذر تسلسل ملفات مصدر الوحدة. ويتحقق JDK من التبعيات والتفاعلات بين الوحدات أثناء الترجمة والتشغيل.

على سبيل المثال، يُعلن تعريف الوحدة التالي أن الوحدة org.wikipedia.barتعتمد على org.wikipedia.bazوحدة أخرى، وتُصدّر الحزم التالية: org.wikipedia.bar.alphaو org.wikipedia.bar.beta:

منظمة الوحدة النمطية ويكيبيديا . شريط { يتطلب المنظمة . ويكيبيديا . باز ؛exports org.wikipedia.bar.alpha ; exports org.wikipedia.bar.beta ; }

ستكون العناصر العامة في org.wikipedia.bar.alphaالحزم متاحة للوحدات التابعة. أما العناصر الخاصة فلا يمكن الوصول إليها حتى باستخدام تقنيات مثل البرمجة الانعكاسية (الانعكاس). في إصدارات جافا من 9 إلى 16، يعتمد السماح الفعلي بهذا "الوصول غير المصرح به" على إعدادات سطر الأوامر . [ 3 ]org.wikipedia.bar.beta

أصبحت JDK معيارية في Java 9. [ 4 ] على سبيل المثال، يتم تصدير غالبية مكتبة Java القياسية بواسطة الوحدة النمطية java.base.

بيان الاستيراد

تُستخدم عبارة الاستيراد لتحديد نوع ينتمي إلى حزمة (مساحة اسم) أخرى. ويمكن اعتبارها مشابهة لما هو موجود usingفي لغة C++.

نوع إعلان الاستيراد

يُتيح تعريف استيراد النوع الإشارة إلى نوع مُسمى باسمه فقط، بدلاً من الاسم الكامل الذي يتضمن اسم الحزمة. يمكن أن تكون تعريفات الاستيراد تعريفات استيراد لنوع واحد أو تعريفات استيراد عند الطلب . يجب وضع تعريفات الاستيراد في بداية ملف الكود بعد تعريف الحزمة.

package org.wikipedia.examples ;استيراد java.util.Random ؛ // تعريف نوع واحدpublic class ImportsTest { public static void main ( String [] args ) { /* السطر التالي مكافئ لـ  * java.util.Random random = new java.util.Random();  * كان سيكون غير صحيح بدون الاستيراد.  */ Random random = new Random (); } }

تم ذكر تعريفات الاستيراد عند الطلب في الكود. يستورد "الاستيراد العام" (أو "الاستيراد الشامل") جميع أنواع الحزمة. بينما يستورد "الاستيراد الثابت" عناصر الحزمة.

/** * يتيح هذا الشكل من استيراد الفئات الوصول إلى جميع الفئات * في حزمة java.util بالاسم، ويمكن استخدامه بدلاً من * تعريف الاستيراد في المثال السابق. */ import java.util.* ;

قد لا يستورد استيراد الأحرف البديلة أي شيء إذا لم تكن هناك رموز موجودة في تلك الحزمة. على سبيل المثال، عبارات مثل "استيراد عام" صحيحة، لكنها لا تفعل شيئًا، لأن جميع الفئات موجودة في حزم داخل حزمة أخرى ؛ لن يستورد هذا النوع من الاستيراد جميع الفئات في الحزمة بشكل متكرر.importjava.*;java

إعلان الاستيراد الثابت

هذا النوع من التصريحات متاح منذ J2SE 5.0 . تسمح تصريحات الاستيراد الثابتة بالوصول إلى الأعضاء الثابتة المُعرَّفة في فئة أو واجهة أو تعليق توضيحي أو تعداد آخر؛ دون تحديد اسم الفئة:

import static java.lang.System.out ; // 'out' هو حقل ثابت في java.lang.Systempublic class HelloWorld { public static void main ( String [] args ) { /* السطر التالي مكافئ لـ  System.out.println("Hi World!");  وكان سيكون غير صحيح بدون تعريف الاستيراد. */ out . println ( "Hello World!" ); } }

تسمح عبارات الاستيراد عند الطلب باستيراد جميع حقول النوع التالي:

/** * يتيح هذا الشكل من التصريح الوصول إلى جميع * الحقول في فئة java.lang.System بالاسم، ويمكن استخدامه بدلاً من * تصريح الاستيراد في المثال السابق. */ import static java.lang.System.* ;

يمكن أيضًا استخدام ثوابت التعداد مع الاستيراد الثابت. على سبيل المثال، يوجد هذا التعداد في الحزمة المسماة screen:

public enum Colors { RED , BLUE , GREEN };

من الممكن استخدام تعريفات الاستيراد الثابتة في فئة أخرى لاسترداد ثوابت التعداد:

استيراد org.wikipedia.screen.ColorName ؛ استيراد ثابت org.wikipedia.screen.ColorName.* ؛public class Dots { /* السطر التالي مكافئ لـ 'ColorName foo = ColorName.RED'،  وكان سيكون غير صحيح بدون الاستيراد الثابت. */ ColorName foo = RED ;void shift () { /* السطر التالي مكافئ لـ  if (foo == ColorName.RED) foo = ColorName.BLUE; */ if ( foo == RED ) { foo = BLUE ; } } }

تعريف استيراد الوحدة النمطية

منذ إصدار Java 25، أصبح بالإمكان استخدام الوحدات النمطية في عبارات الاستيراد لاستيراد جميع الحزم التي تصدرها الوحدة النمطية تلقائيًا. [ 5 ] ويتم ذلك باستخدام import module. على سبيل المثال، مكافئ لـimportmodulejava.sql;

استيراد java.sql.* ؛ استيراد javax.sql.* ؛ // الصادرات غير المباشرة المتبقية من java.logging و java.transaction.xa و java.xml

وبالمثل ، يستورد جميع الحزم الـ 54 التابعة لـ .importmodulejava.base;java.base

استيراد الوحدة النمطية java.base ؛/** * يسمح لنا استيراد الوحدة java.base بتجنب استيراد معظم الفئات يدويًا * يتم استخدام الفئات التالية (خارج java.lang): * java.text.MessageFormat * java.util.Date * java.util.List * java.util.concurrent.ThreadLocalRandom */ public class Example { public static void main ( String [] args ) { List < String > colors = List . of ( "Red" , "Orange" , "Yellow" , "Green" , "Blue" , ​​"Indigo" , "Violet" ); IO . println ( MessageFormat . format ( "My favorite colour is {0} and today is {1,date,long}" , colors . get ( ThreadLocalRandom . current (). nextInt ( colors . size ())), new Date () )); } }

المشغلون

تتشابه المعاملات في جافا مع تلك الموجودة في لغة C++ . مع ذلك، لا يوجد deleteمعامل `unsigned` في جافا بسبب آليات جمع البيانات المهملة ، ولا توجد عمليات على المؤشرات لأن جافا لا تدعمها. ومن الاختلافات الأخرى أن جافا تحتوي على معامل إزاحة لليمين غير مُوقّع (`unsigned` >>>)، بينما يعتمد توقيع معامل الإزاحة لليمين في C على نوع البيانات. لا يمكن إعادة تعريف المعاملات في جافا ، والمعامل الوحيد المُعاد تعريفه هو operator+معامل دمج السلاسل النصية.

أسبقيةالمشغلوصفالترابط
1()استدعاء الأسلوبمن اليسار إلى اليمين
[]الوصول إلى المصفوفة
.اختيار أعضاء الفصل
2++--الزيادة والنقصان في اللاحقة [ 6 ]
3++--الزيادة والنقصان باستخدام البادئةمن اليمين إلى اليسار
+-موجب وسالب أحادي
!~النفي المنطقي والنفي الثنائي
(type) valنوع التحويل
newإنشاء مثيل فئة أو مصفوفة
4*/%الضرب والقسمة وباقي القسمة (المقياس)من اليسار إلى اليمين
5+-الجمع والطرح
+دمج السلاسل
6<<>>>>>الإزاحة الثنائية لليسار، والإزاحة الثنائية لليمين مع الإشارة، والإزاحة الثنائية لليمين بدون إشارة
7<<=العلاقات "أقل من" و "أقل من أو يساوي"
>>=العلاقات "أكبر من" و "أكبر من أو يساوي"
instanceofمقارنة الأنواع
8==!=العلاقات "يساوي" و "لا يساوي"
9&عملية AND المنطقية والبتية
10^عملية XOR المنطقية الثنائية (أو الحصرية)
11|عملية OR المنطقية الثنائية (أو الشاملة)
12&&الشرط المنطقي - و
13||الشرط المنطقي أو
14c ? t : fالشرط الثلاثي (انظر ؟: )من اليمين إلى اليسار
15=مهمة بسيطة
+=-=التوزيع عن طريق الجمع والطرح
*=/=%=التخصيص عن طريق الضرب والقسمة والباقي
<<=>>=>>>=الإسناد عن طريق الإزاحة الثنائية لليسار، والإزاحة الثنائية لليمين مع الإشارة، والإزاحة الثنائية لليمين بدون إشارة
&=^=|=التعيين باستخدام عمليات AND و XOR و OR الثنائية

هياكل التحكم

العبارات الشرطية

ifإفادة

تتشابه عبارات if في لغة Java مع تلك الموجودة في لغة C وتستخدم نفس الصيغة:

إذا كان ( i == 3 ) { doSomething (); }

ifقد تتضمن العبارة elseكتلة اختيارية، وفي هذه الحالة تصبح عبارة if-then-else:

إذا كان ( i == 3 ) { نفّذ شيئًا ما (); } وإلا { نفّذ شيئًا آخر (); }

على غرار لغة C، لا تتضمن بنية else-if أي كلمات مفتاحية خاصة، بل تتكون من سلسلة من عبارات if-then-else المنفصلة:

إذا كان ( i == 3 ) { نفّذ شيئًا ما (); } وإلا إذا كان ( i == 2 ) { نفّذ شيئًا آخر (); } وإلا { نفّذ شيئًا مختلفًا (); }

كما يمكن استخدام عامل التشغيل ?: بدلاً من عبارة if البسيطة، على سبيل المثال

int a = 1 ; int b = 2 ; int minVal = ( a < b ) ? a : b ;

switchإفادة

يمكن استخدام أنواع البيانات الأولية (مثل `<enum> byte` shortو` char<string>` intو`<string>` ) أو أنواع البيانات المُغلِّفة المُقابلة لها في عبارات `switch` في جافا. بدءًا من J2SE 5.0، أصبح من الممكن استخدام أنواع `enum` . بدءًا من Java SE 7، أصبح من الممكن استخدام السلاسل النصية (String). [ 7 ] لا يمكن استخدام أنواع البيانات المرجعية الأخرى في عبارات `switch`.longswitch

تُدرج القيم الممكنة باستخدام caseتسميات. في لغة جافا، قد تحتوي هذه التسميات على ثوابت فقط (بما في ذلك ثوابت التعداد وثوابت السلاسل النصية). يبدأ التنفيذ بعد التسمية المقابلة للتعبير الموجود داخل الأقواس. defaultيمكن إضافة تسمية اختيارية للإشارة إلى أنه سيتم تنفيذ الكود الذي يليها إذا لم تتطابق أي من تسميات الحالة مع التعبير.

ينتهي رمز كل تسمية بالكلمة breakالمفتاحية. من الممكن حذفها مما يؤدي إلى انتقال التنفيذ إلى التسمية التالية، ولكن عادةً ما يتم الإبلاغ عن تحذير أثناء عملية الترجمة.

switch ( ch ) { case 'A' : doSomething (); // يتم التفعيل إذا كانت قيمة ch تساوي 'A' break ; case 'B' : case 'C' : doSomethingElse (); // يتم التفعيل إذا كانت قيمة ch تساوي 'B' أو ch تساوي 'C' break ; default : doSomethingDifferent (); // يتم التفعيل في أي حالة أخرى break ; }
switchتعابير

منذ إصدار Java 14 أصبح من الممكن استخدام تعابير التبديل، والتي تستخدم صيغة السهم الجديدة:

enum Result { GREAT , FINE , // المزيد من قيم enum }النتيجة result = switch ( ch ) { case 'A' -> النتيجة . GREAT ; case 'B' , 'C' -> النتيجة . FINE ; default -> throw new Exception (); };

بدلاً من ذلك، هناك إمكانية للتعبير عن نفس الشيء باستخدام yieldالعبارة، على الرغم من أنه يوصى بتفضيل صيغة السهم لأنها تتجنب مشكلة السقوط العرضي.

النتيجة result = switch ( ch ) { case 'A' : yield Result . GREAT ; case 'B' : case 'C' : yield Result . FINE ; default : throw new Exception (); };

عبارات التكرار

عبارات التكرار هي عبارات تُنفَّذ بشكل متكرر عند تحقق شرط معين. منذ إصدار J2SE 5.0 ، توفر جافا أربعة أشكال لهذه العبارات. يجب أن يكون نوع الشرط صحيحًا booleanأو java.lang.Booleanمنطقيًا. لا تُحوِّل جافا ضمنيًا الأعداد الصحيحة أو أنواع الفئات إلى قيم منطقية.

على سبيل المثال، الكود التالي صالح في لغة C ولكنه ينتج عنه خطأ في الترجمة في لغة Java.

بينما ( 1 ) { نفّذ شيئًا ما (); }

whileحلقة

في whileالحلقة، يتم إجراء الاختبار قبل كل تكرار.

بينما ( i ​​< 10 ) { doSomething (); }

do- whileحلقة

في حلقة doالتكرار while، يتم إجراء الاختبار بعد كل تكرار. وبالتالي، يتم تنفيذ الكود دائمًا مرة واحدة على الأقل.

// يتم استدعاء الدالة doSomething() مرة واحدة على الأقل do { doSomething (); } while ( i < 10 );

forحلقة

forتتضمن الحلقات في جافا مُهيئًا وشرطًا وتعبيرًا عدادًا. من الممكن تضمين عدة تعبيرات من النوع نفسه باستخدام الفاصلة كفاصل (باستثناء الشرط). مع ذلك، على عكس لغة C، فإن الفاصلة مجرد فاصل وليست عاملًا.

for ( int i = 0 ; i < 10 ; i ++ ) { doSomething (); } // حلقة أكثر تعقيدًا باستخدام متغيرين for ( int i = 0 , j = 9 ; i < 10 ; i ++ , j -= 3 ) { doSomething (); }

كما هو الحال في لغة C، فإن جميع التعبيرات الثلاثة اختيارية. الحلقة التالية لا تنتهي أبدًا:

for (;;) { doSomething (); }

حلقة التكرار لكل عنصر

أصبحت حلقات التكرار foreach متاحة منذ J2SE 5.0 . يستخدم هذا النوع من الحلقات مُكرِّرات مُدمجة على المصفوفات والمجموعات لإرجاع كل عنصر في المجموعة المُعطاة. يتم إرجاع كل عنصر ويكون الوصول إليه مُتاحًا ضمن سياق كتلة التعليمات البرمجية. عند تنفيذ الكتلة، يتم إرجاع العنصر التالي حتى لا يتبقى أي عناصر. أُضيفت حلقة for هذه من Java لاحقًا إلى C++11 . على عكس C# ، لا يتضمن هذا النوع من الحلقات كلمة مفتاحية خاصة، بل يستخدم أسلوب كتابة مختلفًا.

for ( int i : intArray ) { doSomething ( i ); }

عبارات الانتقال

الملصقات

تُستخدم التسميات لتحديد نقاط في الكود، وتُستخدم بواسطة عبارات break`and` . على الرغم من أن `is` كلمة محجوزة في جافا، إلا أنه لا يمكن استخدامها للانتقال إلى نقاط محددة في الكود (في الواقع، ليس لها أي فائدة على الإطلاق).continuegoto

ابدأ : بعض الطرق ();

breakإفادة

breakيخرج هذا الأمر من أقرب حلقة أو switchأمر. ويستمر التنفيذ في الأمر الذي يلي الأمر الذي تم إنهاؤه، إن وجد.

for ( int i = 0 ; i < 10 ; i ++ ) { while ( true ) { break ; } // سيتم الخروج من الحلقة عند هذه النقطة }

من الممكن الخروج من الحلقة الخارجية باستخدام التسميات:

outer : for ( int i = 0 ; i < 10 ; i ++ ) { while ( true ) { break outer ; } } // سيتم الخروج عند هذه النقطة

continueإفادة

تُنهي هذه continueالعبارة التكرار الحالي لعبارة التحكم الحالية وتبدأ التكرار التالي. whileتقرأ الحلقة التالية في الكود أدناه الأحرف باستدعاء الدالة getChar()، وتتخطى العبارات في جسم الحلقة إذا كانت الأحرف مسافات.

int ch ; while ( ch == getChar ()) { if ( ch == ' ' ) { continue ; // يتخطى باقي حلقة while }// لن يتم الوصول إلى باقي حلقة while إذا كانت قيمة ch تساوي ' ' doSomething (); }

يمكن تحديد التصنيفات في continueالعبارات breakوالعبارات:

outer : for ( String str : stringsArr ) { char [] strChars = str.toCharArray (); for ( char ch : strChars ) { if ( ch == ' ' ) { /* استمر في الحلقة الخارجية واحصل على السلسلة التالية  من stringsArr */ continue outer ; } doSomething ( ch ) ; } }

returnإفادة

تُستخدم هذه returnالعبارة لإنهاء تنفيذ الدالة وإرجاع قيمة. تُكتب القيمة المُرجعة من الدالة بعد الكلمة returnالمفتاحية. إذا أرجعت الدالة أي قيمة أخرى غير القيمة الافتراضية void، فيجب عليها استخدام هذه returnالعبارة لإرجاع قيمة ما.

void doSomething ( boolean streamClosed ) { // إذا كانت قيمة streamClosed صحيحة، يتم إيقاف التنفيذ if ( streamClosed ) { return ; } readFromStream (); }دالة حساب المجموع ( int a , int b ) { int result = a + b ; return result ; }

returnينهي البيان التنفيذ فورًا، باستثناء حالة واحدة: إذا تمت مصادفة البيان داخل tryكتلة وتم استكماله بـ finally، فسيتم تمرير التحكم إلى finallyالكتلة.

void doSomething ( boolean streamClosed ) { try { if ( streamClosed ) { return ; } readFromStream (); } finally { // سيتم استدعاء هذه الدالة أخيرًا حتى لو لم يتم استدعاء readFromStream() freeResources (); } }

بيانات معالجة الاستثناءات

try- catch- finallyبيانات

تتم إدارة الاستثناءات داخل كتل try-catch

try { // عبارات قد تُطلق استثناءات methodThrowingExceptions (); } catch ( Exception e ) { // تم التقاط الاستثناء ومعالجته هنا reportException ( e ); } finally { // عبارات تُنفذ دائمًا بعد كتل try/catch freeResources (); }

تُنفَّذ التعليمات البرمجية داخل tryالكتلة، وإذا أدى أي منها إلى ظهور استثناء، يتوقف تنفيذ الكتلة وتتولى catchالكتلة معالجة الاستثناء. قد توجد عدة catchكتل، وفي هذه الحالة تُنفَّذ أول كتلة تحتوي على متغير استثناء يتطابق نوعه مع نوع الاستثناء الذي ظهر.

أضافت Java SE 7 عبارات متعددة للالتقاط إلى جانب عبارات أحادية الالتقاط. يسمح هذا النوع من عبارات الالتقاط لجافا بمعالجة أنواع مختلفة من الاستثناءات في كتلة واحدة، شريطة ألا تكون هذه الاستثناءات فئات فرعية من بعضها البعض. ورغم أنها تبدو مشابهة لنوع الاتحاد ، إلا أنها في الواقع النوع الفائق المشترك الأكثر تحديدًا من بين البدائل.

استيراد java.net.HttpRetryException ؛ استيراد java.net.http.HttpTimeoutException ؛void makeRequest () throws HttpRetryException , HttpTimeoutException { // ... }void main ( String [] args ) { try { methodThrowingExceptions (); } catch ( HttpRetryException | HttpTimeoutException e ) { // سيتم التقاط ومعالجة كل من HttpRetryException و HttpTimeoutException هنا // في الواقع، هذا يختزل إلى java.io.IOException. reportException ( e ); } }

إذا لم يتطابق أي جزء من التعليمات البرمجية مع نوع الاستثناء المُثار، يتوقف catchتنفيذ الجزء الخارجي (أو الدالة) الذي يحتوي على عبارة try"-" ، ويُمرر الاستثناء إلى أعلى خارج الجزء (أو الدالة) المُحتوي. ينتشر الاستثناء تصاعديًا عبر مكدس الاستدعاءات حتى يتم العثور على جزء مطابق داخل إحدى الدوال النشطة حاليًا. إذا انتشر الاستثناء حتى وصل إلى أعلى دالة دون العثور على جزء مطابق ، يُكتب وصف نصي للاستثناء إلى دفق الإخراج القياسي.catchcatchmaincatch

finallyتُنفَّذ التعليمات البرمجية داخل الكتلة دائمًا بعد كتلتي try`and` catch، سواءً حدث استثناء أم لا، وحتى في حال returnالوصول إلى تعليمة `and`. تُفيد هذه الكتل في توفير تعليمات برمجية للتنظيف مضمونة التنفيذ دائمًا.

الكتلتان catchو finallyاختياريتان، ولكن يجب أن تكون إحداهما على الأقل موجودة بعد tryالكتلة.

tryعبارات -مع-الموارد

tryتُعدّ عبارات `-with-resources` نوعًا خاصًا من عبارات try` catch-` finally، وقد طُرحت كتطبيق لنمط التخلص (dispose) في Java SE 7. في tryعبارة `-with-resources` try، تتبع الكلمة المفتاحية `-` تهيئة مورد واحد أو أكثر، يتم تحريرها تلقائيًا عند tryانتهاء تنفيذ الكتلة. يجب أن تُنفّذ الموارد نمط `-` java.lang.AutoCloseable. tryلا تتطلب عبارات `-with-resources` وجود كتلة `-` catchأو `-` عادية، على عكس عبارات ` -` finallyالعادية .trycatchfinally

استيراد java.beans.XMLEncoder ؛ استيراد java.io.FileOutputStream ؛ استيراد java.io.IOException ؛ استيراد java.util.logging.Level ؛ استيراد java.util.logging.Logger ؛try ( FileOutputStream fos = new FileOutputStream ( " filename " ) ; XMLEncoder xEnc = new XMLEncoder ( fos ) ) { xEnc.writeObject ( object ) ; } catch ( IOException e ) { Logger.getLogger ( Serializer.class.getName ( ) ) . log ( Level.SEVERE , null , e ) ; }

منذ إصدار Java 9 أصبح من الممكن استخدام المتغيرات المعلنة مسبقاً:

استيراد java.beans.XMLEncoder ؛ استيراد java.io.FileOutputStream ؛ استيراد java.io.IOException ؛ استيراد java.util.logging.Level ؛ استيراد java.util.logging.Logger ؛FileOutputStream fos = new FileOutputStream ( " filename " ) ; XMLEncoder xEnc = new XMLEncoder ( fos ) ; try ( fos ; xEnc ) { xEnc.writeObject ( object ) ; } catch ( IOException e ) { Logger.getLogger ( Serializer.class.getName ( ) ) . log ( Level.SEVERE , null , e ) ; }

throwإفادة

تُستخدم هذه throwالعبارة لإطلاق استثناء وإنهاء تنفيذ الكتلة أو الدالة. ويتم كتابة نسخة الاستثناء المُطلق بعد هذه throwالعبارة.

void methodThrowingExceptions ( Object obj ) { if ( obj == null ) { // يطرح استثناءً من نوع NullPointerException throw new NullPointerException (); } // لن يتم استدعاؤه إذا كان الكائن فارغًا doSomethingWithObject ( obj ); }

assertإفادة

assertتتوفر عبارات التأكيد منذ J2SE 1.4 . تُستخدم هذه العبارات لإجراء تأكيدات في شفرة المصدر، والتي يمكن تفعيلها أو تعطيلها أثناء التنفيذ لفئات أو حزم محددة. لتعريف تأكيد، assertتُستخدم الكلمة المفتاحية متبوعة بتعبير شرطي. إذا كانت نتيجة هذا falseالتعبير صحيحة عند تنفيذ العبارة، فسيحدث خطأ java.lang.AssertionError. يمكن أن تتضمن هذه العبارة نقطتين رأسيتين متبوعتين بتعبير آخر، والذي سيمثل رسالة الخطأ التفصيلية.

// إذا كانت قيمة n تساوي صفرًا، فسيتم طرح استثناء java.lang.AssertionError. assert n != 0 ; /* إذا كانت قيمة n تساوي صفرًا، فسيتم طرح استثناء java.lang.AssertionError مع الرسالة التي تلي النقطتين */ assert n != 0 : "كانت قيمة n تساوي صفرًا" ;

عملية ربط الخيوط

توفر لغة جافا سلاسل تنفيذ من خلال فئة `string` java.lang.Thread. تأخذ هذه الفئة كائنًا java.lang.Runnable(مثل تعبير لامدا)، ويتم تشغيلها باستخدام start()الدالة `start()`، وإيقافها مؤقتًا/حظرها باستخدام الدالة `stop() sleep()`. لإعلام السلاسل الأخرى، wait()تُحرر الدالة `start()` قفل الكائن وتُوقف السلسلة مؤقتًا حتى تستدعي سلسلة أخرى الدالة `stop()` notify()أو ` stop notifyAll()()`.

Thread t = new Thread (() -> { System . out . println ( "Running" ); });t . start ();

الخيوط الخلفية هي خيوط تعمل في الخلفية، مثل خيوط جمع البيانات المهملة أو خيوط المراقبة. يتوقف نظام JVM عن العمل عندما لا يتبقى سوى الخيوط الخلفية.

يمكن الوصول إلى الخيط الحالي باستخدام هذه currentThread()الطريقة.

java.lang.ThreadDeathتاريخيًا، كان يتم طرح خطأ عند استدعاء دالة stop()على خيط، ولكن stop()تم إزالة هذا الخطأ منذ إصدار Java 20 [ 8 ] ، ولم يعد يتم طرحه [ 9 ] . الطريقة المُثلى لإيقاف خيط الآن هي باستخدام الدالة interrupt()، حيث يُسمح للخيط بالانتهاء بسلاسة بدلاً من إيقافه فورًا دون تنظيف.

التحكم في تزامن الخيوط

تتضمن لغة جافا أدوات مدمجة لبرمجة الخيوط المتعددة. ولأغراض مزامنة الخيوط، تم تضمين هذه synchronizedالعبارة في لغة جافا.

لجعل كتلة برمجية متزامنة، تُسبق بالكلمة synchronizedالمفتاحية متبوعةً بكائن القفل داخل الأقواس. عندما يصل الخيط المنفذ إلى الكتلة المتزامنة، فإنه يحصل على قفل استبعاد متبادل ، وينفذ الكتلة، ثم يحرر القفل. لا يُسمح لأي خيوط بالدخول إلى هذه الكتلة حتى يتم تحرير القفل. يمكن استخدام أي نوع مرجعي غير فارغ كقفل.

/* يستحوذ على قفل على الكائن someObject. يجب أن يكون من نوع مرجعي ويجب ألا يكون فارغًا */ synchronized ( someObject ) { // عبارات متزامنة }

ميزات التزامن

توفر لغة جافا المكتبة java.util.concurrent، بالإضافة إلى ميزات الذرية ( java.util.concurrent.atomic) وميزات القفل ( java.util.concurrent.locks).

بدلاً من ذلك ، يتم توفير java.lang.Threadفئة أخرى للحساب غير المتزامن [ 10 ] ؛ يمكن اعتبار هذا مشابهًا لـ في C# ، على الرغم من أن Java تفتقر إلى الروتينات الفرعية الصريحة مثل تلك الموجودة في C#.java.util.concurrent.CompletableFuture<T>System.Threading.Tasks.Task<T>

كجزء من مشروع Loom في Java 21، تم تقديم الخيوط الافتراضية ، التي تسمح بتنفيذ تعليمات برمجية متزامنة، مع إمكانية التوسع لتشمل ملايين المهام. [ 11 ] [ 12 ] يُطلق على خيط Java التقليدي اسم "خيط النظام الأساسي"، وهو ما يُشابه تقريبًا خيط نظام التشغيل، لكن خيوط Java الافتراضية خفيفة الوزن وتُدار بواسطة JVM، وتُجدول على مجموعة صغيرة من خيوط نظام التشغيل الحقيقية. لا تزال الخيوط الافتراضية متزامنة java.lang.Thread، ولكن يتم إنشاؤها باستخدام طرق المصنع ofVirtual(). على الرغم من أن التعليمات البرمجية لا تزال متزامنة، فإن خيوط نظام التشغيل الفعلية غير متزامنة؛ فعند التوقف للانتظار، يفصل JVM التعليمات البرمجية عن الخيط الفعلي، ويُشغل مهامًا أخرى حتى يُرسل نظام التشغيل إشعارًا بحدث غير متزامن لاستئناف تنفيذ التعليمات البرمجية من حيث توقفت.

الأنواع الأولية

تشمل الأنواع الأساسية في جافا أنواع الأعداد الصحيحة، والأعداد العشرية، ووحدات ترميز UTF-16 ، ونوعًا منطقيًا. على عكس لغتي C++ وC#، لا توجد أنواع غير مُوقَّعة في جافا باستثناء charالنوع `type`، الذي يُستخدم لتمثيل وحدات ترميز UTF-16. يُعوَّض غياب الأنواع غير المُوقَّعة بإضافة عملية الإزاحة إلى اليمين غير المُوقَّعة (`unsigned right shift` >>>)، غير الموجودة في C++، باستخدام دوال مثل `unsigned` .toUnsignedInt(). مع ذلك، وُجِّهت انتقادات بشأن عدم التوافق مع لغتي C وC++ الناتج عن ذلك. [ 13 ]

الأنواع الأولية
اسم النوعما يعادل مكتبة الفئاتقيمةيتراوحمقاسالقيمة الافتراضية
shortjava.lang.Shortعدد صحيحمن -32,768 إلى +32,76716 بت (2 بايت)0
intjava.lang.Integerعدد صحيحمن -2,147,483,648 إلى +2,147,483,64732 بت (4 بايت)0
longjava.lang.Longعدد صحيحمن -9,223,372,036,854,775,808 إلى +9,223,372,036,854,775,80764 بت (8 بايت)0
bytejava.lang.Byteعدد صحيحمن -128 إلى 1278 بت (1 بايت)0
floatjava.lang.Floatعدد عشريمن ±1.401298E−45 إلى ±3.402823E+3832 بت (4 بايت)0.0
doublejava.lang.Doubleعدد عشريمن ±4.94065645841246E−324 إلى ±1.79769313486232E+30864 بت (8 بايت)0.0
booleanjava.lang.Booleanمنطقيtrueأوfalse8 بت (1 بايت)false
charjava.lang.Characterحرف واحد من رموز يونيكود'\u0000'خلال'\uFFFF'16 بت (2 بايت)'\u0000'
voidjava.lang.Voidغير متوفرغير متوفرغير متوفرغير متوفر

nullليس له نوع، لا بدائي ولا صنف. يمكن لأي نوع كائن تخزينه null.

يُستخدم هذا الصنف Voidللاحتفاظ بمرجع للكائن Classالذي يُمثل الكلمة المفتاحية void. لا يمكن إنشاء مثيل له لأنه voidلا يمكن أن يكون من نوع أي كائن. على سبيل المثال، CompletableFuture<Void>يُشير إلى أن java.util.concurrent.CompletableFuture<T>يُنفذ مهمة لا تُرجع قيمة.

يمثل هذا الصنف java.lang.Numberجميع القيم العددية التي يمكن تحويلها إلى byte، double، float، int، long، و short.

charلا يُشترط أن يُطابق حرفًا واحدًا. قد يُمثل جزءًا من زوج بديل ، وفي هذه الحالة يتم تمثيل نقطة رمز يونيكود بتسلسل من charقيمتين.

تحتوي فئات التغليف على توابع ثابتة إضافية لإجراء عمليات على أنواعها الأولية، مثل Integer.parseInt()، بالإضافة إلى ثوابت ثابتة تصف معلومات النوع. java.lang.Characterوتحتوي فئة التغليف نفسها على أنواع متداخلة إضافية:

  • java.lang.Character.Subset، وهو يمثل مجموعة فرعية من مجموعة أحرف يونيكود
  • java.lang.Character.UnicodeBlock، تحتوي على ثوابت تمثل كتلة يونيكود
  • java.lang.Character.UnicodeScript، مجموعة من النصوص في يونيكود

التعبئة وفتح الصناديق

أُضيفت هذه الميزة اللغوية في J2SE 5.0 . التغليف هو عملية تحويل قيمة من نوع بيانات أولي إلى قيمة من نوع مرجعي مُطابق، والذي يعمل كغلاف لهذا النوع الأولي. فك التغليف هو العملية العكسية، أي تحويل قيمة من نوع مرجعي (تم تغليفه مسبقًا) إلى قيمة من نوع بيانات أولي مُطابق. لا تتطلب أي من العمليتين تحويلًا صريحًا.

مثال:

int foo = 42 ; // نوع بيانات أولي Integer bar = foo ; /* foo مُغلّف في bar، و bar من نوع Integer،  والذي يعمل كغلاف لـ int */ int foo2 = bar ; // تم فك التغليف والعودة إلى نوع البيانات الأولي

أنواع المراجع

تشمل أنواع المراجع أنواع الأصناف، وأنواع الواجهات، وأنواع المصفوفات. عند استدعاء الدالة البانية، يُنشأ كائن في الذاكرة الديناميكية ويُسند مرجع إلى المتغير. عندما يخرج متغير من نطاق تعريف الكائن، يُقطع المرجع، وعندما لا يتبقى أي مراجع، يُصنف الكائن على أنه كائن مهمل. ثم يقوم جامع البيانات المهملة بجمعه وتدميره بعد فترة.

المتغير المرجعي هو المتغير nullالذي لا يشير إلى أي كائن.

المصفوفات

يتم إنشاء المصفوفات في جافا أثناء وقت التشغيل، تمامًا مثل مثيلات الفئات. يتم تحديد طول المصفوفة عند إنشائها ولا يمكن تغييره.

int [] numbers = new int [ 5 ] ; numbers [ 0 ] = 2 ; numbers [ 1 ] = 5 ; int x = numbers [ 0 ] ; int len ​​= numbers.length ; // len = 5

تُقبل أيضًا تعريفات المصفوفات على نمط لغة C في لغة Java، ولكنها ليست شائعة الاستخدام.

int arr [] = new int [ 10 ] ;

يتم تمثيل المصفوفات في JVM باستخدام قوس مربع مفتوح لليسار لكل بُعد من أبعاد المصفوفة، مع الأحرف التالية:

  • ب ، لـbyte
  • ج ، لـchar
  • د ، لـdouble
  • F ، لـfloat
  • أنا ، من أجلint
  • J ، لـlong
  • S ، لـshort
  • Z ، لـboolean
  • L ، لأي نوع مرجعي (غير بدائي)، متبوعًا باسم الفئة المؤهل بالكامل ثم فاصلة منقوطة ختامية [ a ]

على سبيل المثال، int[][]يصبح [[Iو String[]يصبح [Ljava.lang.String;.

voidلا يوجد كنوع في الذاكرة، ولكنه ممثل داخليًا بالحرف V.

تقتصر المصفوفات على 255 بُعدًا كحد أقصى. الحد الأقصى النظري لطول المصفوفة هو231-1{\displaystyle 2^{31}-1}(2,147,483,647، وهو ما يعادل Integer.MAX_VALUE)، لأن المصفوفات لا يمكن الوصول إليها إلا باستخدام فهارس 32 بت، ولكن هذا الحد يعتمد عادةً على النظام والآلة الافتراضية.

java.util.Arraysتُوفّر الفئتان java.lang.reflect.Arrayلمعالجة المصفوفات والعمليات الانعكاسية عليها، على التوالي. [ 14 ] [ 15 ]

يبدو أن المصفوفات تحتوي على حقل length، لكنه ليس حقلاً حقيقياً؛ بل هو خاصية مدمجة يتم تقييمها بشكل أصلي بواسطة arraylengthتعليمة البايت كود . [ 1 ] لا تحتوي المصفوفات على أعضاء أو أساليب أو مُنشئات مُعلنة (بخلاف تلك الموروثة من java.lang.Object).

ترث المصفوفات الفئة java.lang.Objectوتُطبّق واجهاتها java.lang.Cloneable. java.io.Serializableالمصفوفات مُضمّنة ضمنيًا final، ولا يمكن وراثتها من فئات أخرى. على الرغم من كونها فئات، لا يوجد ملف .class للمصفوفات لأنها تُنشأ مباشرةً في الذاكرة أثناء التنفيذ، وليس لها تمثيل فيزيائي في بايت كود ، ولا يتم تحميلها بواسطة مُحمّل الفئات .

لأن المصفوفات هي أنواع مرجعية، يمكن استخدامها مباشرة في معلمات النوع العامة.

استيراد java.util.ArrayList ؛ استيراد java.util.List ؛List < int []> frequencies = new ArrayList <> ();

المُهيئات

// الصيغة الطويلة int [] numbers = new int [] { 20 , 1 , 42 , 15 , 34 }; // الصيغة المختصرة int [] numbers2 = { 20 , 1 , 42 , 15 , 34 };

المصفوفات متعددة الأبعاد

في لغة جافا، يتم تمثيل المصفوفات متعددة الأبعاد كمصفوفات من المصفوفات. من الناحية التقنية، يتم تمثيلها كمصفوفات من المراجع إلى مصفوفات أخرى.

int [][] numbers = new int [ 3 ][ 3 ] ; numbers [ 1 ][ 2 ] = 2 ;int [][] numbers2 = {{ 2 , 3 , 2 }, { 1 , 2 , 6 }, { 2 , 4 , 5 }};

نظراً لطبيعة المصفوفات متعددة الأبعاد، يمكن أن تختلف المصفوفات الفرعية في الطول، لذا فإن المصفوفات متعددة الأبعاد ليست بالضرورة مستطيلة الشكل على عكس لغة C:

int [][] numbers = new int [ 2 ][] ; // تهيئة البُعد الأول فقطnumbers [ 0 ] = new int [ 3 ] ; numbers [ 1 ] = new int [ 2 ] ;

الصفوف الدراسية

تُعدّ الفئات من أساسيات لغات البرمجة كائنية التوجه مثل جافا. تحتوي الفئات على أعضاء لتخزين البيانات ومعالجتها. تُقسم الفئات إلى فئات رئيسية وفئات متداخلة . الفئات المتداخلة هي فئات موجودة داخل فئة أخرى، ويمكنها الوصول إلى الأعضاء الخاصة بالفئة المُحيطة. تشمل الفئات المتداخلة فئات الأعضاء (التي يمكن تعريفها باستخدام المُعدِّل static للتداخل البسيط أو بدونه للفئات الداخلية)، والفئات المحلية ، والفئات المجهولة .

تصريح

فئة رفيعة المستوى
class Foo { // أعضاء الفئة }
الطبقة الداخلية
// الفئة الرئيسية class Foo { // الفئة الداخلية class Bar { // ... } }
فئة متداخلة
// فئة المستوى الأعلى class Foo { // فئة متداخلة static class Bar { // ... } }
الطبقة المحلية
class Foo { void bar () { // فئة محلية داخل دالة class Foobar { // ... } } }
فئة مجهولة
class Foo { void bar () { // إنشاء فئة مجهولة جديدة تمتد من Object new Object () {}; } }

التفعيل

تُحدد الأعضاء غير الثابتة في الصنف أنواع متغيرات وأساليب النسخة ، المرتبطة بالكائنات المُنشأة من ذلك الصنف. ولإنشاء هذه الكائنات، يجب إنشاء نسخة من الصنف باستخدام newعامل التشغيل واستدعاء مُنشئ الصنف.

Foo foo = new Foo ();

الوصول إلى الأعضاء

يتم الوصول إلى أعضاء كل من النسخ والفئات الثابتة باستخدام .عامل التشغيل (النقطة).

الوصول إلى عضو من أعضاء المثيل: يمكن الوصول إلى أعضاء المثيل من خلال اسم متغير.

String foo = "Hello" ; String bar = foo . toUpperCase ();

الوصول إلى عضو ثابت في فئة: يتم الوصول إلى الأعضاء الثابتة باستخدام اسم الفئة أو أي نوع آخر. لا يتطلب ذلك إنشاء نسخة من الفئة. يتم تعريف الأعضاء الثابتة باستخدام staticالمُعدِّل.

public class Foo { public static void doSomething () { // ... } }// استدعاء الدالة الثابتة Foo.doSomething ( );

المُعدِّلات

المُعدِّلات هي كلمات مفتاحية تُستخدم لتعديل تعريفات الأنواع وأعضاء الأنواع. ومن أبرزها مجموعة فرعية تحتوي على مُعدِّلات الوصول.

  • abstract- يحدد أن الفئة تعمل فقط كفئة أساسية ولا يمكن إنشاء مثيل لها.
  • static- يستخدم فقط للفئات الأعضاء، ويحدد أن الفئة العضو لا تنتمي إلى مثيل محدد من الفئة الحاوية.
  • final- الفئات التي تم وضع علامة عليها بأنها finalلا يمكن توسيعها ولا يمكن أن يكون لها أي فئات فرعية.
  • strictfp- يحدد أن جميع عمليات الفاصلة العائمة يجب أن تتم وفقًا لمعيار IEEE 754 ويحظر استخدام الدقة المحسنة لتخزين النتائج الوسيطة.
فئة مجردة

افتراضيًا، تكون جميع الطرق في جميع الفئات ملموسة، ما لم تُستخدم الكلمة المفتاحية abstract. قد تتضمن الفئة المجردة طرقًا مجردة، أي طرقًا لا يوجد لها تطبيق. افتراضيًا، تكون جميع الطرق في جميع الواجهات مجردة، ما لم تُستخدم الكلمة المفتاحية default. يمكن استخدام الكلمة المفتاحية default لتحديد طريقة ملموسة في واجهة.

// بشكل افتراضي، جميع الطرق في جميع الفئات ملموسة، ما لم يتم استخدام الكلمة المفتاحية abstract. abstract class Demo { // قد تتضمن الفئة المجردة طرقًا مجردة، والتي ليس لها تنفيذ. public abstract int sum ( int x , int y );// قد تتضمن الفئة المجردة أيضًا طرقًا ملموسة. public int product ( int x , int y ) { return x * y ; } }// بشكل افتراضي، جميع الدوال في جميع الواجهات مجردة، إلا إذا تم استخدام الكلمة المفتاحية default. interface DemoInterface { int getLength (); // يمكن استخدام الكلمة المفتاحية abstract هنا، على الرغم من أنها غير مجدية تمامًا // يمكن استخدام الكلمة المفتاحية default في هذا السياق لتحديد دالة ملموسة في واجهة default int product ( int x , int y ) { return x * y ; } }

الفصل الدراسي الأخير

لا يمكن إنشاء فئات فرعية من فئة نهائية . ولأن القيام بذلك قد يوفر مزايا أمنية وكفاءة، فإن العديد من فئات مكتبة جافا القياسية نهائية، مثل java.lang.Systemو java.lang.String.

مثال:

final class Final { // ... }// فئة مشتقة ممنوعة تمتد من الفئة النهائية { // ... }
مُعدِّلات الوصول

تُحدد مُعدِّلات الوصول ، أو مُعدِّلات الوراثة ، إمكانية الوصول إلى الفئات والأساليب والأعضاء الآخرين. publicيمكن الوصول إلى الأعضاء المُعَلَّمة بهذه المُعدِّلات من أي مكان. إذا لم يكن للفئة أو أحد أعضائها أي مُعدِّلات، يُفترض الوصول الافتراضي.

public class Foo { int baz () { return 0 ; }فئة خاصة Bar {} }

يوضح الجدول التالي ما إذا كان الكود الموجود داخل فئة ما لديه حق الوصول إلى الفئة أو الطريقة اعتمادًا على موقع الفئة التي يتم الوصول إليها والمعدِّل الخاص بالفئة أو عضو الفئة التي تم الوصول إليها:

المعدلنفس الفئة أو فئة متداخلةفئة أخرى داخل نفس الحزمةفئة موسعة داخل حزمة أخرىغير ممتد داخل عبوة أخرى
privateنعملالالا
افتراضي (حزمة خاصة)نعمنعملالا
protectedنعمنعمنعملا
publicنعمنعمنعمنعم
توضح هذه الصورة نطاق أعضاء الفئة داخل الفئات والحزم.

المُنشئات والمُهيئات

المُنشئ هو كتلة برمجية خاصة تُشبه الدوال ، ويتم استدعاؤها عند تهيئة كائن. وظيفته هي تهيئة عناصر الكائن. الفرق الرئيسي بين المُنشئات والدوال العادية هو أن المُنشئات تُستدعى فقط عند إنشاء نسخة من الصنف، ولا تُرجع أي قيمة. تُصرَّح المُنشئات بطريقة تُشبه الدوال، ولكنها تُسمى باسم الصنف، ولا يُحدد نوع القيمة المُرجعة؛ فمثلاً، بالنسبة للصنف X، يكون المُنشئ هو X(...)؛ وعلى وجه الخصوص، لا يحتوي المُنشئ الافتراضي على أي مُعاملات X().

class Foo { String str ;// دالة البناء بدون وسائط Foo () {}// دالة البناء ذات الوسيط الواحد Foo ( String str ) { this . str = str ; } }

يبدو المُنشئ مُشابهًا للدالة، ولكنه في الواقع عبارة عن كتل تهيئة للكائن، ولا يُمكن استدعاؤه مُباشرةً بواسطة استدعاء دالة (على عكس لغة C++ ، حيث تُعتبر المُنشئات دوال أعضاء خاصة ). [ 16 ] مع ذلك، في بايت كود JVM ، يظهر المُنشئ تحت اسم <init>"دالة تهيئة الكائن"، ويتم تمييزه void(وبالتالي لا يُضيف أي كائن ناتج إلى مكدس معاملات JVM عند اكتمال التنفيذ). [ 17 ]

المُهيئات هي كتل من التعليمات البرمجية تُنفذ عند إنشاء فئة أو نسخة منها. يوجد نوعان من المُهيئات: المُهيئات الثابتة ومُهيئات النسخ .

تقوم المُهيئات الثابتة بتهيئة الحقول الثابتة عند إنشاء الصنف. ويتم تعريفها باستخدام staticالكلمة المفتاحية:

class Foo { static { // التهيئة } }

يتم إنشاء الصنف مرة واحدة فقط. لذلك، لا يتم استدعاء المُهيئات الثابتة أكثر من مرة. على النقيض من ذلك، يتم استدعاء مُهيئات النسخ تلقائيًا قبل استدعاء المُنشئ في كل مرة يتم فيها إنشاء نسخة من الصنف. على عكس المُنشئات، لا يمكن لمُهيئات النسخ أن تأخذ أي وسائط، وعمومًا لا يمكنها إطلاق أي استثناءات مُدققة (باستثناء حالات خاصة قليلة). يتم تعريف مُهيئات النسخ في كتلة بدون أي كلمات مفتاحية.

class Foo { { // التهيئة } }

بما أن جافا تعتمد على آلية جمع البيانات المهملة، فلا توجد دوال تدمير~X() أو deleteعوامل تشغيل. مع ذلك، لكل كائن دالة finalize()تُستدعى قبل جمع البيانات المهملة، ويمكن تجاوزها لتنفيذ الإنهاء. لكن لا توجد ضمانات بشأن الخيط الذي سيستدعي finalize()الدالة لأي كائن معين، أو حتى ما إذا كانت ستُستدعى أصلاً. دوال الإنهاء غير حتمية (على عكس دوال التدمير في لغة C++)، وقد finalize()يؤدي تحرير الموارد الحيوية في استدعاء إلى سلوك غير متوقع. [ 18 ] كما تم توفير فئة أخرى، java.lang.ref.Cleanerتم تقديمها في جافا 9، لتوفير شبكات أمان منخفضة المستوى لاستعادة الموارد غير المتعلقة بالذاكرة، مثل المؤشرات الأصلية، ومُعرّفات الملفات، والمآخذ. [ 19 ]

طُرق

يجب أن تكون جميع التعليمات البرمجية في جافا ضمن دوال . الدوال تشبه الدوال العادية، إلا أنها تنتمي إلى فئات. تحتوي الدالة على قيمة مُعادة، واسم، وعادةً ما تحتوي على بعض المعاملات التي يتم تهيئتها عند استدعائها مع بعض الوسائط. على غرار لغة C++، فإن الدوال التي لا تُعيد أي قيمة يكون نوع إرجاعها مُعلنًا كـ `null` void. على عكس لغة C++، لا يُسمح للدوال في جافا أن تحتوي على قيم افتراضية للمعاملات ، وعادةً ما يتم تحميل الدوال بشكل زائد.

class Foo { int bar ( int a , int b ) { return ( a * 2 ) + b ; }// دالة مُحمّلة بنفس الاسم ولكن بمجموعة وسائط مختلفة int bar ( int a ) { return a * 2 ; } }

يتم استدعاء الطريقة باستخدام .الترميز على كائن، أو في حالة الطريقة الثابتة، يتم استدعاؤها أيضًا على اسم فئة.

Foo foo = new Foo ( ); int result = foo.bar ( 7 , 2 ); // يتم استدعاء دالة غير ثابتة على fooint finalResult = Math.abs ( result ) ; // استدعاء دالة ثابتة

تشير الكلمة throwsالمفتاحية إلى أن الدالة تُطلق استثناءً. يجب إدراج جميع الاستثناءات التي تم التحقق منها في قائمة مفصولة بفواصل.

استيراد java.io.File ؛ استيراد java.io.IOException ؛ استيراد java.util.zip.DataFormatException ؛// يشير إلى إمكانية حدوث استثناءات IOException و DataFormatException void operatOnFile ( File f ) throws IOException , DataFormatException { // ... }
المُعدِّلات
  • abstract- لا يمكن أن توجد الطرق المجردة إلا في الفئات المجردة ، وهذه الطرق ليس لها جسم ويجب تجاوزها في فئة فرعية ما لم تكن مجردة في حد ذاتها.
  • staticيجعل هذا الأسلوب ثابتًا ويمكن الوصول إليه دون إنشاء نسخة من الفئة. مع ذلك، لا يمكن للأساليب الثابتة الوصول إلى الأعضاء غير الثابتة في نفس الفئة.
  • final- يُعلن أنه لا يمكن تجاوز الطريقة في فئة فرعية.
  • nativeيشير هذا إلى أن هذه الطريقة مُنفذة عبر JNI في كود يعتمد على النظام الأساسي. ويتم التنفيذ الفعلي خارج كود Java، ولا تحتوي هذه الطرق على جسم.
  • strictfp- يُعلن عن التزام صارم بمعيار IEEE 754 في تنفيذ عمليات الفاصلة العائمة. أصبح الآن قديماً.
  • synchronized- يُعلن هذا الشرط أن الخيط الذي يُنفذ هذه الطريقة يجب أن يحصل على مُراقب. بالنسبة synchronizedللطرق، يكون المُراقب هو نسخة الفئة، أو java.lang.Classإذا كانت الطريقة ثابتة.
  • مُعدِّلات الوصول - مماثلة لتلك المستخدمة مع الفئات.
الأساليب النهائية

لا يمكن تجاوز أو إخفاء أي دالة نهائية بواسطة الفئات الفرعية. [ 20 ] يُستخدم هذا لمنع حدوث سلوك غير متوقع من فئة فرعية تُغير دالة قد تكون حاسمة لوظيفة الفئة أو اتساقها. [ 21 ]

مثال:

public class Base { public void foo () { // ... }public final void bar () { // ... }public static void baz () { // ... }public static final void qux () { // ... } }public class Derived extends Base { // حسنًا، تجاوز Base::foo() @Override public void foo () { // ... }// ممنوع @Override public void bar () { // ... }// حسنًا، تم تجاوز Base::baz() @Override public static void baz () { // ... }// ممنوع @Override public static void qux () { // ... } }

من المفاهيم الخاطئة الشائعة أن تعريف دالة ما على أنها `final` finalيُحسّن الكفاءة، إذ يسمح للمُصرّف بإدراج الدالة مباشرةً أينما تم استدعاؤها (انظر التوسيع المضمن ). ولأن الدالة تُحمّل أثناء التشغيل ، فإن المُصرّفات لا تستطيع فعل ذلك. بيئة التشغيل ومُصرّف JIT هما فقط من يعرفان تحديدًا الفئات التي تم تحميلها، وبالتالي فهما فقط من يستطيعان اتخاذ القرارات بشأن وقت التضمين، وما إذا كانت الدالة نهائية أم لا. [ 22 ]

تُعدّ مُجمّعات لغة الآلة التي تُنتج شفرة آلة قابلة للتنفيذ مباشرةً ومُخصصة لمنصة مُعينة ، استثناءً. عند استخدام الربط الثابت ، يُمكن للمُجمّع أن يفترض بأمان إمكانية تضمين الدوال والمتغيرات القابلة للحساب في وقت الترجمة .

المعاملات المتغيرة

أُضيفت هذه الميزة اللغوية في J2SE 5.0 . يُمكن تعريف الوسيط الأخير للدالة كمعامل ذي عدد متغير من المعاملات ، وفي هذه الحالة تُصبح الدالة دالة ذات عدد متغير من المعاملات (مقارنةً بالدوال ذات العدد الثابت من المعاملات) أو ببساطة دالة متعددة المعاملات . يسمح هذا بتمرير عدد متغير (قد يكون صفرًا) من القيم، من النوع المُعلن، إلى الدالة كمعاملات. ستكون هذه القيم متاحة داخل الدالة كمصفوفة.

// الأرقام تمثل الوسائط المتغيرة void printReport ( String header , int ... numbers ) { // تظهر الأرقام كـ int[] System . out . println ( header ); for ( int num : numbers ) { System . out . println ( num ); } }// استدعاء دالة printReport ذات الوسائط المتغيرة ( "بيانات التقرير" , 74 , 83 , 25 , 96 );

الحقول

يمكن تعريف الحقول، أو متغيرات الفئة ، داخل جسم الفئة لتخزين البيانات.

class Foo { double bar ; }

يمكن تهيئة الحقول مباشرةً عند تعريفها.

class Foo { double bar = 2.3 ; }
المُعدِّلات
  • static- يجعل الحقل عضوًا ثابتًا.
  • final- يسمح بتهيئة الحقل مرة واحدة فقط في المُنشئ أو داخل كتلة التهيئة أو أثناء تعريفه، أيهما أسبق.
  • transient- يشير إلى أن هذا الحقل لن يتم تخزينه أثناء عملية التسلسل .
  • volatile- إذا تم تعريف حقل volatile، فسيتم ضمان أن ترى جميع الخيوط قيمة متسقة للمتغير.

الميراث

في لغة جافا، لا يمكن للفئات أن ترث إلا من فئة واحدة . يمكن اشتقاق فئة من أي فئة غير مُعَلَّمة بـ ` final. يُعلن عن الوراثة باستخدام extendsالكلمة المفتاحية `. يمكن للفئة أن تشير إلى نفسها باستخدام الكلمة thisالمفتاحية `، وإلى فئتها الأصلية المباشرة باستخدام الكلمة superالمفتاحية `.

class Foo {}class Foobar extends Foo {}

إذا لم يحدد الصنف صنفه الأصلي، فإنه يرث ضمنيًا من java.lang.Objectالصنف الأصلي. وبالتالي، فإن جميع الأصناف في جافا هي أصناف فرعية من Objectالصنف الأصلي.

إذا لم يكن للفئة الأصلية مُنشئ بدون مُعاملات، فيجب على الفئة الفرعية تحديد مُنشئ الفئة الأصلية الذي ستستخدمه في مُنشئاتها. على سبيل المثال:

class Foo { public Foo ( int n ) { // قم بشيء ما باستخدام n } }class Foobar extends Foo { private int number ; // لا تحتوي الفئة الأصلية على مُنشئ بدون مُعاملات // لذلك علينا تحديد مُنشئ الفئة الأصلية الذي سنستخدمه وكيفية استخدامهpublic Foobar ( int number ) { super ( number ); this . number = number ; } }
أساليب التجاوز

على عكس لغة C++، فإن جميع finalالطرق غير الافتراضية في Java هي طرق افتراضية ويمكن تجاوزها بواسطة الفئات الوارثة.

class Operation { public int doSomething () { return 0 ; } }class NewOperation extends Operation { @Override public int doSomething () { return 1 ; } }
الفئات المجردة

الصنف المجرد هو صنف غير مكتمل، أو يُعتبر غير مكتمل، ولا يمكن إنشاء مثيل له (مباشرة). [ 23 ]

تحتوي الفئة Xعلى أساليب مجردة إذا كان أي مما يلي صحيحًا:

  • Xيتضمن صراحةً تعريفًا لطريقة مجردة.
  • أي من Xالفئات العليا في سلسلة الوراثة تحتوي على طريقة مجردة Xولا تقوم بتعريف أو وراثة طريقة تقوم بتنفيذها.
  • الواجهة الفائقة المباشرة Xلـ تعلن أو ترث طريقة (وهي بالتالي مجردة بالضرورة) Xولا تعلن أو ترث طريقة تقوم بتنفيذها.
  • يمكن إنشاء فئة فرعية من فئة مجردة ليست مجردة في حد ذاتها، مما يؤدي إلى تنفيذ مُنشئ للفئة المجردة، وبالتالي تنفيذ مُهيئات الحقول لمتغيرات مثيل تلك الفئة.
package org.wikipedia.examples ;public class MyAbstractClass { private static final String hello ;static { System.out.printf ( " % s : static block runtime%n" , MyAbstractClass.class.getName ( ) ) ; hello = String.format ( " hello from % s " , MyAbstractClass.class.getName ( ) ) ; }{ System.out.printf ( " % s : instance block runtime% n " , MyAbstractClass.class.getName ( ) ) ; }public AbstractClass ( ) { System.out.printf ( " % s : constructor runtime%n " , MyAbstractClass.class.getName ( ) ) ; }public static void hello () { System . out . println ( hello ); } }
package org.wikipedia.examples ;public class MyCustomClass extends MyAbstractClass {static { System.out.printf ( " % s : static block runtime% n " , MyCustomClass.class.getName ( ) ) ; }{ System.out.printf ( " % s : instance block runtime%n " , MyCustomClass.class.getName ( ) ) ; }public CustomClass () { System . out . printf ( "%s: constructor runtime%n" , MyCustomClass . class . getName ()); }public static void main ( String [] args ) { MyCustomClass nc = new MyCustomClass (); hello (); MyAbstractClass . hello (); // صالحة أيضًا } }

الناتج:

org.wikipedia.examples.MyAbstractClass: وقت تشغيل الكتلة الثابتة org.wikipedia.examples.MyCustomClass: وقت تشغيل الكتلة الثابتة org.wikipedia.examples.MyAbstractClass: كتلة مثيل وقت التشغيل org.wikipedia.examples.MyAbstractClass: وقت تشغيل المُنشئ org.wikipedia.examples.MyCustomClass: كتلة مثيل وقت التشغيل org.wikipedia.examples.MyCustomClass: وقت تشغيل المُنشئ مرحباً من org.wikipedia.examples.MyAbstractClass 

التعدادات

أُضيفت هذه الميزة اللغوية في J2SE 5.0 . من الناحية التقنية، تُعدّ التعدادات نوعًا من الأصناف التي تحتوي على ثوابت تعدادية ضمن بنيتها. يُعرّف كل ثابت تعدادي نسخةً من نوع التعداد. لا يمكن إنشاء نسخ من أصناف التعداد في أي مكان آخر سوى داخل صنف التعداد نفسه.

enum Season { WINTER , SPRING , SUMMER , AUTUMN , }

يُسمح لثوابت التعداد بامتلاك دوال إنشاء، والتي يتم استدعاؤها عند تحميل الفئة:

public enum Season { WINTER ( "بارد" ), SPRING ( "أكثر دفئًا" ), SUMMER ( "حار" ), AUTUMN ( "أكثر برودة" );الموسم ( وصف السلسلة ) { هذا.الوصف = الوصف ؛ }وصف السلسلة النصية النهائية الخاصة ؛public String getDescription () { return description ; } }

يمكن أن تحتوي التعدادات على أجسام فئات، وفي هذه الحالة يتم التعامل معها كفئات مجهولة تمتد من فئة التعداد:

public enum Season { WINTER { @Override String getDescription () { return "cold" } }, SPRING { @Override String getDescription () { return "warmer" ; } }, SUMMER { @Override String getDescription () { return "hot" ; } }, FALL { @Override String getDescription () { return "cooler" ; } };abstract String getDescription (); }

واجهات

الواجهات هي أنواع لا تحتوي على حقول، وعادةً ما تُعرّف عددًا من الدوال دون تنفيذ فعلي. وهي مفيدة لتحديد عقد مع أي عدد من التنفيذات المختلفة. كل واجهة مجردة ضمنيًا. يُسمح لدوال الواجهة بامتلاك مجموعة فرعية من مُعدِّلات الوصول، وذلك حسب إصدار اللغة، strictfpوهو ما يُحقق نفس تأثير الأصناف، وكذلك staticمنذ Java SE 8.

واجهة ActionListener { int ACTION_ADD = 0 ; int ACTION_REMOVE = 1 ; void actionSelected ( int action ); }

تنفيذ واجهة

تُنفَّذ الواجهة بواسطة فئة باستخدام implementsالكلمة المفتاحية `interface`. يُسمح بتنفيذ أكثر من واجهة، وفي هذه الحالة تُكتب الواجهات بعد implementsالكلمة المفتاحية `interface` في قائمة مفصولة بفواصل. يجب على الفئة التي تُنفِّذ واجهةً ما إعادة تعريف جميع توابعها، وإلا فيجب تعريفها كفئة مجردة.

واجهة RequestListener { int requestReceived (); }class ActionHandler implements ActionListener , RequestListener { public void actionSelected ( int action ) { // ... }public int requestReceived () { // ... } }// استدعاء الدالة المُعرَّفة بواسطة الواجهة // يمكن تمثيل ActionHandler كـ RequestListener... RequestListener listener = new ActionHandler (); // ...وبالتالي من المعروف أنه يُنفِّذ الدالة requestReceived() listener.requestReceived ( ) ;

الواجهات الوظيفية وتعبيرات لامدا

أُضيفت هذه الميزات مع إصدار Java SE 8. تُصبح الواجهة تلقائيًا واجهةً وظيفيةً إذا كانت تُعرّف طريقةً واحدةً فقط (باستثناء الطرق الموروثة java.lang.Object). في هذه الحالة، يُمكن تمثيل التنفيذ بتعبير لامدا بدلًا من تنفيذه في فئة جديدة، مما يُبسّط كتابة التعليمات البرمجية بأسلوب البرمجة الوظيفية . يُمكن إضافة تعليق java.lang.FunctionalInterfaceتوضيحي اختياري إلى الواجهات الوظيفية، يُخبر المُصرّف بالتحقق مما إذا كانت الواجهة تُطابق تعريف الواجهة الوظيفية.

// واجهة وظيفية @FunctionalInterface interface Calculation { int calculate ( int someNumber , int someOtherNumber ); }// دالة تقبل هذه الواجهة كمعامل int runCalculation ( Calculation calculation ) { return calculation . calculate ( 1 , 2 ); }// استخدام تعبير لامدا لاستدعاء الدالة runCalculation (( number , otherNumber ) -> number + otherNumber );// الكود المكافئ الذي يستخدم فئة مجهولة بدلاً من ذلك runCalculation ( new Calculation () { @Override public int calculate ( int someNumber , int someOtherNumber ) { return someNumber + someOtherNumber ; } })

لا يلزم تحديد أنواع معاملات دالة لامدا بشكل كامل، ويمكن استنتاجها من الواجهة التي تُنفذها، ولكن لا يوجد مكان لتحديد نوع القيمة المُعادة من دالة لامدا بشكل صريح (إذ يُستنتج هذا النوع تلقائيًا). يمكن كتابة جسم دالة لامدا بدون كتلة الجسم أو عبارة returnإذا كانت مجرد تعبير. كذلك، بالنسبة للواجهات التي تحتوي على معامل واحد فقط في الدالة، يمكن حذف الأقواس الدائرية. [ 24 ]

// نفس الاستدعاء كما في الأعلى، ولكن مع تحديد الأنواع بالكامل وكتلة نصية runCalculation (( int number , int otherNumber ) -> { return number + otherNumber ; });// واجهة وظيفية ذات دالة تأخذ مُعاملًا واحدًا فقط interface StringExtender { String extendString ( String input ); }// تهيئة متغير من هذا النوع باستخدام تعبير لامدا StringExtender extender = input -> input + " Extended" ;

لا يمكن للعبارات اللامدا تحديد throwsبنود. تُنفذ اللامدا واجهة وظيفية مستهدفة (مثل java.lang.Runnable، إلخ). لا تُعد اللامدا تعبيرات كاملة عن أنواع محددة، بل هي تعبيرات متعددة الأنواع، يتأثر نوعها بالنوع المستهدف المحيط بها بدلاً من محتواها الخاص. [ 25 ]

استيراد java.util.function.Function ;// غير صالح، لأن تعابير لامدا نفسها ليس لها نوع مستقل var f = ( int x ) -> x + 1 ; // يجب أن يكون بدلاً من ذلك: Function < Integer , Integer > f = x -> x + 1 ;

إذا نفّذت دالة لامدا واجهة وظيفية تمتد من واجهة أخرى java.lang.Serializable، فعند تسلسل دالة لامدا، تصبح java.lang.invoke.SerializedLambda[ 26 ] ، مُلتقطةً معلوماتٍ حول دالة لامدا نفسها، وتُسمى "شكلها المُسلسل". [ 27 ] هذا ضروري، لأن فئات تنفيذ لامدا اصطناعية وخاصة بآلة جافا الافتراضية (JVM)، وبالتالي يجب إعادة بنائها بدقة في استدعاء آخر لآلة جافا الافتراضية. وكما هو الحال في لغة C++، فإن أسماء أنواع لامدا اصطناعية ومولدة بواسطة المُصرّف مع تفاصيل تنفيذ غير مُحددة.

Runnable r = ( ) -> System.out.println ( " Hello " ) ;// يمكن طباعة شيء مثل: // class org.wikipedia.examples.Main$$Lambda$1/ 0x0000000800b00440 System.out.println ( r.getClass ( ) ) ;

لا تقوم الدوال اللامدا بإنشاء ملفات الفئات ، بل تقوم بإصدار invokedynamicتعليمات على JVM، والتي يستخدمها وقت التشغيل لإنشاء فئة تنفيذ مناسبة.

عادةً ما تكون دوال لامدا الملتقطة كائنات منفصلة، ​​نظرًا لاحتياجها إلى حالة ملتقطة مخزنة، ومع ذلك، قد تكون دوال لامدا غير الملتقطة كائنات أحادية .

Runnable r1 = () -> {}; Runnable r2 = () -> {};System.out.println ( r1 == r2 ) ; // قد يطبع القيمة true أو false؛ يتم تحديد ذلك بواسطة JVM

ومع ذلك، على عكس لغة C++، فإن أنواع lambda ليست جزءًا من نموذج اللغة؛ لا يمكن الاعتماد على أي شيء يتعلق بفئة وقت التشغيل الخاصة بها، بينما في لغة C++ لا يزال من الممكن استخراج نوع lambda للحصول على نوع إغلاق فريد حقيقي؛ لا يمكن الإشارة إلى decltypelambda في التعليمات البرمجية.java.lang.Class<?>

مراجع المنهج

تسمح لغة جافا بالإشارة إلى الدوال باستخدام المعامل ` <namespace>` ::(وهو يختلف عن معامل تحديد مساحة الاسم في لغة C++ ::). ليس من الضروري استخدام تعابير لامدا عندما توجد بالفعل دالة مُسماة متوافقة مع الواجهة. يمكن تمرير هذه الدالة بدلاً من تعبير لامدا باستخدام مرجع دالة. توجد عدة أنواع من مراجع الدوال:

نوع المرجعمثاللامدا المكافئ
ثابتInteger::sum(m,n)->m+n
مرتبط ب"LongString"::substringi->"LongString".substring(i)
غير مجلدString::isEmptys->s.isEmpty()
مُنشئ الفئةArrayList<String>::newlen->newArrayList<String>(len)
مُنشئ المصفوفةString[]::newlen->newString[len]

يمكن استبدال الكود أعلاه، الذي يستدعي الدوال، runCalculationبما يلي باستخدام مراجع الأساليب:

تشغيل الحساب ( المجموع العددي :: 

لاحظ أنه في لغة جافا، لا تُعتبر الدوال البانية أساليب، وبالتالي X::Xفهي غير موجودة؛ يتم استرداد مرجع الدالة البانية باستخدام X::new.

الميراث

يمكن للواجهات أن ترث من واجهات أخرى تمامًا مثل الأصناف. على عكس الأصناف، يُسمح لها بالوراثة من عدة واجهات. مع ذلك، من الممكن أن تحتوي عدة واجهات على حقل بنفس الاسم، وفي هذه الحالة يصبح هذا الحقل عضوًا واحدًا غامضًا لا يمكن الوصول إليه.

/* يجب على الفئة التي تُنفذ هذه الواجهة أن تُنفذ أساليب كل من ActionListener و RequestListener */ interface EventListener extends ActionListener , RequestListener { }

الطرق الافتراضية

أضافت Java SE 8 ميزة الطرق الافتراضية للواجهات، مما يسمح للمطورين بإضافة طرق جديدة إلى الواجهات الموجودة دون التأثير على توافقها مع الفئات التي تُنفذ الواجهة بالفعل. على عكس طرق الواجهة العادية، تحتوي الطرق الافتراضية على جسم يتم استدعاؤه في حال عدم قيام الفئة المُنفذة بتجاوزها.

واجهة StringManipulator { String extendString ( String input ); // دالة اختيارية التنفيذ String shortenString ( String input ) { return input . substring ( 1 ) ; } }// هذه فئة صالحة على الرغم من عدم تنفيذها لجميع الطرق class PartialStringManipulator implements StringManipulator { @Override public String extendString ( String input ) { return String . format ( "%s Extended" , input ); } }

الأساليب الثابتة

الأساليب الثابتة هي ميزة لغوية أخرى تم تقديمها في Java SE 8. وهي تعمل بنفس الطريقة تمامًا كما في الفئات.

interface StringUtils { static String shortenByOneSymbol ( String input ) { return input . substring ( 1 ); } }StringUtils.shortenByOneSymbol ( "Test " ) ;

طرق خاصة

أُضيفت الدوال الخاصة في إصدار Java 9. يمكن أن تحتوي الواجهة على دالة مُعرّفة كخاصة، وفي هذه الحالة لن تكون مرئية للفئات الوارثة. ويمكن استدعاؤها من الدوال الافتراضية لأغراض إعادة استخدام الكود.

واجهة Logger { افتراضي void logError () { log ( Level . ERROR ); }void logInfo ( ) { log ( Level . INFO ); }private void log ( Level level ) { SystemLogger . log ( level . id ); } }

التعليقات التوضيحية

تُعدّ التعليقات التوضيحية في لغة جافا وسيلةً لتضمين البيانات الوصفية في الكود. وقد أُضيفت هذه الميزة اللغوية في J2SE 5.0 .

أنواع التعليقات التوضيحية

تحتوي لغة جافا على مجموعة من أنواع التعليقات التوضيحية المُعرَّفة مسبقًا، ولكن يُسمح لها بتعريف أنواع جديدة. يُعدّ تعريف نوع التعليق التوضيحي نوعًا خاصًا من تعريف الواجهة. ويتم تعريفها بنفس طريقة تعريف الواجهات، باستثناء أن الكلمة interfaceالمفتاحية مسبوقة بالعلامة @`-`. تُعتبر تعليقات جافا التوضيحية واجهات، وهي مُشتقة ضمنيًا من java.lang.annotation.Annotationأي شيء آخر ولا يُمكن اشتقاقها منه. على عكس تعليقات C++ التوضيحية، التي يُمكن أن تكون أي كائن، لا يُمكن إنشاء كائن حقيقي من تعليقات جافا التوضيحية في وقت التشغيل.

@interface BlockingOperations {}

قد تحتوي التعليقات التوضيحية على نفس التصريحات في متنها كما في الواجهات الشائعة، بالإضافة إلى أنه يُسمح لها بتضمين تعدادات وتعليقات توضيحية. والفرق الرئيسي هو أن تصريحات الأساليب المجردة يجب ألا تحتوي على أي معلمات أو تُطلق أي استثناءات. كما يمكن أن تحتوي على قيمة افتراضية، يتم تحديدها باستخدام الكلمة defaultالمفتاحية بعد اسم الأسلوب.

@interface BlockingOperations { boolean fileSystemOperations (); boolean networkOperations () default false ; }
استخدام التعليقات التوضيحية

يمكن استخدام التعليقات التوضيحية في أي نوع من أنواع التصريحات، سواءً كانت حزمة، أو فئة (بما في ذلك التعدادات)، أو واجهة (بما في ذلك التعليقات التوضيحية)، أو حقل، أو دالة، أو مُعامل، أو مُنشئ، أو متغير محلي. كما يمكن استخدامها مع ثوابت التعداد. تُصرَّح التعليقات التوضيحية باستخدام علامة @قبل اسم نوع التعليق التوضيحي، ثم تُكتب أزواج العنصر والقيمة بين قوسين. يجب تعيين قيمة لجميع العناصر التي ليس لها قيمة افتراضية.

@BlockingOperations ( fileSystemOperations , // إلزامي networkOperations = true // اختياري ) void openOutputStream () { // دالة مُعَلَّمة }

إلى جانب الصيغة العامة، توجد صيغتان أخريان لتعريف التعليقات التوضيحية، وهما اختصارات. التعليق التوضيحي للعلامة هو صيغة مختصرة، ويُستخدم عندما لا يتم تعيين أي قيم للعناصر:

@Unused // اختصار لـ @Unused() void travelToJupiter () {}

يُطلق على الشكل المختصر الآخر اسم " التعليق التوضيحي أحادي العنصر" . ويُستخدم مع أنواع التعليقات التوضيحية التي تحتوي على عنصر واحد فقط، أو في حالة وجود عناصر متعددة، ولكن عنصر واحد فقط منها يفتقر إلى قيمة افتراضية. في نموذج التعليق التوضيحي أحادي العنصر، يُحذف اسم العنصر وتُكتب القيمة فقط بدلاً منه.

/* مكافئ لـ @BlockingOperations(fileSystemOperations = true). يحتوي networkOperations على قيمة افتراضية ولا يلزم تعيين قيمة له */@BlockingOperations ( true ) void openOutputStream () {}

الأدوية الجنيسة

البرمجة العامة (الأنواع العامة)، أو الأنواع المُعَلمة، أو تعدد الأشكال المُعَلم ، هي إحدى الميزات الرئيسية التي تم تقديمها في J2SE 5.0 . قبل ظهور الأنواع العامة، كان من الضروري تعريف جميع الأنواع بشكل صريح. مع ظهورها، أصبح من الممكن العمل بطريقة مماثلة مع أنواع مختلفة دون الحاجة إلى تعريف الأنواع بدقة. الهدف الرئيسي من الأنواع العامة هو ضمان سلامة الأنواع واكتشاف أخطاء وقت التشغيل أثناء الترجمة. على عكس قوالب C++ ، لا تُنشئ الأنواع العامة تخصيصًا لكل نوع، وعلى عكس C#، لا يتم تجسيد الأنواع العامة ، ولا تتوفر معلومات عن المعاملات المستخدمة في وقت التشغيل بسبب حذف النوع [ 28 ] (بينما توفر Kotlin ، وهي لغة أخرى تعمل على JVM، أنواعًا عامة مُجسّدة ، إلا أنها تحقق ذلك عن طريق تضمين النوع في موقع الاستدعاء [ 29 ] ). يعود ذلك إلى أن Java، تاريخيًا، كانت تفتقر إلى الأنواع العامة تمامًا. وبالتالي يتم حذف الأنواع العامة في وقت التشغيل للسماح للفئة العامة X<T>بأن تكون متوافقة مع X.

على سبيل المثال، قبل إدخال الأنواع العامة، كان إطار عمل مجموعات جافا يخزن كل شيء على شكل java.lang.Object.

استيراد java.util.ArrayList ؛ استيراد java.util.List ؛List names = new ArrayList ( ); names.add ( " Alice " ); names.add ( " Bob" ); String first = ( String ) names.get ( 0 ) ; // first = "Alice " names.add ( 1 ) ; // مسموح

أثناء التشغيل، تظهر الأنواع العامة كحد أدنى لمعامل النوع (إذا لم يُحدد حد أدنى، فهذا ضمنيًا java.lang.Object). ولأن الأنواع العامة تُحذف، فلا يمكن إنشاء نوع عام (مثل ) أو التحقق من الأنواع مقابل تخصيص (مثل ).newT()if(namesinstanceofList<String>)

كذلك، لا يجوز للفئات العامة أن ترث من فئة أخرى java.lang.Throwable. [ 30 ] والسبب في ذلك هو أن الاستثناء العام FooException<T>سيؤدي إلى حذف FooException<String>الاستثناءين FooException<Integer>من النوع نفسه أثناء التشغيل، مما يجعل التمييز بينهما غير ممكن. مع ذلك، يمكن طرح استثناء من نوع عام (طالما أنه محصور ضمن نطاق معين java.lang.Throwable). على سبيل المثال، يُستخدم النمط التالي، المعروف أحيانًا باسم إعادة طرح الاستثناء العام أو الطرح الخفي ، لتجاوز الاستثناءات المُدققة تمامًا، كما هو الحال في سمة Project Lombok@SneakyThrows . [ 31 ]

static < T extends Throwable > void sneakyThrow ( Throwable t ) throws T { throw ( T ) t ; }

يؤدي هذا Tإلى مسح جميع القيم java.lang.Throwable، متجاوزًا آلية الاستثناء المدققة (التي تفرض فقط على الأنواع التي لا تنحدر من java.lang.Errorأو java.lang.RuntimeException) تمامًا.

الفئات العامة

يمكن تحديد خصائص الفئات بإضافة متغير نوع داخل قوسين زاويين ( <و >) بعد اسم الفئة. يتيح ذلك استخدام متغير النوع هذا في أعضاء الفئة بدلاً من الأنواع الفعلية. يمكن أن يكون هناك أكثر من متغير نوع واحد، وفي هذه الحالة يتم تعريفها في قائمة مفصولة بفواصل.

من الممكن تقييد متغير نوع بنوع فرعي من فئة محددة، أو تعريف واجهة يجب أن يُنفذها هذا النوع. في هذه الحالة، يُلحق اسم المتغير بالكلمة extendsالمفتاحية متبوعة باسم الفئة أو الواجهة. إذا كان المتغير مقيدًا بكل من الفئة والواجهة، أو إذا كانت هناك عدة واجهات، يُكتب اسم الفئة أولًا، متبوعًا بأسماء الواجهات، مع &استخدام علامة (-) كفاصل (بطريقة تُشبه نوع التقاطع ).

/* يحتوي هذا الصنف على متغيرين من النوع، T و V. يجب أن يكون T نوعًا فرعيًا من ArrayList وأن يُنفذ واجهة Formattable */ public class Mapper < T extends ArrayList & Formattable , V > { public void add ( T array , V item ) { // يحتوي المصفوفة على دالة add لأنها صنف فرعي من ArrayList array.add ( item ) ; } }

When a variable of a parameterized type is declared or an instance is created, its type is written exactly in the same format as in the class header, except the actual type is written in the place of the type variable declaration.

/* Mapper is created with CustomList as T and Integer as V.CustomList must be a subclass of ArrayList and implement Formattable */Mapper<CustomList,Integer>mapper=newMapper<CustomList,Integer>();

Since Java SE 7, it is possible to use a diamond (<>) in place of type arguments, in which case the latter will be inferred. This is sometimes called the "diamond operator", even though it is not actually an operator, but rather an empty type list. The following code in Java SE 7 is equivalent to the code in the previous example:

Mapper<CustomList,Integer>mapper=newMapper<>();

When declaring a variable for a parameterized type, it is possible to use wildcards instead of explicit type names. Wildcards are expressed by writing ? sign instead of the actual type. It is possible to limit possible types to the subclasses or superclasses of some specific class by writing the extends keyword or the super keyword correspondingly followed by the class name.

/* Any Mapper instance with CustomList as the first parametermay be used regardless of the second one.*/Mapper<CustomList,?>mapper;mapper=newMapper<CustomList,Boolean>();mapper=newMapper<CustomList,Integer>();/* Will not accept types that use anything buta subclass of Number as the second parameter */voidaddMapper(Mapper<?,?extendsNumber>mapper){}

Generic methods and constructors

Usage of generics may be limited to some particular methods, this concept applies to constructors as well. To declare a parameterized method, type variables are written before the return type of the method in the same format as for the generic classes. In the case of constructor, type variables are declared before the constructor name.

classMapper{// The class is not generic, the constructor is<T,V>Mapper(Tarray,Vitem){}}/* This method will accept only arrays of the same type asthe searched item type or its subtype */static<T,VextendsT>booleancontains(Titem,V[]arr){for(TcurrentItem:arr){if(item.equals(currentItem)){returntrue;}}returnfalse;}

Generic interfaces

Interfaces can be parameterized in the similar manner as the classes.

interfaceExpandable<TextendsNumber>{voidaddItem(Titem);}// This class is parameterizedclassMyArray<TextendsNumber>implementsExpandable<T>{voidaddItem(Titem){}}// And this is not and uses an explicit type insteadclassIntegerArrayimplementsExpandable<Integer>{voidaddItem(Integeritem){}}

See also

Notes

  1. Note that in class files, the dots appear as slashes. For example, Object[] becomes [Ljava/lang/Object;

References

  1. 12Oracle Corporation. "Chapter 6. The Java Virtual Machine Instruction Set". docs.oracle.com. Oracle Corporation. Retrieved May 26, 2026.
  2. Mark Reinhold (March 8, 2016). "The State of the Module System". Oracle Corporation. Retrieved February 18, 2017.
  3. "JEP 396: Strongly Encapsulate JDK Internals by Default". Retrieved February 6, 2021.
  4. "JDK Module Summary". Oracle Corporation. June 24, 2016. Archived from the original on December 8, 2015. Retrieved February 18, 2017.
  5. "JEP 494: Module Import Declarations (Second Preview)". openjdk.org.
  6. "Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)". docs.oracle.com. Oracle and/or its affiliates. Archived from the original on June 24, 2015. Retrieved June 16, 2015.
  7. "The switch Statement (The Java™ Tutorials > Learning the Java Language > Language Basics)". docs.oracle.com. Archived from the original on March 15, 2010. Retrieved August 15, 2021.
  8. OpenJDK (September 23, 2025). "Release Note: Thread.stop Is Removed". bugs.openjdk.org. OpenJDK.
  9. Oracle Corporation. "Class ThreadDeath". docs.oracle.com. Oracle Corporation. Retrieved May 27, 2026.
  10. Oracle Corporation. "Class CompletableFuture<T>". docs.oracle.com. Oracle Corporation. Retrieved May 27, 2026.
  11. "Virtual Threads". Oracle Help Center. Retrieved September 10, 2024.
  12. "JEP 491: Synchronize Virtual Threads without Pinning". OpenJDK. Retrieved March 30, 2025.
  13. Owens, Sean. "Java and unsigned int, unsigned short, unsigned byte, unsigned long, etc. (Or rather, the lack thereof)". Archived from the original on February 20, 2009. Retrieved April 21, 2010.
  14. Oracle Corporation (March 17, 2026). "Class Arrays". docs.google.com. Oracle Corporation.
  15. Oracle Corporation (March 17, 2026). "Class Array". docs.google.com. Oracle Corporation.
  16. Oracle Corporation. "Chapter 8. Classes". docs.oracle.com. Oracle Corporation. Retrieved May 26, 2026.
  17. Oracle Corporation. "Chapter 2. The Structure of the Java Virtual Machine". docs.oracle.com. Oracle Corporation. Retrieved May 26, 2026.
  18. Sun Microsystems. "Avoid Finalizers". docs.oracle.com. Sun Microsystems. Retrieved May 27, 2026.
  19. Sun Microsystems. "Class Cleaner". docs.oracle.com. Sun Microsystems. Retrieved May 27, 2026.
  20. "Chapter 8. Classes". docs.oracle.com. Retrieved April 25, 2024.
  21. "Writing Final Classes and Methods". docs.oracle.com. Retrieved April 25, 2024.
  22. "Java theory and practice: Is that your final answer?". developer.ibm.com. Archived from the original on February 8, 2009. Retrieved April 25, 2024.
  23. Oracle Corporation. "8.1.1.1 - abstract Classes". docs.oracle.com. Oracle Corporation. Retrieved May 27, 2026.
  24. "Lambda Expressions (The Java™ Tutorials > Learning the Java Language > Classes and Objects)". docs.oracle.com. Archived from the original on June 16, 2020. Retrieved August 8, 2021.
  25. Oracle Corporation. "Chapter 15. Expressions". docs.oracle.com. Oracle Corporation. Retrieved May 31, 2026.
  26. Oracle Corporation. "Class SerializedLambda". docs.oracle.com. Oracle Corporation. Retrieved May 31, 2026.
  27. Oracle Corporation. "Serialized Form". docs.oracle.com. Oracle Corporation. Retrieved May 31, 2026.
  28. "Generics in the Run Time (C# Programming Guide)". Archived from the original on March 10, 2016. Retrieved March 9, 2016.
  29. JetBrains sro (14 ديسمبر 2024). "الأنواع العامة: في، خارج، أين" . kotlinlang.org . JetBrains sro
  30. شركة أوراكل. "القيود المفروضة على الأنواع العامة" . docs.oracle.com . شركة أوراكل . تم الاطلاع عليه بتاريخ 28 مايو 2026 .
  31. مشروع لومبوك (22 أبريل 2026). "نوع التعليق التوضيحي: رميات خفية" . projectlombok.org . مشروع لومبوك.

للمزيد من القراءة