2. أساسيات لغة Java
2.1. مقدمة
سنعتبر لغة Java في البداية لغة برمجة تقليدية. وسنتناول موضوع الكائنات لاحقًا.
في البرنامج، هناك أمران
- البيانات
- التعليمات التي تتعامل معها
نسعى عمومًا إلى فصل البيانات عن التعليمات:

2.2. بيانات Java
تستخدم Java أنواع البيانات التالية:
- الأعداد الصحيحة
- الأرقام العائمة
- الأحرف والسلاسل
- القيم المنطقية
- الكائنات
2.2.1. أنواع البيانات المحددة مسبقًا
النوع | الترميز | النطاق |
حرف | 2 بايت | حرف يونيكود |
int | 4 بايت | [-231، 231 -1] |
long | 8 بايت | [-263، 263 -1] |
بايت | 1 بايت | [-27 , 27 -1] |
قصير | 2 بايت | [-2(15)، 2(15)،-1] |
عائم | 4 بايت | [3.410⁻³⁸, 3.410³⁸] بالقيمة المطلقة |
مزدوج | 8 بايت | [1.7 × 10⁻³⁰⁸، 1.7 × 10³⁰⁸] من حيث القيمة المطلقة |
منطقية | 1 بت | صحيح، خطأ |
سلسلة | مرجع كائن | سلسلة |
تاريخ | مرجع كائن | تاريخ |
حرف | مرجع الكائن | حرف |
عدد صحيح | مرجع كائن | int |
طويل | مرجع كائن | long |
بايت | مرجع الكائن | بايت |
عدد عائم | مرجع الكائن | عدد عائم |
عدد مزدوج | مرجع كائن | double |
منطقية | مرجع كائن | منطقية |
2.2.2. ترميز البيانات الحرفية
عدد صحيح | 145، -7، 0xFF (سداسي عشري) |
عدد مزدوج | 134.789، -45E-18 (-45 × 10⁻¹⁸) |
عدد عائم | 134.789F، -45E-18F (-45 × 10⁻¹⁸) |
حرف | 'A'، 'b' |
سلسلة | "اليوم" |
منطقية | صحيح، خطأ |
تاريخ | تاريخ جديد (13،10،1954) (اليوم، الشهر، السنة) |
2.2.3. إعلان البيانات
2.2.3.1. دور الإعلانات
يقوم البرنامج بمعالجة البيانات التي تتميز باسم ونوع. يتم تخزين هذه البيانات في الذاكرة. عند ترجمة البرنامج، يقوم المترجم بتخصيص موقع في الذاكرة لكل جزء من البيانات يتميز بعنوان وحجم. ويقوم بذلك باستخدام الإعلانات التي وضعها المبرمج.
علاوة على ذلك، تسمح هذه الإعلانات للمترجم بالكشف عن أخطاء البرمجة. وبالتالي، فإن العملية
x=x*2;
غير صحيحة إذا كانت x سلسلة، على سبيل المثال.
2.2.3.2. إعلان الثوابت
صيغة إعلان الثابت هي كما يلي:
<mark style="background-color: #ffff00">النوع</mark>**<mark style="background-color: #ffff00"> النهائي </mark>**<mark style="background-color: #ffff00">الاسم=القيمة؛ </mark> //يحدد اسم الثابت=القيمة
مثال: final float PI=3.141592F;
ملاحظة
لماذا نعلن الثوابت؟
- سيكون البرنامج أسهل في القراءة إذا أُعطيت الثابتة اسمًا ذي معنى:
مثال: *<bdi dir="ltr" class="odt-ltr-term">final float VAT</bdi>\_rate=0.186F*;
- سيكون تعديل البرنامج أسهل إذا لزم تغيير "الثابت". وبالتالي، في الحالة السابقة، إذا تغير معدل ضريبة القيمة المضافة إلى 33٪، فإن التعديل الوحيد المطلوب سيكون تغيير العبارة التي تحدد قيمته:
*<bdi dir="ltr" class="odt-ltr-term">final float tax</bdi>\_rate=0.33F*;
إذا كنا قد استخدمنا 0.186 صراحةً في البرنامج، فسيتعين علينا عندئذٍ تعديل العديد من العبارات.
2.2.3.3. إعلان المتغيرات
يتم تحديد المتغير بواسطة اسم ويشير إلى نوع البيانات. يتكون اسم متغير Java من n حرفًا، يجب أن يكون أولها حرفًا، ويمكن أن يكون الباقي أحرفًا أو أرقامًا. تميز Java بين الأحرف الكبيرة والصغيرة. وبالتالي، فإن المتغيرين FIN و fin مختلفان.
يمكن تهيئة المتغيرات عند إعلانها. صيغة إعلان متغير واحد أو أكثر هي:
حيث يكون معرف_النوع نوعًا محددًا مسبقًا أو نوع كائن محدد من قبل المبرمج.
2.2.4. التحويلات بين الأرقام وسلاسل الأحرف
رقم -> سلسلة | "" + رقم |
سلسلة -> عدد صحيح | Integer.parseInt(سلسلة) |
سلسلة -> طويل | Long.parseLong(سلسلة) |
سلسلة -> دبل | Double.valueOf(سلسلة).doubleValue() |
سلسلة -> عدد عائم | Float.valueOf(سلسلة).floatValue() |
فيما يلي برنامج يوضح التقنيات الرئيسية للتحويل بين الأرقام والسلاسل. قد يفشل تحويل سلسلة إلى رقم إذا كانت السلسلة لا تمثل رقمًا صالحًا. يؤدي هذا إلى خطأ فادح، يُعرف باسم استثناء في Java. يمكن معالجة هذا الخطأ باستخدام كتلة try/catch التالية:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante
إذا لم ترمي الدالة استثناءً، ينتقل البرنامج إلى العبارة التالية؛ وإلا، فإنه يدخل إلى نص جملة catch ثم ينتقل إلى العبارة التالية. سنعود إلى معالجة الاستثناءات لاحقًا.
import java.io.*;
public class conv1{
public static void main(String arg[]){
String S;
final int i=10;
final long l=100000;
final float f=(float)45.78;
double d=-14.98;
// number --> string
S=""+i;
affiche(S);
S=""+l;
affiche(S);
S=""+f;
affiche(S);
S=""+d;
affiche(S);
//boolean --> string
final boolean b=false;
S=""+new Boolean(b);
affiche(S);
// string --> int
int i1;
i1=Integer.parseInt("10");
affiche(""+i1);
try{
i1=Integer.parseInt("10.67");
affiche(""+i1);
} catch (Exception e){
affiche("Erreur "+e);
}
// string --> long
long l1;
l1=Long.parseLong("100");
affiche(""+l1);
try{
l1=Long.parseLong("10.675");
affiche(""+l1);
} catch (Exception e){
affiche("Erreur "+e);
}
// chain --> double
double d1;
d1=Double.valueOf("100.87").doubleValue();
affiche(""+d1);
try{
d1=Double.valueOf("abcd").doubleValue();
affiche(""+d1);
} catch (Exception e){
affiche("Erreur "+e);
}
// string --> float
float f1;
f1=Float.valueOf("100.87").floatValue();
affiche(""+f1);
try{
d1=Float.valueOf("abcd").floatValue();
affiche(""+f1);
} catch (Exception e){
affiche("Erreur "+e);
}
}// fine hand
public static void affiche(String S){
System.out.println("S="+S);
}
}// end of class
النتائج هي كما يلي:
S=10
S=100000
S=45.78
S=-14.98
S=false
S=10
S=Erreur java.lang.NumberFormatException: 10.67
S=100
S=Erreur java.lang.NumberFormatException: 10.675
S=100.87
S=Erreur java.lang.NumberFormatException: abcd
S=100.87
S=Erreur java.lang.NumberFormatException: abcd
2.2.5. مصفوفات البيانات
مصفوفة Java هي كائن يسمح بتجميع البيانات من نفس النوع تحت معرف واحد. يتم إعلانها على النحو التالي:
Type Array[] = new Type[n] أو Type[] Array = new Type[n]
كلا الصيغتين صحيحتان. n هو عدد العناصر التي يمكن للمصفوفة استيعابها. تشير الصيغة Array[i] إلى العنصر الموجود في الفهرس i، حيث i يقع في النطاق [0,n-1]. أي إشارة إلى العنصر Array[i] حيث i لا يقع في النطاق [0,n-1] ستؤدي إلى حدوث استثناء.
يمكن تعريف مصفوفة ثنائية الأبعاد على النحو التالي:
Type Array[][] = new Type[n][p] أو Type[][] Array = new Type[n][p]
تشير صيغة Array[i] إلى عنصر البيانات i في Array حيث ينتمي i إلى الفاصل [0,n-1]. Array[i] هو نفسه مصفوفة: تشير Array[i][j] إلى العنصر j في Array[i]، حيث ينتمي j إلى الفاصل [0,p-1]. أي إشارة إلى عنصر في Array بمؤشرات غير صحيحة تؤدي إلى حدوث خطأ فادح.
فيما يلي مثال:
public class test1{
public static void main(String arg[]){
float[][] taux=new float[2][2];
taux[1][0]=0.24F;
taux[1][1]=0.33F;
System.out.println(taux[1].length);
System.out.println(taux[1][1]);
}
}
ونتيجة التنفيذ:
المصفوفة هي كائن له سمة "length": وهي تمثل حجم المصفوفة.
2.3. أوامر Java الأساسية
نحن نميز
- بين التعليمات الأساسية التي ينفذها الكمبيوتر
- الأوامر التي تتحكم في سير البرنامج.
تتضح التعليمات الأساسية عند النظر في بنية الحاسوب الصغير وأجهزته الطرفية.

-
قراءة المعلومات من لوحة المفاتيح
-
معالجة المعلومات
-
كتابة المعلومات على الشاشة
-
قراءة المعلومات من ملف على القرص
-
كتابة المعلومات إلى ملف على القرص
2.3.1. الكتابة على الشاشة
صيغة عبارة إخراج الشاشة هي كما يلي:
System.out.println(التعبير) أو System.err.println(التعبير)
حيث التعبير هو أي نوع بيانات يمكن تحويله إلى سلسلة ليتم عرضه على الشاشة. في المثال السابق، رأينا جملتي طباعة:
تقوم System.out بالكتابة إلى ملف نصي، والذي يكون الشاشة بشكل افتراضي. وينطبق الأمر نفسه على System.err. يتم تعيين أرقام (أو واصفات) 1 و 2 لهذه الملفات على التوالي. كما يتم التعامل مع دفق إدخال لوحة المفاتيح (System.in) كملف نصي، مع الواصف 0. يدعم كل من DOS و Unix توصيل الأوامر:
يتم توجيه (إعادة توجيه) كل ما يكتبه الأمر 1 إلى System.out إلى مدخل System.in للأمر 2. بعبارة أخرى، يقرأ الأمر 2 من System.in البيانات التي أنتجها الأمر 2 عبر System.out، والتي لم تعد معروضة على الشاشة. يستخدم هذا النظام على نطاق واسع في Unix. في هذا التوجيه، لا يتم إعادة توجيه دفق System.err: فهو يكتب إلى الشاشة. ولهذا السبب يتم استخدامه لكتابة رسائل الخطأ (ومن هنا جاء اسمه err): يمكننا أن نكون على يقين من أنه عند توجيه الأوامر، ستستمر رسائل الخطأ في الظهور على الشاشة. لذلك يجب أن نعتاد على كتابة رسائل الخطأ على الشاشة باستخدام دفق System.err بدلاً من دفق System.out.
2.3.2. قراءة البيانات المكتوبة على لوحة المفاتيح
يتم تمثيل تدفق البيانات الواردة من لوحة المفاتيح بواسطة الكائن System.in من النوع InputStream. ويسمح هذا النوع من الكائنات بقراءة البيانات حرفًا حرفًا. ويترك للمبرمج بعد ذلك استخراج المعلومات ذات الصلة من تدفق الأحرف هذا. ولا يسمح النوع InputStream بقراءة سطر نصي كامل دفعة واحدة. أما النوع BufferedReader فيسمح بذلك باستخدام الطريقة readLine.
لقراءة أسطر النص التي يتم إدخالها عبر لوحة المفاتيح، نقوم بإنشاء دفق إدخال جديد من النوع BufferedReader من دفق الإدخال System.in* من النوع InputStream*:
لن نشرح تفاصيل هذه العبارة هنا، لأنها تتضمن مفهوم إنشاء الكائنات. سنستخدمها كما هي.
قد يفشل إنشاء دفق: عندئذٍ يتم إنشاء خطأ فادح، يُسمى استثناءً في Java. كلما كان من المحتمل أن تولد إحدى الطرق استثناءً، يطلب مُركب Java أن يتعامل معها المبرمج. لذلك، لإنشاء دفق الإدخال السابق، يجب أن نكتب فعليًا:
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
System.err.println("Erreur " +e);
System.exit(1);
}
مرة أخرى، لن ندخل في تفاصيل معالجة الاستثناءات هنا. بمجرد إنشاء دفق IN السابق، يمكننا قراءة سطر من النص باستخدام العبارة:
يتم تخزين السطر الذي تمت كتابته على لوحة المفاتيح في المتغير ligne ويمكن بعد ذلك استخدامه بواسطة البرنامج.
2.3.3. مثال على الإدخال/الإخراج
فيما يلي برنامج يوضح عمليات الإدخال/الإخراج عبر لوحة المفاتيح/الشاشة:
import java.io.*; // required to use I/O streams
public class io1{
public static void main (String[] arg){
// write to System.out stream
Object obj=new Object();
System.out.println(""+obj);
System.out.println(obj.getClass().getName());
// write to System.err stream
int i=10;
System.err.println("i="+i);
// reading a line entered on the keyboard
String ligne;
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
affiche(e);
System.exit(1);
}
System.out.print("Tapez une ligne : ");
try{
ligne=IN.readLine();
System.out.println("ligne="+ligne);
} catch (Exception e){
affiche(e);
System.exit(2);
}
}//fine hand
public static void affiche(Exception e){
System.err.println("Erreur : "+e);
}
}//end of class
ونتيجة التنفيذ:
C:\Serge\java\bases\iostream>java io1
java.lang.Object@1ee78b
java.lang.Object
i=10
Tapez une ligne : je suis là
ligne=je suis là
التعليمات
تهدف إلى إظهار أنه يمكن عرض أي كائن. لن نحاول هنا شرح معنى ما يتم عرضه. لدينا أيضًا عرض قيمة الكائن في الكتلة:
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
affiche(e);
System.exit(1);
}
المتغير e هو كائن Exception يتم عرضه هنا باستخدام استدعاء display(e). لقد صادفنا عرض قيمة الاستثناء هذا في برنامج التحويل الذي رأيناه سابقًا، على الرغم من أننا لم نناقشه في ذلك الوقت.
2.3.4. تعيين قيمة تعبير إلى متغير
ما يهمنا هنا هو العملية variable=expression;
يمكن أن يكون التعبير من الأنواع التالية: حسابي، نسبي، منطقي، سلسلة
2.3.4.1. تفسير عملية التعيين
العملية متغير=تعبير؛ هي في حد ذاتها تعبير يتم تقييمه على النحو التالي:
- يتم تقييم الطرف الأيمن من عملية التعيين: والنتيجة هي قيمة V.
- يتم تعيين القيمة V للمتغير
- القيمة V هي أيضًا قيمة عملية التعيين، التي يُنظر إليها الآن على أنها تعبير.
ولهذا السبب فإن التعبير V1=V2=التعبير صحيح. وبسبب الأسبقية، سيتم تقييم عامل = الموجود في أقصى اليمين. وبالتالي نحصل على V1=(V2=التعبير). يتم تقييم التعبير V2=التعبير ويكون له القيمة V. أدى تقييم هذا التعبير إلى تعيين V إلى V2. ثم يتم تقييم عامل = التالي على أنه V1=V. لا تزال قيمة هذا التعبير هي V. ويؤدي تقييمه إلى تعيين V إلى V1. وبالتالي، فإن العملية V1=V2=التعبير هي تعبير يتم تقييمه
1: يؤدي إلى تعيين قيمة التعبير للمتغيرين V1 و V2
2: يعيد قيمة التعبير كنتيجة.
يمكننا تعميم هذا على تعبير بالصيغة: V1=V2=....=Vn=التعبير
2.3.4.2. التعبير الحسابي
المعاملات الخاصة بالتعبيرات الحسابية هي كما يلي:
+: الجمع
- : الطرح
*: الضرب
/ : القسمة: تكون النتيجة هي الناتج الدقيق إذا كان أحد المعاملين على الأقل عددًا حقيقيًا. إذا كان كلا المعاملين عددين صحيحين، تكون النتيجة هي الناتج الصحيح. وبالتالي، 5/2 -> 2 و 5.0/2 -> 2.5.
% : القسمة: تكون النتيجة هي الباقي بغض النظر عن طبيعة المعاملات، مع كون الناتج عددًا صحيحًا. وبالتالي، فهذه هي عملية القسمة على القاسم.
هناك العديد من الدوال الرياضية:
double sqrt(double x) | الجذر التربيعي |
double cos(double x) | جيب التمام |
جيب التمام | جيب |
تانغنت مزدوج(x مزدوج) | الظل |
double pow(double x, double y) | x أس y (x > 0) |
exp مزدوج (x مزدوج) | أسي |
double log(double x) | اللوغاريتم الطبيعي |
double abs(double x) | القيمة المطلقة |
إلخ...
جميع هذه الدوال محددة في فئة Java تسمى Math. عند استخدامها، يجب أن تسبقها باسم الفئة التي تم تعريفها فيها. وبالتالي، ستكتب:
تعريف فئة Math هو كما يلي:
public final class java.lang.Math
extends java.lang.Object (I-§1.12)
{
// Fields
public final static double E; §1.10.1
public final static double PI; §1.10.2
// Methods
public static double abs(double a); §1.10.3
public static float abs(float a); §1.10.4
public static int abs(int a); §1.10.5
public static long abs(long a); §1.10.6
public static double acos(double a); §1.10.7
public static double asin(double a); §1.10.8
public static double atan(double a); §1.10.9
public static double atan2(double a, double b); §1.10.10
public static double ceil(double a); §1.10.11
public static double cos(double a); §1.10.12
public static double exp(double a); §1.10.13
public static double floor(double a); §1.10.14
public static double §1.10.15
IEEEremainder(double f1, double f2);
public static double log(double a); §1.10.16
public static double max(double a, double b); §1.10.17
public static float max(float a, float b); §1.10.18
public static int max(int a, int b); §1.10.19
public static long max(long a, long b); §1.10.20
public static double min(double a, double b); §1.10.21
public static float min(float a, float b); §1.10.22
public static int min(int a, int b); §1.10.23
public static long min(long a, long b); §1.10.24
public static double pow(double a, double b); §1.10.25
public static double random(); §1.10.26
public static double rint(double a); §1.10.27
public static long round(double a); §1.10.28
public static int round(float a); §1.10.29
public static double sin(double a); §1.10.30
public static double sqrt(double a); §1.10.31
public static double tan(double a); §1.10.32
}
2.3.4.3. المُشغِّلات في تقييم التعبيرات الحسابية
أولوية العوامل عند تقييم تعبير حسابي هي كما يلي (من الأعلى إلى الأدنى):
[الدوال]، [ ( )]، [ *، /، %]، [+، -]
تتمتع العوامل الحسابية الموجودة داخل نفس الكتلة [ ] بنفس الأسبقية.
2.3.4.4. المعاملات العلائقية
المعاملات هي كما يلي: <, <=, ==, !=, >, >=
ترتيب الأسبقية
>, >=, <, <=
==, !=
نتيجة التعبير العلائقي هي القيمة المنطقية false إذا كان التعبير خاطئًا؛ وإلا، فهي true.
مثال:
مقارنة بين حرفين
لنفترض وجود حرفين C1 و C2. يمكن مقارنتهما باستخدام العوامل
<، <=، ==، !=، >، >=
في هذه الحالة، تتم مقارنة رموز ASCII الخاصة بهما — وهي أرقام. تذكر أنه وفقًا لترتيب ASCII، تنطبق العلاقات التالية:
مسافة < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'
مقارنة سلسلتين من الأحرف
يتم مقارنتهما حرفًا بحرف. أول عدم تساوي يتم العثور عليه بين حرفين يؤدي إلى عدم تساوي في نفس الاتجاه للسلسلتين.
أمثلة:
لنفترض مقارنة السلسلتين "Cat" و "Dog"
تسمح لنا هذه المتباينة الأخيرة باستنتاج أن "Cat" < "Dog".

لنفكر في مقارنة السلسلتين "Cat" و "Kitten". هما متساويتان طوال الوقت حتى تنتهي السلسلة "Cat". في هذه الحالة، تُعتبر السلسلة التي انتهت هي "الأصغر". وبالتالي، لدينا العلاقة
"<bdi dir="ltr" class="odt-ltr-term">Cat</bdi>" < "<bdi dir="ltr" class="odt-ltr-term">Kitten</bdi>".
دوال لمقارنة سلسلتين
لا يمكننا استخدام عوامل العلاقة <، <=، ==، !=، >، >= هنا. يجب علينا استخدام طرق من فئة String:
String chaine1, chaine2;
chaine1=…;
chaine2=…;
int i=chaine1.compareTo(chaine2);
boolean egal=chaine1.equals(chaine2)
في الكود أعلاه، ستكون قيمة المتغير i:
0: إذا كانت السلسلتان متساويتين
1: إذا كانت السلسلة 1 > السلسلة 2
-1: إذا كانت السلسلة 1 < السلسلة 2
ستكون قيمة المتغير equal هي true إذا كانت السلسلتان متساويتين.
2.3.4.5. التعبيرات المنطقية
المعاملات هي & (و)، || (أو)، و! (ليس). نتيجة التعبير المنطقي هي قيمة منطقية.
ترتيب الأسبقية ! ، &&، ||
مثال:
تكون الأولوية للمشغلات العلائقية على المشغلات && و ||.
2.3.4.6. العمليات على البتات
المشغلات
لنفترض أن i و j عددان صحيحان.
i<<n | يحول i بمقدار n بتات إلى اليسار. البتات الواردة هي أصفار. |
i>>n | يحول i n بتات إلى اليمين. إذا كان i عددًا صحيحًا موقّعًا (signed char، int، long)، يتم الحفاظ على بت الإشارة. |
i & j | تُجري عملية "AND" المنطقية بين i و j بتًا بتًا. |
i | j | يُنفذ عملية OR المنطقية بين i و j بتًا بتًا. |
~i | يعكس i إلى 1 |
i^j | يُجري عملية XOR بين i و j |
دع
عملية | القيمة |
i<<4 | 0x23F0 |
i>>4 | 0x0123 يتم الحفاظ على بت الإشارة. |
k>>4 | 0xFF12 يتم الحفاظ على بت الإشارة. |
i&j | 0x1023 |
i|j | 0xF33F |
~i | 0xEDC0 |
2.3.4.7. تركيبة من العوامل
يمكن كتابة a=<bdi dir="ltr" class="odt-ltr-term">a+b</bdi> على النحو التالي: <bdi dir="ltr" class="odt-ltr-term">a+</bdi>=b
يمكن كتابة a=<bdi dir="ltr" class="odt-ltr-term">a-b</bdi> على النحو التالي: <bdi dir="ltr" class="odt-ltr-term">a-</bdi>=b
وينطبق الأمر نفسه على العوامل /، %، *، <<، >>، &، |، ^
وبالتالي، يمكن كتابة a=a+2; على النحو التالي: a+=2;
2.3.4.8. عوامل الزيادة والنقصان
الترميز variable++ يعني variable=variable+1 أو variable+=1
الرمز variable-- يعني variable=variable-1 أو variable-=1.
2.3.4.9. عامل ?
يتم تقييم التعبير expr_cond ? expr1:expr2 يتم تقييمه على النحو التالي:
1: يتم تقييم التعبير expr_cond. هذا تعبير شرطي بقيمة صحيحة أو خاطئة
2: إذا كانت القيمة صحيحة، فإن قيمة التعبير هي قيمة expr1. ولا يتم تقييم expr2.
3: إذا كان خطأً، يحدث العكس: تكون قيمة التعبير هي قيمة expr2. ولا يتم تقييم expr1.
مثال
*i = (j > 4 ? j + 1 : j - 1);*
سيُعيّن للمتغير i:
j+1 إذا كان j>4، و j-1 في الحالات الأخرى
وهذا يعادل كتابة if(j>4) i=j+1; else i=j-1; ولكنه أكثر إيجازًا.
2.3.4.10. أولوية العمليات بشكل عام
() [] وظيفة | gd |
! ~ ++ -- | dg |
مشغلات التحويل (النوع) الجديدة | dg |
* / % | gd |
+ - | gd |
<< >> | gd |
< <= > >= instanceof | gd |
== != | gd |
& | gd |
^ | gd |
| | gd |
&& | gd |
|| | gd |
: | dg |
= += -= إلخ. | dg |
gd: يشير إلى أنه، بالنسبة للمشغلات ذات الأولوية المتساوية، يتم مراعاة الأولوية من اليسار إلى اليمين. وهذا يعني أنه عندما يحتوي التعبير على مشغلات ذات أولوية متساوية، يتم تقييم المشغل الأبعد إلى اليسار في التعبير أولاً. يشير dg إلى الأولوية من اليمين إلى اليسار.
2.3.4.11. تحويل الأنواع
من الممكن، داخل تعبير ما، تغيير تمثيل قيمة ما مؤقتًا. وهذا ما يُسمى تحويل النوع. صيغة تغيير نوع قيمة في تعبير ما هي (النوع) القيمة. ثم تأخذ القيمة النوع المحدد. ويؤدي هذا إلى تغيير في تمثيل القيمة.
مثال:
هنا، من الضروري تحويل i أو j إلى نوع عائم؛ وإلا، فإن القسمة ستُرجع ناتجًا صحيحًا بدلاً من قيمة عائمة.
*i* هي قيمة مشفرة بدقة في 2 بايت
*(<bdi dir="ltr" class="odt-ltr-term">float</bdi>) i* هي نفس القيمة، المشفرة تقريبًا كرقم عائم على 4 بايت
وبالتالي، هناك تحويل لنوع قيمة i. يحدث هذا التحويل فقط خلال فترة الحساب؛ حيث تحتفظ المتغير i دائمًا بنوع int الخاص بها.
2.4. عبارات التحكم في تدفق البرنامج
2.4.1. توقف
تسمح لك طريقة exit المحددة في فئة System بإيقاف تنفيذ البرنامج.
الإجراء : يوقف العملية الحالية ويعيد قيمة الحالة إلى العملية الأم
تقوم exit بإنهاء العملية الحالية وإرجاع التحكم إلى العملية المستدعية. يمكن للعملية المستدعية استخدام قيمة الحالة. في نظام DOS، يتم إرجاع متغير الحالة هذا إلى DOS في متغير النظام ERRORLEVEL، والذي يمكن التحقق من قيمته في ملف دفعي. في نظام Unix، يسترد المتغير $? قيمة الحالة إذا كان مترجم الأوامر هو Bourne Shell (/bin/sh).
مثال:
لإنهاء البرنامج بقيمة حالة تساوي 0.
2.4.2. بنية شرطية بسيطة
syntaxe : if (condition) {actions_condition_vraie;} else {actions_condition_fausse;}
ملاحظات:
- يُوضع الشرط بين قوسين.
- تنتهي كل إجراء بفاصلة منقوطة.
- لا يتبع الأقواس المتعرجة فاصلة منقوطة.
- الأقواس المتعرجة ضرورية فقط إذا كان هناك أكثر من إجراء واحد.
- يمكن حذف جملة else.
- لا يوجد "then".
المكافئ الخوارزمي لهذه البنية هو بنية if-then-else:
مثال
if (x>0) { nx=nx+1;sx=sx+x;} else dx=dx-x;
يمكنك تداخل هياكل القرار:
تظهر المشكلة التالية أحيانًا:
public static void main(void){
int n=5;
if(n>1)
if(n>6)
System.out.println(">6");
else System.out.println("<=6");
}
في المثال السابق، إلى أي عبارة if تشير عبارة else؟ القاعدة هي أن else تشير دائمًا إلى أقرب عبارة *if: if(n>6)* في هذا المثال. لننظر إلى مثال آخر:
public static void main(void)
{ int n=0;
if(n>1)
if(n>6) System.out.println(">6");
else; // else from if(n>6): nothing to do
else System.out.println("<=1"); // else du if(n>1)
}
هنا أردنا وضع else في عبارة if(n>1) وعدم وضع else في عبارة if(n>6). وبسبب الملاحظة السابقة، نحن مضطرون لوضع else في عبارة if(n>6)، التي لا تحتوي على أي عبارة.
2.4.3. بنية الحالة
الصيغة هي كما يلي:
switch(expression) {
case v1:
actions1;
break;
case v2:
actions2;
break;
. .. .. .. .. ..
default: actions_sinon;
}
ملاحظات
- لا يمكن أن تكون قيمة تعبير التحكم سوى عدد صحيح أو حرف.
- يُحاط تعبير التحكم بأقواس.
- يمكن حذف الجملة الافتراضية.
- القيم vi هي القيم المحتملة للتعبير. إذا كانت نتيجة التعبير هي vi، يتم تنفيذ الإجراءات التي تلي جملة case vi.
- يؤدي بيان break إلى الخروج من بنية case. إذا كان غائبًا في نهاية كتلة التعليمات للقيمة vi، يستمر التنفيذ بالتعليمات الخاصة بالقيمة vi+1.
مثال
في الخوارزميات
selon la valeur de choix
cas 0
arrêt
cas 1
exécuter module M1
cas 2
exécuter module M2
sinon
erreur<--vrai
findescas
في جافا
int choix, erreur;
switch(choix){
case 0: System.exit(0);
case 1: M1();break;
case 2: M2();break;
default: erreur=1;
}
2.4.4. بنية الحلقة
2.4.4.1. عدد التكرارات المعروف
الصيغة
for (i=id;i<=if;i=i+ip){
actions;
}
ملاحظات
- يتم وضع المعلمات الثلاثة لحلقة for بين قوسين.
- يتم فصل المعلمات الثلاثة لحلقة for بفواصل منقوطة.
- تنتهي كل عملية في حلقة for بفاصلة منقوطة.
- لا تكون الأقواس المتعرجة ضرورية إلا إذا كان هناك أكثر من إجراء واحد.
- لا يتبع الأقواس المتعرجة فاصلة منقوطة.
المكافئ الخوارزمي هو بنية for:
والتي يمكن ترجمتها إلى بنية while:
2.4.4.2. عدد التكرارات غير معروف
هناك العديد من هياكل التحكم في Java لهذه الحالة.
حلقة while
while(condition){
actions;
}
تستمر الحلقة طالما أن الشرط صحيح. قد لا يتم تنفيذ الحلقة أبدًا.
ملاحظات:
- يتم وضع الشرط بين قوسين.
- يُختتم كل إجراء بفاصلة منقوطة.
- لا تكون الأقواس المتعرجة ضرورية إلا إذا كان هناك أكثر من إجراء واحد.
- لا يتبع الأقواس المتعرجة فاصلة منقوطة.
البنية الخوارزمية المقابلة هي بنية while:
بنية Do-while
الصيغة هي كما يلي:
do{
instructions;
}while(condition);
تستمر الحلقة حتى تصبح الشرط غير صحيحة أو طالما أن الشرط صحيحة. هنا، يتم تنفيذ الحلقة مرة واحدة على الأقل.
ملاحظات
- يُوضع الشرط بين قوسين.
- يُختتم كل إجراء بفاصلة منقوطة.
- لا تكون الأقواس المتعرجة ضرورية إلا إذا كان هناك أكثر من إجراء واحد.
- لا يتبع الأقواس المتعرجة فاصلة منقوطة.
البنية الخوارزمية المقابلة هي بنية "كرر ... حتى":
هيكل لـ (for)
الصيغة هي كما يلي:
for(instructions_départ;condition;instructions_fin_boucle){
instructions;
}
تستمر الحلقة طالما أن الشرط صحيح (يتم تقييمه قبل كل تكرار). يتم تنفيذ تعليمات_البداية قبل الدخول إلى الحلقة للمرة الأولى. يتم تنفيذ تعليمات_نهاية_الحلقة بعد كل تكرار.
ملاحظات
- يتم وضع المعلمات الثلاثة لحلقة for بين قوسين.
- يتم فصل المعلمات الثلاثة لحلقة for بفواصل منقوطة.
- تنتهي كل عبارة for بفاصلة منقوطة.
- لا تكون الأقواس المتعرجة ضرورية إلا في حالة وجود أكثر من إجراء واحد.
- لا يتبع الأقواس المتعرجة فاصلة منقوطة.
- يتم فصل العبارات المختلفة في start_statements و end_loop_statements بفواصل.
البنية الخوارزمية المقابلة هي كما يلي:
أمثلة
تحسب جميع البرامج التالية مجموع أول n أعداد صحيحة.
1 for(i=1, somme=0;i<=n;i=i+1)
somme=somme+a[i];
2 for (i=1, somme=0;i<=n;somme=somme+a[i], i=i+1);
3 i=1;somme=0;
while(i<=n)
{ somme+=i; i++; }
4 i=1; somme=0;
do somme+=i++;
while (i<=n);
عبارات التحكم في الحلقات
break | يخرج من حلقة for أو while أو do...while. |
continue | ينتقل إلى التكرار التالي لدورات for و while و do...while |
2.5. بنية برنامج Java
قد يكون لبرنامج Java الذي لا يستخدم فئات أو دوال محددة من قبل المستخدم بخلاف الدالة main البنية التالية:
public class test1{
public static void main(String arg[]){
… code du programme
}// hand
}// class
الوظيفة الرئيسية، المعروفة أيضًا باسم الأسلوب، هي أول ما يتم تنفيذه عند تشغيل برنامج Java. ويجب أن تحتوي على التوقيع التالي:
public static void main(String arg[]){
أو
public static void main(String[] arg){
يمكن أن يكون اسم الحجة arg أي شيء. وهي عبارة عن مصفوفة من السلاسل تمثل حجج سطر الأوامر. سنعود إلى هذا لاحقًا.
إذا كنت تستخدم دوال قد ترمي استثناءات لا ترغب في معالجتها صراحةً، فيمكنك تغليف كود البرنامج في كتلة try/catch:
public class test1{
public static void main(String arg[]){
try{
… code du programme
} catch (Exception e){
// error handling
}// try
}// hand
}// class
في بداية شفرة المصدر وقبل تعريف الفئة، من الشائع العثور على عبارات استيراد الفئة. على سبيل المثال:
import java.io.*;
public class test1{
public static void main(String arg[]){
… code du programme
}// hand
}// class
لنأخذ مثالاً. لنفكر في عبارة الكتابة التالية:
الذي يطبع "java" على الشاشة. هناك الكثير مما يحدث في هذا البيان البسيط:
- System هي فئة اسمها الكامل هو java.lang.System
- out هي خاصية لهذه الفئة من النوع java.io.PrintStream، وهي فئة أخرى
- println هي طريقة لفئة java.io.PrintStream.
لن نعقد هذا الشرح دون داعٍ، فهو يأتي في وقت مبكر جدًا لأنه يتطلب فهم مفهوم الفئة الذي لم يتم تناوله بعد. يمكن اعتبار الفئة موردًا. هنا، سيحتاج المُترجم إلى الوصول إلى كل من فئتي java.lang.System و java.io.PrintStream. يتم تنظيم مئات فئات Java في أرشيفات تُعرف أيضًا باسم الحزم. تُستخدم عبارات الاستيراد الموضوعة في بداية البرنامج لإخبار المُترجم بالفئات الخارجية التي يحتاجها البرنامج (تلك المستخدمة ولكن غير المُعرَّفة في ملف المصدر المراد ترجمته). وبالتالي، في مثالنا، يحتاج برنامجنا إلى فئتي java.lang.System و java.io.PrintStream. نحدد ذلك باستخدام عبارة الاستيراد. يمكننا كتابة ما يلي في بداية البرنامج:
نظرًا لأن برنامج Java يستخدم عادةً عشرات الفئات الخارجية، فسيكون من الممل كتابة جميع عبارات الاستيراد الضرورية. تم تجميع الفئات في حزم، ويمكننا استيراد الحزمة بأكملها. وبالتالي، لاستيراد حزمتي java.lang و java.io، نكتب:
تحتوي حزمة java.lang على جميع الفئات الأساسية في Java ويتم استيرادها تلقائيًا بواسطة المُجمع. لذا، في النهاية، سنكتب فقط:
2.6. معالجة الاستثناءات
العديد من وظائف Java قادرة على توليد استثناءات، أي أخطاء. وقد صادفنا بالفعل إحدى هذه الوظائف، وهي وظيفة readLine:
String ligne=null;
try{
ligne=IN.readLine();
System.out.println("ligne="+ligne);
} catch (Exception e){
affiche(e);
System.exit(2);
}// try
عندما يكون من المحتمل أن ترمي دالة استثناءً، يطلب مُركِّب Java من المبرمج معالجته من أجل إنتاج برامج أكثر مقاومة للأخطاء: يجب عليك دائمًا تجنب "تعطل" التطبيق بشكل غير متوقع. هنا، ترمي الدالة readLine استثناءً إذا لم يكن هناك ما يُقرأ — على سبيل المثال، لأن دفق الإدخال قد أُغلق. تتبع معالجة الاستثناءات هذا النمط:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante
إذا لم تُطلق الدالة استثناءً، ينتقل البرنامج إلى الجملة التالية؛ وإلا، فإنه يدخل إلى نص جملة catch ثم ينتقل إلى الجملة التالية. يرجى ملاحظة النقاط التالية:
- e هو كائن مشتق من نوع Exception. يمكننا أن نكون أكثر تحديدًا باستخدام أنواع مثل IOException و SecurityException و ArithmeticException وغيرها: هناك حوالي عشرين نوعًا من الاستثناءات. بكتابة catch (Exception e)، نشير إلى أننا نريد معالجة جميع أنواع الاستثناءات. إذا كان من المحتمل أن يولد الكود الموجود في كتلة try أنواعًا متعددة من الاستثناءات، فقد نرغب في أن نكون أكثر تحديدًا من خلال معالجة الاستثناء باستخدام كتل catch متعددة:
try{
appel de la fonction susceptible de générer l'exception
} catch (IOException e){
traiter l'exception e
}
} catch (ArrayIndexOutOfBoundsException e){
traiter l'exception e
}
} catch (RunTimeException e){
traiter l'exception e
}
instruction suivante
- يمكن إضافة جملة finally إلى كتل try/catch:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
finally{
code exécuté après try ou catch
}
instruction suivante
هنا، سواء حدثت استثناء أم لا، سيتم دائمًا تنفيذ الكود الموجود في جملة finally.
- تحتوي فئة Exception على طريقة getMessage() التي تُرجع رسالة توضح تفاصيل الخطأ الذي حدث. لذا، إذا أردنا عرض هذه الرسالة، نكتب:
catch (Exception ex){
System.err.println("L'erreur suivante s'est produite : "+ex.getMessage());
...
}//catch
- تحتوي فئة Exception على طريقة toString() التي تُرجع سلسلة تشير إلى نوع الاستثناء وقيمة الخاصية Message. وبالتالي يمكننا كتابة:
catch (Exception ex){
System.err.println ("L'erreur suivante s'est produite : "+ex.toString());
...
}//catch
يمكننا أيضًا كتابة:
هنا لدينا عملية string + Exception التي سيتم تحويلها تلقائيًا إلى string + Exception.toString() بواسطة المُجمع من أجل ربط سلسلتين.
يوضح المثال التالي استثناءً تم إنشاؤه باستخدام عنصر مصفوفة غير موجود:
// tables
// imports
import java.io.*;
public class tab1{
public static void main(String[] args){
// declaring & initializing an array
int[] tab=new int[] {0,1,2,3};
int i;
// table display with for
for (i=0; i<tab.length; i++)
System.out.println("tab[" + i + "]=" + tab[i]);
// generating an exception
try{
tab[100]=6;
}catch (Exception e){
System.err.println("L'erreur suivante s'est produite : " + e);
}//try-catch
}//hand
}//class
يؤدي تشغيل البرنامج إلى النتائج التالية:
tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
L'erreur suivante s'est produite : java.lang.ArrayIndexOutOfBoundsException
فيما يلي مثال آخر نتعامل فيه مع الاستثناء الناتج عن تعيين سلسلة إلى رقم عندما لا تمثل السلسلة رقمًا:
// imports
import java.io.*;
public class console1{
public static void main(String[] args){
// creation of an input stream
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
}catch(Exception ex){}
// We ask for the name
System.out.print("Nom : ");
// reading response
String nom=null;
try{
nom=IN.readLine();
}catch(Exception ex){}
// age requested
int age=0;
boolean ageOK=false;
while ( ! ageOK){
// question
System.out.print("âge : ");
// read-verify answer
try{
age=Integer.parseInt(IN.readLine());
ageOK=true;
}catch(Exception ex) {
System.err.println("Age incorrect, recommencez...");
}//try-catch
}//while
// final display
System.out.println("Vous vous appelez " + nom + " et vous avez " + age + " ans");
}//Main
}//class
بعض نتائج التنفيذ:
E:\data\serge\MSNET\c#\bases\1>console1
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12 ans
2.7. تجميع برنامج جافا وتشغيله
قم بتجميع البرنامج التالي ثم تشغيله:
// importing classes
import java.io.*;
// test class
public class coucou{
// hand function
public static void main(String args[]){
// screen display
System.out.println("coucou");
}//hand
}//class
يجب تسمية ملف المصدر الذي يحتوي على فئة coucou السابقة باسم coucou.java:
يتم ترجمة وتشغيل برنامج Java في نافذة DOS. توجد الملفات التنفيذية javac.exe (المترجم) و java.exe (المترجم الفوري) في دليل bin ضمن دليل تثبيت JDK:
E:\data\serge\JAVA\classes\paquetages\personne>dir "e:\program files\jdk14\bin\java?.exe"
07/02/2002 12:52 24 649 java.exe
07/02/2002 12:52 28 766 javac.exe
سيقوم المُجمِّع javac.exe بتحليل ملف المصدر .java وإنتاج ملف .class مُجمَّع. لا يمكن للمعالج تشغيل هذا الملف على الفور. فهو يتطلب مترجم Java (java.exe)، المعروف باسم الآلة الافتراضية أو JVM (Java Virtual Machine). من الكود الوسيط في ملف .class، تُنشئ الآلة الافتراضية تعليمات خاصة بمعالج الجهاز الذي تعمل عليه. توجد آلات افتراضية لـ Java لأنواع مختلفة من أنظمة التشغيل (Windows وUnix وMac OS وغيرها). يمكن تنفيذ ملف .class بواسطة أي من هذه الآلات الافتراضية، وبالتالي على أي نظام تشغيل. تعد قابلية النقل عبر الأنظمة هذه إحدى نقاط القوة الرئيسية لـ Java.
دعونا نقوم بتجميع البرنامج السابق:
E:\data\serge\JAVA\ESSAIS\intro1>"e:\program files\jdk14\bin\javac" coucou.java
E:\data\serge\JAVA\ESSAIS\intro1>dir
10/06/2002 08:42 228 coucou.java
10/06/2002 08:48 403 coucou.class
دعونا نقوم بتشغيل ملف .class الذي تم إنشاؤه:
لاحظ أنه في أمر التنفيذ أعلاه، لم نحدد اللاحقة .class لملف coucou.class المراد تنفيذه. فهي ضمنية. إذا كان دليل bin الخاص بـ JDK موجودًا في مسار PATH لجهاز DOS، فلن نحتاج إلى توفير المسار الكامل لملفات javac.exe و java.exe القابلة للتنفيذ. يمكننا ببساطة كتابة
2.8. الحجج الرئيسية للبرنامج
تقبل الدالة الرئيسية مصفوفة من السلاسل كمعلمات: String[]. تحتوي هذه المصفوفة على حجج سطر الأوامر المستخدمة لتشغيل التطبيق. وبالتالي، إذا قمنا بتشغيل البرنامج P باستخدام الأمر:
وإذا تم تعريف الدالة الرئيسية على النحو التالي:
فسيكون لدينا arg[0]="arg0"، arg[1]="arg1" … وإليك مثال على ذلك:
import java.io.*;
public class param1{
public static void main(String[] arg){
int i;
System.out.println("Nombre d'arguments="+arg.length);
for (i=0;i<arg.length;i++)
System.out.println("arg["+i+"]="+arg[i]);
}
}
النتائج هي كما يلي:
2.9. تمرير المعلمات إلى دالة
أظهرت الأمثلة السابقة برامج Java تحتوي على دالة واحدة فقط، وهي الدالة الرئيسية. يوضح المثال التالي كيفية استخدام الدوال وكيفية تبادل المعلومات بينها. يتم تمرير معلمات الدالة دائمًا بالقيمة: أي يتم نسخ قيمة المعلمة الفعلية إلى المعلمة الشكلية المقابلة.
import java.io.*;
public class param2{
public static void main(String[] arg){
String S="papa";
changeString(S);
System.out.println("Paramètre effectif S="+S);
int age=20;
changeInt(age);
System.out.println("Paramètre effectif age="+age);
}
private static void changeString(String S){
S="maman";
System.out.println("Paramètre formel S="+S);
}
private static void changeInt(int a){
a=30;
System.out.println("Paramètre formel a="+a);
}
}
النتائج التي تم الحصول عليها هي كما يلي:
تم نسخ قيم المعلمات الفعلية "dad" و 20 إلى المعلمات الشكلية S و a. ثم تم تعديلهما. بقيت المعلمات الفعلية دون تغيير. لاحظ هنا نوع المعلمات الفعلية:
- S هو مرجع كائن، أي عنوان كائن في الذاكرة
- age هو عدد صحيح
2.10. مثال على حساب الضريبة
سنختتم هذا الفصل بمثال سنعود إليه عدة مرات في هذا المستند. نقترح كتابة برنامج لحساب ضريبة دافع الضرائب. سنأخذ الحالة المبسطة لدافع الضرائب الذي لا يملك سوى راتبه ليبلغ عنه:
- نحسب عدد شرائح الضريبة للموظف على النحو التالي: nbParts = nbEnfants / 2 + 1 إذا كان غير متزوج، و nbEnfants / 2 + 2 إذا كان متزوجًا، حيث nbEnfants هو عدد الأطفال.
- إذا كان لديه ثلاثة أطفال على الأقل، يحصل على نصف حصة إضافية.
- نحسب الدخل الخاضع للضريبة R = 0.72 × S، حيث S هو الراتب السنوي
- نحسب معامل الأسرة QF = R / nbParts
- نحسب ضريبتك I. انظر الجدول التالي:
12,620.0 | 0 | 0 |
13,190 | 0.05 | 631 |
15,640 | 0.1 | 1,290.5 |
24,740 | 0.15 | 2,072.5 |
31,810 | 0.2 | 3,309.5 |
39,970 | 0.25 | 4,900 |
48,360 | 0.3 | 6,898.5 |
55,790 | 0.35 | 9,316.5 |
92,970 | 0.4 | 12,106 |
127,860 | 0.45 | 16,754.5 |
151,250 | 0.50 | 23,147.5 |
172,040 | 0.55 | 30,710 |
195,000 | 0.60 | 39,312 |
0 | 0.65 | 49,062 |
يحتوي كل صف على 3 حقول. لحساب الضريبة I، نبحث عن الصف الأول الذي يكون فيه QF <= الحقل 1. على سبيل المثال، إذا كان QF = 23,000، فسنجد الصف
الضريبة I تساوي إذن 0.15*R - 2072.5*nbParts. إذا كان QF بحيث لا تتحقق الشرط QF<=field1 أبدًا، يتم استخدام المعاملات من الصف الأخير. هنا:
مما يعطي الضريبة I = 0.65*R - 49062*nbParts.
برنامج Java المقابل هو كما يلي:
import java.io.*;
public class impots{
// ------------ hand
public static void main(String arg[]){
// data
// tax bracket limits
double Limites[]={12620, 13190, 15640, 24740, 31810, 39970, 48360,55790, 92970, 127860, 151250, 172040, 195000, 0};
// coefficient applied to the number of shares
double Coeffn[]={0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5,12106, 16754.5, 23147.5, 30710, 39312, 49062};
// the program
// keyboard input stream creation
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
}
catch(Exception e){
erreur("Création du flux d'entrée", e, 1);
}
// we recover marital status
boolean OK=false;
String reponse=null;
while(! OK){
try{
System.out.print("Etes-vous marié(e) (O/N) ? ");
reponse=IN.readLine();
reponse=reponse.trim().toLowerCase();
if (! reponse.equals("o") && !reponse.equals("n"))
System.out.println("Réponse incorrecte. Recommencez");
else OK=true;
} catch(Exception e){
erreur("Lecture état marital",e,2);
}
}
boolean Marie = reponse.equals("o");
// number of children
OK=false;
int NbEnfants=0;
while(! OK){
try{
System.out.print("Nombre d'enfants : ");
reponse=IN.readLine();
try{
NbEnfants=Integer.parseInt(reponse);
if(NbEnfants>=0) OK=true;
else System.err.println("Réponse incorrecte. Recommencez");
} catch(Exception e){
System.err.println("Réponse incorrecte. Recommencez");
}// try
} catch(Exception e){
erreur("Lecture état marital",e,2);
}// try
}// while
// salary
OK=false;
long Salaire=0;
while(! OK){
try{
System.out.print("Salaire annuel : ");
reponse=IN.readLine();
try{
Salaire=Long.parseLong(reponse);
if(Salaire>=0) OK=true;
else System.err.println("Réponse incorrecte. Recommencez");
} catch(Exception e){
System.err.println("Réponse incorrecte. Recommencez");
}// try
} catch(Exception e){
erreur("Lecture Salaire",e,4);
}// try
}// while
// calculating the number of shares
double NbParts;
if(Marie) NbParts=(double)NbEnfants/2+2;
else NbParts=(double)NbEnfants/2+1;
if (NbEnfants>=3) NbParts+=0.5;
// taxable income
double Revenu;
Revenu=0.72*Salaire;
// family quotient
double QF;
QF=Revenu/NbParts;
// search for tax bracket corresponding to QF
int i;
int NbTranches=Limites.length;
Limites[NbTranches-1]=QF;
i=0;
while(QF>Limites[i]) i++;
// tax
long impots=(long)(i*0.05*Revenu-Coeffn[i]*NbParts);
// the result is displayed
System.out.println("Impôt à payer : " + impots);
}// hand
// ------------ error
private static void erreur(String msg, Exception e, int exitCode){
System.err.println(msg+"("+e+")");
System.exit(exitCode);
}// error
}// class
النتائج التي تم الحصول عليها هي كما يلي:
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : 3
Salaire annuel : 200000
Impôt à payer : 16400
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? n
Nombre d'enfants : 2
Salaire annuel : 200000
Impôt à payer : 33388
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? w
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? q
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : q
Réponse incorrecte. Recommencez
Nombre d'enfants : 2
Salaire annuel : q
Réponse incorrecte. Recommencez
Salaire annuel : 1
Impôt à payer : 0