Skip to content

2. مبانی زبان جاوا

2.1. مقدمه

ما در ابتدا جاوا را به‌عنوان یک زبان برنامه‌نویسی متعارف در نظر می‌گیریم. اشیاء را بعداً پوشش خواهیم داد.

در یک برنامه، دو نوع داده وجود دارد

  • داده‌ها
  • دستورالعمل‌هایی که آن را دستکاری می‌کنند

ما معمولاً سعی می‌کنیم داده‌ها را از دستورها جدا کنیم:

Image

2.2. داده‌های جاوا

جاوا از انواع داده زیر استفاده می‌کند:

  • اعداد صحیح
  • اعداد ممیز شناور
  • کاراکترها و رشته‌های کاراکتری
  • بول‌ها
  • ابجکت‌ها

2.2.1. انواع داده‌های از پیش تعریف‌شده

نوع
کدگذاری
دامنه
char
۲ بایت
نویسه یونیکد
int
۴ بایت
[-231, 231-1]
long
۸ بایت
[-263, 263 -1]
byte
۱ بایت
[-27 , 27 -1]
short
۲ بایت
[-215, 215-1]
float
4 بایت
[3.4 10-38, 3.4 10+38] (مقدار مطلق)
double
8 بایت
[1.7 10-308 , 1.7 10+308] در مقدار مطلق
boolean
۱ بیت
درست، نادرست
String
ارجاع شیء
رشتهٔ کاراکتری
Date
ارجاع شیء
تاریخ
Character
ارجاع شیء
char
Integer
ارجاع شیء
integer
Long
ارجاع شیء
long
Byte
اشاره به شیء
بایت
Float
اشاره به شیء
ممیز شناور
Double
ارجاع شیء
دوگانه
Boolean
ارجاع شیء
بولی

2.2.2. نمایش داده صریح

entier
145, -7, 0xFF (هگزادسیمال)
دوگانه
134.789, -45E-18 (-45 × 10⁻¹⁸)
شناور
134.789F, -45E-18F (-45 × 10⁻¹⁸)
caractère
'A', 'b'
رشته‌ای
"امروز"
booléen
true, false
date
new Date(13,10,1954) (روز، ماه، سال)

2.2.3. گزارش‌دهی داده‌ها

2.2.3.1. نقش اعلان‌ها

یک برنامه داده‌هایی را دستکاری می‌کند که با یک نام و یک نوع مشخص می‌شوند. این داده‌ها در حافظه ذخیره می‌شوند. هنگامی که برنامه کامپایل می‌شود، کامپایلر به هر قطعه داده یک مکان حافظه را که با یک آدرس و یک اندازه مشخص می‌شود، اختصاص می‌دهد. این کار را با استفاده از اعلان‌هایی که توسط برنامه‌نویس انجام شده است، انجام می‌دهد.

علاوه بر این، این اعلان‌ها به کامپایلر امکان می‌دهند تا خطاهای برنامه‌نویسی را تشخیص دهد. برای مثال، عملگر

x = x * 2;

در صورتی که، برای مثال، x یک رشتهٔ کاراکتری باشد، این عملیات به عنوان یک خطا علامت‌گذاری خواهد شد.

2.2.3.2. اعلام ثابت‌ها

سینتکس برای تعریف یک ثابت به شرح زیر است:

final type name=value; // ثابت name=value را تعریف می‌کند

مثلاً: final float PI = 3.141592F;

توجه

چرا ثابت‌ها را تعریف کنیم؟

  • خوانایی برنامه با دادن نام معنادار به ثابت افزایش می‌یابد:

مثلاً: final float taux_tva = 0.186F;

  • در صورتی که نیاز به تغییر «ثابت» باشد، اصلاح برنامه آسان‌تر خواهد بود. بنابراین، در مثال قبلی، اگر نرخ مالیات بر ارزش افزوده به ۳۳ درصد افزایش یابد، تنها تغییری که لازم است اعمال شود، اصلاح عبارت تعریف‌کننده مقدار آن خواهد بود:

final float taux_tva=0.33F;

اگر 0.186 به‌طور صریح در برنامه استفاده شده بود، در آن صورت لازم بود شمار زیادی از دستورات اصلاح شوند.

2.2.3.3. اعلام متغیر

یک متغیر با یک نام شناسایی می‌شود و با یک نوع داده مرتبط است. نام یک متغیر جاوا از n کاراکتر تشکیل شده است که اولین کاراکتر آن باید یک حرف باشد و بقیه می‌توانند حروف یا اعداد باشند. جاوا بین حروف بزرگ و کوچک تمایز قائل می‌شود. بنابراین، متغیرهای FIN و fin با هم متفاوت هستند.

متغیرها را می‌توان هنگام تعریف مقداردهی اولیه کرد. نحو تعریف یک یا چند متغیر به صورت زیر است:

identificateur_de_type variable1,variable2,...,variablen;

که در آن identificateur_de_type می‌تواند یک نوع از پیش تعریف‌شده یا یک نوع شیء باشد که توسط برنامه‌نویس تعریف شده است.

2.2.4. تبدیل بین اعداد و رشته‌های کاراکتری

number -> string
"" + number
string -> int
Integer.parseInt(string)
string -> long
Long.parseLong(string)
string -> double
Double.valueOf(string).doubleValue()
string -> float
Float.valueOf(string).floatValue()

در اینجا برنامه‌ای است که تکنیک‌های اصلی تبدیل بین اعداد و رشته‌های متنی را نشان می‌دهد. تبدیل یک رشته به عدد ممکن است ناموفق باشد اگر رشته نمایانگر عددی معتبر نباشد. در این حالت، یک خطای مرگبار—که در جاوا به آن استثنا گفته می‌شود—ایجاد می‌شود. این خطا را می‌توان با بند 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;

    // عدد --> رشته
    S=""+i;
    affiche(S);
    S=""+l;
    affiche(S);
    S=""+f;
    affiche(S);
    S=""+d;
    affiche(S);

    //بولی → رشته
    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);
    }
    
    // string --> 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);
    }

}// پایان main

  public static void affiche(String S){
    System.out.println("S="+S);
  }
}// پایان کلاس

نتایج به‌دست‌آمده به شرح زیر است:

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. آرایه‌های داده

یک آرایهٔ جاوا یک شیء است که امکان گروه‌بندی داده‌های یکسان تحت یک شناسهٔ واحد را فراهم می‌کند. آن به صورت زیر تعریف می‌شود:

Type[] = new Type[n] یا Type[] Array = new Type[n]

هر دو نحو معتبر هستند. n تعداد آیتم‌های داده‌ای است که آرایه می‌تواند در خود جای دهد. نحو Array[i] به آیتم داده‌ای با شماره i اشاره دارد، که در آن i به بازه [0,n-1] تعلق دارد. هر ارجاع به عنصر داده Tableau[i] که i به محدوده [0,n-1] تعلق نداشته باشد، باعث ایجاد یک استثنا خواهد شد.

یک آرایه دو بعدی را می‌توان به صورت زیر اعلام کرد:

Type Array[][] = new Type[n][p] یا Type[][] Array = new Type[n][p]

سینتکس Array[i] به عنصر داده i از Tableau اشاره دارد، که در آن i به بازه [0,n-1] تعلق دارد. Tableau[i] خود یک جدول است: Tableau[i][j] به آیتم داده شماره … اشاره دارد. j در Tableau[i]، جایی که j به بازه [0,p-1] تعلق دارد. هرگونه ارجاع به داده‌ها در Tableau با شاخص‌های نادرست، خطای مرگبار ایجاد می‌کند.

در اینجا یک مثال آورده شده است:


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]);
  }
}

و نتایج اجرای آن:

2
0.33

یک آرایه یک شیء با ویژگی length است: این اندازه آرایه است.

2.3. دستورهای پایه‌ای جاوا

تفاوتی قائل می‌شوند بین

  • دستورات پایه‌ای که توسط کامپیوتر اجرا می‌شوند.
  • دستورالعمل‌هایی که جریان برنامه را کنترل می‌کنند.

دستورالعمل‌های پایه زمانی روشن می‌شوند که ساختار یک میکروکامپیوتر و اجزای جانبی آن را در نظر بگیریم.

Image

  1. خواندن اطلاعات از صفحه‌کلید

  2. پردازش اطلاعات

  3. نمایش اطلاعات روی صفحه

  4. خواندن اطلاعات از یک فایل دیسکی

  5. نوشتن اطلاعات در یک فایل دیسکی

2.3.1. نوشتن روی صفحه

نحو دستور نوشتن روی صفحه به شرح زیر است:

System.out.println(expression) یا System.err.println(expression)

که در آن expression هر نوع داده‌ای است که می‌توان آن را به رشتهٔ کاراکتری برای نمایش روی صفحه تبدیل کرد. در مثال قبلی، ما دو دستور نوشتن دیدیم:

System.out.println(taux[1].length);
System.out.println(taux[1][1]);

System.out در یک فایل متنی می‌نویسد که به طور پیش‌فرض صفحه نمایش است. همین امر در مورد System.err نیز صدق می‌کند. این فایل‌ها به ترتیب شماره‌های ۱ و ۲ را دارند (یا descripteur). جریان ورودی صفحه‌کلید (System.in) نیز به‌عنوان یک فایل متنی با توصیف‌گر ۰ در نظر گرفته می‌شود. هر دو سیستم‌عامل DOS و یونیکس از لوله‌کشی دستورات (command piping) پشتیبانی می‌کنند:

    commande1 | commande2

هر چیزی که commande1 به System.out می‌نویسد، از commande2 به ورودی System.in هدایت (مسیردهی) می‌شود. به عبارت دیگر، commande2 از طریق System.in، داده‌های تولید شده توسط commande2 از طریق System.out را می‌خواند، و در نتیجه این داده‌ها دیگر روی صفحه نمایش داده نمی‌شوند. این سیستم به طور گسترده در یونیکس استفاده می‌شود. در این خط لوله، جریان System.err هدایت نمی‌شود: آن به صفحه نمایش می‌نویسد. به همین دلیل است که برای خروجی گرفتن پیام‌های خطا استفاده می‌شود (از این رو نام آن err است): این امر تضمین می‌کند که هنگام ارسال دستورات به صورت متوالی (piped)، پیام‌های خطا همچنان روی صفحه نمایش داده شوند. بنابراین، این روش صحیح است که پیام‌های خطا را به جای استفاده از جریان System.out، با استفاده از جریان System.err روی صفحه بنویسید.

2.3.2. خواندن داده‌های وارد شده از طریق صفحه‌کلید

جریان داده از صفحه‌کلید توسط شیء System.in از نوع InputStream نشان داده می‌شود. این نوع شیء امکان خواندن داده را کاراکتر به کاراکتر فراهم می‌کند. سپس این وظیفه برنامه‌نویس است که اطلاعات مرتبط را از این جریان کاراکتری استخراج کند. نوع InputStream اجازه نمی‌دهد که یک خط متن یکجا خوانده شود. نوع BufferedReader با استفاده از متد readLine این کار را امکان‌پذیر می‌سازد.

برای خواندن خطوط متنی که از صفحه‌کلید تایپ می‌شوند، ما از جریان ورودی System.in از نوع InputStream، یک جریان ورودی دیگر ایجاد می‌کنیم، این بار از نوع BufferedReader:

BufferedReader IN=new BufferedReader(new InputStreamReader(System.in));

ما جزئیات این دستور را در اینجا توضیح نمی‌دهیم، زیرا با مفهوم ساخت شیء (object construction) در ارتباط است. ما آن را به همین شکل به کار خواهیم برد.

ایجاد یک استریم ممکن است با شکست مواجه شود: در این صورت یک خطای مرگبار که در جاوا به آن استثنا (exception) گفته می‌شود، تولید می‌گردد. هرگاه احتمال تولید استثنا توسط یک متد وجود داشته باشد، کامپایلر جاوا الزام می‌کند که این استثنا توسط برنامه‌نویس مدیریت شود. بنابراین، برای ایجاد استریم ورودی قبلی، در واقع باید بنویسیم:


BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
        System.err.println("Erreur " +e);
        System.exit(1);
}

یک بار دیگر، ما در اینجا تلاش نمی‌کنیم توضیحی دربارهٔ مدیریت استثنا ارائه دهیم. پس از ایجاد جریان IN پیشین، می‌توان یک خط متن را با استفاده از عبارت زیر خواند:

    String ligne;
    ligne=IN.readLine();

خطی که روی صفحه‌کلید تایپ می‌شود در متغیر ligne ذخیره شده و سپس می‌تواند توسط برنامه پردازش شود.

2.3.3. نمونه ورودی/خروجی

در اینجا برنامه‌ای برای نمایش عملیات ورودی و خروجی صفحه‌کلید/صفحه نمایش آورده شده است:


import java.io.*;        // برای استفاده از استریم‌های ورودی/خروجی لازم است

public class io1{
  
  
  public static void main (String[] arg){
    
    // نوشتن به استریم System.out
    Object obj=new Object();
    System.out.println(""+obj);
    System.out.println(obj.getClass().getName());
    
    // نوشتن به استریم System.err
    int i=10;
    System.err.println("i="+i);
    
    //خواندن یک خط واردشده از طریق صفحه‌کلید
    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);
    }
  }//پایان ورودی

  public static void affiche(Exception e){
    System.err.println("Erreur : "+e);
  }

}//پایان کلاس

و نتایج اجرای آن:

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à

دستورالعمل‌ها

Object obj=new Object();
System.out.println(""+obj);
System.out.println(obj.getClass().getName());

منظور نشان دادن این است که هر شیئی را می‌توان نمایش داد. در اینجا قصد نداریم معنای آنچه نمایش داده می‌شود را توضیح دهیم. همچنین نمایش مقدار یک شیء در بلوک را داریم:

try{
      IN=new BufferedReader(new InputStreamReader(System.in));
    } catch (Exception e){
      affiche(e);
      System.exit(1);
    }

متغیر e یک شی از نوع Exception است که در اینجا با استفاده از فراخوانی affiche(e) نمایش داده می‌شود. ما قبلاً این نمایش مقدار استثنا را در برنامه تبدیل توصیف‌شده در بالا بدون اشاره به آن مشاهده کرده بودیم.

2.3.4. مقدار یک عبارت را به یک متغیر اختصاص دادن

اکنون در حال بررسی عملیات variable=expression; هستیم

این عبارت می‌تواند از انواع زیر باشد: عددی، مقایسه‌ای، بولی، کاراکتری

2.3.4.1. تفسیر عمل تخصیص

عمل variable=expression; خود یک عبارت است که به شرح زیر ارزیابی می‌شود:

  • سمت راست عملیات تخصیص ارزیابی می‌شود: نتیجه یک مقدار V است.
  • مقدار V به متغیر اختصاص داده می‌شود
  • مقدار V همچنین مقدار تخصیص است، این بار به عنوان یک عبارت در نظر گرفته می‌شود.

به همین دلیل عملیات V1=V2=expression معتبر است. به دلیل اولویت عملگرها، عملگر سمت راست‌تر «=» ارزیابی می‌شود. بنابراین داریم V1=(V2=expression). بیان V2=expression ارزیابی می‌شود و مقدار V را دارد. ارزیابی این بیان منجر به تخصیص مقدار V2 به V شد. سپس عملگر = بعدی به صورت زیر ارزیابی می‌شود V1=V. مقدار این عبارت همچنان V است. ارزیابی آن منجر به تخصیص V به V1 می‌شود. بنابراین، عمل V1=V2=expression یک عبارت است که ارزیابی آن

1: باعث تخصیص مقدار expression به متغیرهای V1 و V2 می‌شود

2: مقدار expression را بازمی‌گرداند.

این می‌تواند به یک عبارت به شکل زیر تعمیم داده شود: V1 = V2 = ... = Vn = expression

2.3.4.2. بیان جبری

عملگرهای مورد استفاده در عبارت‌های عددی به شرح زیر هستند:

+: جمع

  • : تفریق

*: ضرب

/: تقسیم: اگر حداقل یکی از دو عدد عملی یک عدد اعشاری باشد، نتیجه، کسر اعشاری دقیق خواهد بود. اگر هر دو عدد عملی صحیح باشند، نتیجه، کسر صحیح خواهد بود. بنابراین 5/2 → 2 و 5.0/2 → 2.5.

% : باقی‌مانده: نتیجه باقی‌مانده است، صرف‌نظر از نوع عملوندها، در حالی که کسر یک عدد صحیح است. این عملگر در واقع عمل ماژولو است.

توابع ریاضی مختلفی وجود دارند:

double sqrt(double x)
ریشه‌ی مربع
double cos(double x)
کسینوس
sin(double x)
سینوس
تنگنت
تانژانت
double pow(double x, double y)
x به توان y (x > 0)
double exp(double x)
نرخ رشد نمایی
log(double x)
لگاریتم طبیعی
double abs(double x)
مقدار مطلق

و غیره...

تمام این توابع در یک کلاس جاوا به نام Math تعریف شده‌اند. هنگام استفاده از آن‌ها، باید نام کلاس تعریف‌کننده را قبل از نام تابع بنویسید. بنابراین، شما می‌نویسید:

double x, y=4;
x=Math.sqrt(y);

تعریف کلاس 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

        // متدها
    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. ترتیب اولویت در ارزیابی عبارت‌های عددی

ترتیب تقدم عملگرها هنگام ارزیابی عبارت‌های عددی به شرح زیر است (از بالاترین به پایین‌ترین):

[fonctions], [ ( )], [ *, /, %], [+, -]

عملگرها در یک بلوک [ ] اولویت یکسانی دارند.

2.3.4.4. عبارت‌های مقایسه‌ای

عملگرها به شرح زیر هستند: <, <=, ==, !=, >, >=

ترتیب اولویت

>, >=, <, <=

==, !=

نتیجه یک عبارت رابطه‌ای مقدار بولی false در صورتی که عبارت نادرست باشد و در غیر این صورت مقدار true است.

مثال:

      boolean fin;
      int x;
      fin=x>4;

مقایسه دو کاراکتر

فرض کنید دو کاراکتر C1 و C2 وجود داشته باشند. می‌توان آن‌ها را با استفاده از عملگرها مقایسه کرد

<, <=, ==, !=, >, >=

این کدهای آن‌ها، ASCII – که اعداد هستند – با هم مقایسه می‌شوند. باید توجه داشت که، بر اساس ترتیب ASCII، روابط زیر برقرار هستند:

space < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'

مقایسه دو رشته کاراکتری

آنها کاراکتر به کاراکتر با هم مقایسه می‌شوند. اولین نابرابری که بین دو کاراکتر یافت شود، منجر به نابرابری با همان علامت برای رشته‌ها می‌شود.

مثال‌ها:

مقایسهٔ رشته‌های «Cat» و «Dog» را در نظر بگیرید.

این نابرابری آخر به این معنی است که «Cat» < «Dog».

Image

فرض کنید ما در حال مقایسه رشته‌های «Cat» و «Kitten» هستیم. این دو رشته تا زمانی که رشته «Cat» به پایان نرسد، برابر هستند. در این حالت، رشته تمام‌شده به‌عنوان «کوچکتر» اعلام می‌شود. بنابراین رابطه زیر برقرار است:

«گربه» < «بچه گربه».

تابع‌های مقایسه دو رشته

عملگرهای رابطه ای <, <=, ==, !=, >, >= در اینجا قابل استفاده نیستند. شما باید از متدهای کلاس String استفاده کنید:

String chaine1, chaine2;
chaine1=…;
chaine2=…;
int i=chaine1.compareTo(chaine2);
boolean egal=chaine1.equals(chaine2)

در مثال بالا، متغیر i مقدار زیر را خواهد داشت:

0: اگر دو رشته برابر باشند

۱: اگر رشته ۱ بزرگ‌تر از رشته ۲ باشد

-1: اگر رشته 1 کوچکتر از رشته 2 باشد

متغیر egal اگر دو رشته برابر باشند، مقدار true را خواهد داشت.

2.3.4.5. بیان‌های بولی

عملگرهای هستند: & (و) ||(or) و ! (نه). نتیجه یک عبارت بولی یک مقدار بولی است.

ترتیب اولویت ! , &&، ||

مثال:

int fin;
int x;
fin= x>2 && x<4;

عملگرهای رابطی بر عملگرهای && و || اولویت دارند.

2.3.4.6. عملیات بیت‌بیتی

عملگرها

فرض کنید i و j دو عدد صحیح باشند.

i<<n
i را n بیت به سمت چپ جابجا می‌کند. بیت‌های ورودی صفر هستند.
i>>n
i را n بیت به سمت راست جابجا می‌کند. اگر i یک عدد صحیح علامت‌دار (signed char, int, long) باشد، بیت علامت حفظ می‌شود.
i و j
عملیات OR منطقی بیت‌به‌بیت i و j را انجام می‌دهد.
i | j
عملیات OR منطقی بیت‌بیتی i و j را انجام می‌دهد.
~i
مکمل‌گیری i به 1
i^j
عملیات OU EXCLUSIF را روی i و j انجام می‌دهد

فرض کنید

    int i=0x123F, k=0xF123;
    unsigned j=0xF123;
عملکرد
مقدار
i<<4
0x23F0
i>>4
0x0123 بیت علامت حفظ می‌شود.
k>>4
0xFF12 بیت علامت حفظ می‌شود.
i&j
0x1023
i|j
0xF33F
~i
0xEDC0

2.3.4.7. ترکیب عملگرها

a=a+b را می‌توان به صورت a+=b نوشت

a=a-b را می‌توان به صورت a-=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 به شرح زیر ارزیابی می‌شود:

۱: عبارت expr_cond ارزیابی می‌شود. این یک عبارت شرطی است که مقدار true یا false را برمی‌گرداند

۲: اگر درست باشد، مقدار عبارت مقدار expr1 است. expr2 ارزیابی نمی‌شود.

۳: اگر عبارت نادرست باشد، برعکس این عمل رخ می‌دهد: مقدار عبارت، مقدار expr2 است. expr1 ارزیابی نمی‌شود.

مثال

i = (j > 4 ? j + 1 : j - 1);

مقدار زیر را به متغیر i تخصیص می‌دهد:

j+1 اگر j>4، در غیر این صورت j-1

این کار همانند نوشتن if(j&gt;4) i=j+1; else i=j-1; است، اما مختصرتر است.

2.3.4.10. اولویت‌بندی کلی عملگرها

() [] تابع
gd
! ~ ++ --
dg
اپراتورهای تبدیل نوع new ()[]
dg
* / %
gd
+ -
gd
<< >>
gd
< <= > >= instanceof
gd
== !=
gd
&
gd
^
gd
|
gd
&&
gd
||
gd
؟ :
dg
= += -= و غیره .
dg

gd: نشان می‌دهد که در مواردی که عملگرها اولویت یکسانی دارند، ترتیب ارزیابی از چپ به راست رعایت می‌شود. این بدان معناست که وقتی یک عبارت شامل عملگرهایی با اولویت یکسان باشد، عملگری که در سمت چپ‌تر قرار دارد، ابتدا ارزیابی می‌شود. dg نشان‌دهنده ترتیب ارزیابی از راست به چپ است.

2.3.4.11. نوع‌یابی

امکان دارد در داخل یک عبارت، نمایش یک مقدار را به طور موقت تغییر داد. این عمل «تغییر نوع» (type casting) نامیده می‌شود. نحو تغییر نوع یک مقدار در یک عبارت به شکل زیر است: (type) value. در این صورت مقدار، نوع مشخص‌شده را به خود می‌گیرد. این امر منجر به تغییر در نمایش مقدار می‌شود.

مثال:

int i, j;
float isurj;
isurj= (float)i/j;   // اولویت () بر /

در اینجا لازم است نوع i یا j را به عدد حقیقی تغییر دهیم؛ در غیر این صورت، تقسیم، باقی‌ماندهٔ صحیحی به جای عدد حقیقی برمی‌گرداند.

i مقداری است که دقیقاً روی ۲ بایت رمزگذاری شده است

(float) i همان مقدار است که به صورت یک عدد اعشاری بر روی ۴ بایت نزدیک‌سازی شده است

بنابراین یک تبدیل‌کد (transcoding) برای مقدار i انجام می‌شود. این تبدیل‌کد فقط در طول یک محاسبه واحد انجام می‌شود؛ متغیر i همیشه نوع خود int را حفظ می‌کند.

2.4. دستورالعمل‌های کنترل جریان برنامه

2.4.1. توقف

متد exit، که در کلاس System تعریف شده است، امکان توقف اجرای یک برنامه را فراهم می‌کند.

سینتکس : void exit(int status)

عمل: فرآیند جاری را خاتمه می‌دهد و مقدار وضعیت را به فرآیند والد بازمی‌گرداند

تابع exit فرآیند جاری را خاتمه می‌دهد و کنترل را به فرآیند فراخواننده بازمی‌گرداند. مقدار متغیر status می‌تواند توسط فرآیند فراخواننده استفاده شود. در DOS، این متغیر status در متغیر سیستمی DOS به ERRORLEVEL بازگردانده می‌شود که مقدار آن را می‌توان در یک فایل دسته‌ای بررسی کرد. در یونیکس، متغیر $? مقدار status را در صورتی که تفسیرگر فرمان، Bourne Shell (/bin/sh) باشد، بازیابی می‌کند.

مثال:

    System.exit(0);

برای خاتمه دادن به برنامه با مقدار وضعیت 0.

2.4.2. ساختار تصمیم‌گیری ساده


 syntaxe :  if (condition) {actions_condition_vraie;} else {actions_condition_fausse;}

یادداشت‌ها:

  • شرط در داخل پرانتز قرار دارد.
  • هر عمل با یک نقطه‌ویرگول دنبال می‌شود.
  • کروشه‌ها به دنبالهٔ نقطه ویرگول نیستند.
  • کروشه‌ها فقط در صورتی لازم هستند که بیش از یک عمل وجود داشته باشد.
  • بند «else» می‌تواند حذف شود.
  • هیچ «then» وجود ندارد.

معادل الگوریتمی این ساختار، ساختار «if … thenelse» است:

si condition
  alors actions_condition_vraie
  sinon actions_conditions_fausse
finsi

مثال


    if (x>0)  { nx=nx+1;sx=sx+x;} else dx=dx-x;

ساختارهای انتخابی می‌توانند در هم تودرتو شوند:

if(condition1)
if (condition2)
        {......}
      else         //شرط2
         {......}
else         //شرط۱
     {.......}

گاهی اوقات مشکل زیر پیش می‌آید:


public static void main(void){
      int n=5;

   if(n>1)
     if(n>6)
             System.out.println(">6");
     else System.out.println("<=6");
}

در مثال قبلی، else به کدام if اشاره می‌کند؟ قاعده این است که 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 عبارت if(n>6): کاری برای انجام دادن نیست 
   else System.out.println("<=1");    // شعبه else از if(n>1) 
}

در اینجا، ما می‌خواستیم یک else را پس از if(n>1) قرار دهیم، و نه یک else را پس از if(n>6). به دلیل نکتهٔ قبلی، مجبوریم برای if(n>6) یک «else» قرار دهیم که در آن هیچ دستوری وجود ندارد.

2.4.3. ساختار مورد

سینتکس به شرح زیر است:

switch(expression) {
    case v1:     
            actions1;
            break;
    case v2:     
            actions2;
            break;
         . .. .. .. .. ..
    default:     actions_sinon;
}

یادداشت‌ها

  • مقدار عبارت کنترل باید یک عدد صحیح یا یک کاراکتر باشد.
  • بیان کنترل در داخل پرانتز قرار می‌گیرد.
  • بند default ممکن است حذف شود.
  • مقادیر vi مقادیر ممکن برای عبارت هستند. اگر عبارت به vi ارزیابی شود، عملیات‌های پس از بند مورد vi اجرا می‌شوند.
  • دستور break ساختار مورد را ترک می‌کند. اگر این دستور در انتهای بلوک دستورات برای مقدار 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 با یک نقطه‌ویرگول دنبال می‌شود.
  • کروشه‌ها فقط در صورتی لازم هستند که بیش از یک عمل وجود داشته باشد.
  • کروشه منحنی با نقطه ویرگول دنبال نمی‌شود.

معادل الگوریتمی ساختار pour است:

pour i variant de id à if avec un pas de ip
        actions
finpour

که می‌تواند به ساختار tantque تبدیل شود:

    i  id
    tantque i<=if
        actions
        i i+ip
    fintantque

2.4.4.2. تعداد تکرارها نامشخص

در جاوا ساختارهای کنترل متعددی برای این سناریو وجود دارد.

حلقه while


    while(condition){
          actions;
        } 

حلقه تا زمانی که شرط برقرار باشد ادامه می‌یابد. ممکن است هرگز اجرا نشود.

نکات:

  • شرط در داخل پرانتز قرار می‌گیرد.
  • هر عمل با یک نقطه‌ویرگول دنبال می‌شود.
  • کروشه‌ها فقط در صورتی لازم هستند که بیش از یک عمل وجود داشته باشد.
  • کروشهٔ منحنی با نقطه‌ویرگول دنبال نمی‌شود.

ساختار الگوریتمی متناظر، ساختار «while» است:

tantque condition
        actions
fintantque

ساختار تکرار تا (do while)

سینتکس به شرح زیر است:


    do{
       instructions;
    }while(condition); 

حلقه تا زمانی که شرط نادرست شود یا تا زمانی که شرط برقرار باشد، ادامه می‌یابد. در این حالت، حلقه حداقل یک بار اجرا می‌شود.

یادداشت‌ها

  • شرط در داخل پرانتز قرار می‌گیرد.
  • هر عمل با یک نقطه‌ویرگول دنبال می‌شود.
  • کروشه‌ها فقط در صورتی لازم هستند که بیش از یک عمل وجود داشته باشد.
  • کروشه منحنی با نقطه ویرگول دنبال نمی‌شود.

ساختار الگوریتمی متناظر، ساختار «تکرار … تا» است:

répéter
    actions
jusqu'à condition

ساختار برای 'for'

سینتکس به شرح زیر است:


for(instructions_départ;condition;instructions_fin_boucle){
    instructions; 
}

حلقه تا زمانی که شرط برقرار باشد ادامه می‌یابد (که قبل از هر تکرار ارزیابی می‌شود). Instructions_départ قبل از ورود به حلقه برای اولین بار اجرا می‌شوند. Instructions_fin_boucle پس از هر تکرار اجرا می‌شوند.

یادداشت‌ها

  • سه آرگومان for در داخل پرانتز قرار می‌گیرند.
  • سه آرگومان for با نقطه‌ویرگول از هم جدا شده‌اند.
  • هر عمل در حلقه for با نقطه‌ویرگول پایان می‌یابد.
  • کروشه‌ها فقط در صورتی لازم هستند که بیش از یک عمل وجود داشته باشد.
  • کروشه منحنی به دنبالهٔ آن نقطه‌ویرگول قرار نمی‌گیرد.
  • دستورالعمل‌های مختلف در instructions_depart و instructions_fin_boucle با ویرگول از هم جدا شده‌اند.

ساختار الگوریتمی متناظر به شرح زیر است:

instructions_départ
tantque condition
        actions
        instructions_fin_boucle
fintantque

مثال‌ها

برنامه‌های زیر همگی مجموع 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. ساختار یک برنامه جاوا

یک برنامهٔ جاوا که از هیچ کلاس یا تابع تعریف‌شده توسط کاربر به جز تابع اصلی main استفاده نمی‌کند، ممکن است ساختار زیر را داشته باشد:


public class test1{
    public static void main(String arg[]){
        … code du programme
    }// main
}// کلاس

تابع main، که به آن متد نیز گفته می‌شود، اولین تابعی است که هنگام اجرای یک برنامه جاوا اجرا می‌شود. این تابع باید امضای زیر را داشته باشد:


    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){
            // مدیریت خطا
        }// try
    }// main
}// کلاس

در ابتدای کد منبع و پیش از تعریف کلاس، معمولاً با دستورات وارد کردن کلاس مواجه می‌شویم. برای مثال:


import java.io.*;
public class test1{
    public static void main(String arg[]){
        … code du programme
    }// main
}// کلاس

بیایید یک مثال بزنیم. عبارت نوشتن زیر را در نظر بگیرید:

System.out.println("java");

که java را روی صفحه می‌نویسد. در این دستور ساده اتفاقات زیادی در جریان است:

  • System کلاسی است که نام کامل آن java.lang.System است
  • out یک ویژگی از این کلاس با نوع java.io.PrintStream، کلاس دیگری است.
  • println یک متد از کلاس java.io.PrintStream است.

ما این توضیح را بی‌دلیل پیچیده نخواهیم کرد، زیرا این توضیح بیش از حد زود است و نیازمند درک مفهوم کلاس است که هنوز پوشش داده نشده است. می‌توان یک کلاس را به‌عنوان یک منبع در نظر گرفت. در اینجا، کامپایلر نیاز به دسترسی به دو کلاس java.lang.System و java.io.PrintStream دارد. صدها کلاس جاوا در آرشیوهایی که به آن‌ها «پکیج» نیز گفته می‌شود، سازماندهی شده‌اند. دستورات import که در ابتدای برنامه قرار می‌گیرند، برای اطلاع دادن به کامپایلر در مورد کلاس‌های خارجی مورد نیاز برنامه (کلاس‌هایی که استفاده شده‌اند اما در فایل منبعی که باید کامپایل شود، تعریف نشده‌اند) به کار می‌روند. بنابراین، در مثال ما، برنامه ما به کلاس‌های java.lang.System و java.io.PrintStream نیاز دارد. این با استفاده از دستور import مشخص می‌شود. ما می‌توانیم موارد زیر را در ابتدای برنامه بنویسیم:

import java.lang.System;
import java.io.PrintStream;

از آنجا که یک برنامه جاوا معمولاً از چندین ده کلاس خارجی استفاده می‌کند، نوشتن تمام توابع لازم import کار خسته‌کننده‌ای خواهد بود. کلاس‌ها در بسته‌ها گروه‌بندی شده‌اند، بنابراین می‌توان کل بسته را وارد کرد. بنابراین، برای وارد کردن بسته‌های java.lang و java.io، می‌نویسیم:

import java.lang.*;
import java.io.*;

پکیج java.lang شامل تمام کلاس‌های پایهٔ جاوا است و به‌طور خودکار توسط کامپایلر وارد می‌شود. بنابراین، در نهایت، شما صرفاً می‌نویسید:

import java.io.*;

2.6. مدیریت استثنا

بسیاری از توابع جاوا قادر به تولید استثناها، یعنی خطاها، هستند. ما قبلاً با یکی از این توابع، تابع readLine، مواجه شده‌ایم:


String ligne=null;
try{
      ligne=IN.readLine();
      System.out.println("ligne="+ligne);
    } catch (Exception e){
      affiche(e);
      System.exit(2);
}// try

زمانی که یک تابع احتمال پرتاب استثنا را دارد، کامپایلر جاوا از برنامه‌نویس می‌خواهد که آن را مدیریت کند تا برنامه‌هایی مقاوم‌تر در برابر خطاها تولید شوند: یک برنامه کاربردی هرگز نباید به طور غیرمنتظره از کار بیفتد. در اینجا، تابع 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

به طور جایگزین، می‌توانیم بنویسیم:

catch (Exception ex){
    System.err.println ("L'erreur suivante s'est produite : "+ex);
    ...
}//گرفتن

در اینجا یک عملیات string + Exception داریم که توسط کامپایلر به‌طور خودکار به string + Exception.toString() تبدیل می‌شود تا دو رشتهٔ کاراکتری را الحاق کند.

مثال زیر استثناء‌ای را نشان می‌دهد که در اثر تلاش برای دسترسی به عنصر آرایه‌ای که وجود ندارد، ایجاد می‌شود:

//نقاشی‌ها

// واردات
import java.io.*;

public class tab1{
  public static void main(String[] args){
    // اعلام و مقداردهی اولیهٔ یک آرایه
    int[] tab=new int[] {0,1,2,3};
    int i;
     //نمایش یک آرایه با استفاده از حلقه for
    for (i=0; i<tab.length; i++)
      System.out.println("tab[" + i + "]=" + tab[i]);
    // انداختن یک استثنا
      try{
      tab[100]=6;
    }catch (Exception e){
      System.err.println("L'erreur suivante s'est produite : " + e);
    }//try-catch
  }//main
}//کلاس

اجرای برنامه نتایج زیر را تولید می‌کند:

tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
L'erreur suivante s'est produite : java.lang.ArrayIndexOutOfBoundsException

در اینجا یک مثال دیگر آورده شده است که در آن با استثنایی که از تخصیص یک رشته به یک عدد زمانی که آن رشته نماینده عددی نیست، ایجاد می‌شود، برخورد می‌کنیم:

// واردات‌ها
import java.io.*;

public class console1{
  public static void main(String[] args){
      // ایجاد یک جریان ورودی
    BufferedReader IN=null;
    try{
        IN=new BufferedReader(new InputStreamReader(System.in));
    }catch(Exception ex){}
     // درخواست نام
    System.out.print("Nom : ");
     // خواندن پاسخ
    String nom=null;
    try{
        nom=IN.readLine();
    }catch(Exception ex){}      
     // سن درخواست‌شده
    int age=0;
    boolean ageOK=false;
    while ( ! ageOK){
       // سوال
      System.out.print("âge : ");
       // خواندن و تأیید پاسخ
      try{
        age=Integer.parseInt(IN.readLine());
        ageOK=true;
      }catch(Exception ex) {
        System.err.println("Age incorrect, recommencez...");
      }//try-catch
    }//در حالی که
     // نمایش نهایی
    System.out.println("Vous vous appelez " + nom + " et vous avez " + age + " ans");
  }//اصلی
}//کلاس

برخی از نتایج اجرا:

dos>java console1
Nom : dupont
âge : 23
Vous vous appelez dupont et vous avez 23 ans
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. کامپایل و اجرای یک برنامه جاوا

برنامه زیر را کامپایل کرده و سپس اجرا کنید:

// واردات کلاس
import java.io.*;

//کلاس تست
public class coucou{
    // تابع اصلی
  public static void main(String args[]){
      //خروجی صفحه
    System.out.println("coucou");
  }//main
}//کلاس

فایل منبعی که کلاس قبلی coucou را در خود دارد باید با نام coucou.java نامگذاری شود:

E:\data\serge\JAVA\ESSAIS\intro1>dir
10/06/2002  08:42                  228 coucou.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.exe) نیاز دارد که به آن ماشین مجازی یا JVM (ماشین مجازی جاوا) گفته می‌شود. با استفاده از کد میانی موجود در فایل .class، ماشین مجازی دستورالعمل‌های مخصوص پردازنده ماشینی را که روی آن در حال اجراست، تولید می‌کند. ماشین‌های مجازی جاوا برای انواع مختلف سیستم‌عامل‌ها (ویندوز، یونیکس، مک OS و غیره) در دسترس هستند. یک فایل .class می‌تواند توسط هر یک از این ماشین‌های مجازی و در نتیجه روی هر سیستم‌عاملی اجرا شود. این قابلیت حمل‌پذیری بین سیستم‌ها یکی از نقاط قوت اصلی جاوا است.

بیایید برنامه قبلی را کامپایل کنیم:

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 را اجرا کنیم:

E:\data\serge\JAVA\ESSAIS\intro1>"e:\program files\jdk14\bin\java" coucou
coucou

توجه داشته باشید که در درخواست اجرای بالا، پسوند .class برای فایل coucou.class که باید اجرا شود، مشخص نشده است. این پسوند ضمنی است. اگر دایرکتوری bin از JDK در داخل PATH بر روی ماشین DOS قرار داشته باشد، نیازی به مشخص کردن مسیر کامل برای فایل‌های اجرایی javac.exe و java.exe نیست. سپس به سادگی می‌نویسید

javac coucou.java
java coucou

2.8. آرگومان‌های اصلی برنامه

تابع اصلی main یک آرایه از رشته‌ها را به‌عنوان پارامتر می‌پذیرد: String[]. این آرایه شامل آرگومان‌های خط فرمان است که برای راه‌اندازی برنامه استفاده می‌شوند. بنابراین، اگر برنامه P با فرمان زیر اجرا شود:

        java P arg0 arg1 … argn

و اگر تابع main به صورت زیر تعریف شده باشد:

public static void main(String[] arg);

ما 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]);
  }
}

نتایج به‌دست‌آمده به شرح زیر است:

dos>java param1 a b c
Nombre d'arguments=3
arg[0]=a
arg[1]=b
arg[2]=c

2.9. ارسال پارامتر به یک تابع

مثال‌های قبلی تنها برنامه‌های جاوایی را با یک تابع واحد، یعنی تابع اصلی main، نشان داده‌اند. مثال زیر نشان می‌دهد چگونه از توابع استفاده کنیم و اطلاعات چگونه بین آن‌ها مبادله می‌شود. پارامترهای تابع همیشه به صورت مقدار پاس می‌شوند؛ یعنی مقدار پارامتر واقعی در پارامتر رسمی متناظر کپی می‌شود.


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);
  }
}

نتایج به‌دست‌آمده به شرح زیر است:

Paramètre formel S=maman
Paramètre effectif S=papa
Paramètre formel a=30
Paramètre effectif age=20

مقادیر پارامترهای حقیقی «papa» و 20 به پارامترهای صوری S و a کپی شدند. سپس این‌ها اصلاح شدند. با این حال، پارامترهای حقیقی بدون تغییر باقی ماندند. توجه کنید به نوع پارامترهای حقیقی:

  • S اشاره‌ای به شیء c.a.d است – نشانی حافظه یک شیء
  • age یک مقدار صحیح است

2.10. مثال مالیاتی

این فصل را با مثالی به پایان می‌رسانیم که در چندین نوبت در این سند به آن باز خواهیم گشت. ما قصد داریم برنامه‌ای بنویسیم تا بدهی مالیاتی یک مؤدی را محاسبه کند. مورد ساده‌شدهٔ مؤدی‌ای را در نظر می‌گیریم که تنها حقوق خود را برای اظهار دارد:

  • ما تعداد طبقات مالیاتی کارمند را به صورت nbParts = nbEnfants/2 + 1 در صورتی که مجرد باشد، محاسبه می‌کنیم، nbEnfants/2 + 2 اگر متأهل باشند، که در آن nbEnfants تعداد فرزندانی است که دارند.
  • اگر حداقل سه فرزند داشته باشند، مستحق دریافت نیم‌حقوق اضافی هستند
  • درآمد مشمول مالیات او به صورت R = 0.72 × S محاسبه می‌شود، که در آن S حقوق سالانه او است.
  • ضریب خانوادگی او به صورت QF = R / nbParts محاسبه می‌شود
  • مالیات I او محاسبه می‌شود. جدول زیر را در نظر بگیرید:
۱۲٬۶۲۰٫۰
0
0
۱۳٬۱۹۰
0.05
۶۳۱
۱۵٬۶۴۰
0.1
۱٬۲۹۰٫۵
۲۴٬۷۴۰
0.15
۲٬۰۷۲٫۵
۳۱٬۸۱۰
0.2
۳٬۳۰۹٫۵
۳۹٬۹۷۰
0.25
۴٬۹۰۰
۴۸٬۳۶۰
0.3
۶۸۹۸.۵
۵۵٬۷۹۰
0.35
۹٬۳۱۶٫۵
۹۲٬۹۷۰
0.4
۱۲٬۱۰۶
۱۲۷٬۸۶۰
0.45
۱۶٬۷۵۴٫۵
۱۵۱٬۲۵۰
0.50
۲۳٬۱۴۷٫۵
۱۷۲٬۰۴۰
0.55
۳۰٬۷۱۰
۱۹۵٬۰۰۰
0.60
۳۹٬۳۱۲
0
0.65
۴۹٬۰۶۲

هر سطر شامل ۳ فیلد است. برای محاسبه مالیات I، به دنبال اولین سطری می‌گردیم که QFfield1 باشد. برای مثال، اگر QF = 23000 باشد، سطر را پیدا خواهیم کرد

    24740        0.15        2072.5

مالیات I سپس برابر است با 0.15*R - 2072.5*nbParts. اگر QF به گونه‌ای باشد که شرط QF <= field1 هرگز برقرار نشود، ضرایب مربوط به آخرین خط استفاده می‌شوند. در این صورت:

    0                0.65        49062

که مالیات I = 0.65*R - 49062*nbParts را به دست می‌دهد.

برنامه جاوا متناظر به شرح زیر است:


import java.io.*;

public class impots{

    // ------------ main
    public static void main(String arg[]){

        // داده‌ها

        // آستانه‌های جدول مالیات
        double Limites[]={12620, 13190, 15640, 24740, 31810, 39970, 48360,55790, 92970, 127860, 151250, 172040, 195000, 0};    
        //ضریب اعمال‌شده بر تعداد سهام
        double Coeffn[]={0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5,12106, 16754.5, 23147.5, 30710, 39312, 49062};

        // برنامه

        // ایجاد جریان ورودی صفحه‌کلید
        BufferedReader IN=null;
        try{
            IN=new BufferedReader(new InputStreamReader(System.in));
        }
        catch(Exception e){
            erreur("Création du flux d'entrée", e, 1);
        }

            // بازیابی وضعیت تأهل
        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");

            // تعداد فرزندان
        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");
                }// تلاش
            } catch(Exception e){
                erreur("Lecture état marital",e,2);
            }// تلاش
        }// در حالی که

        // حقوق
        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");
                }// سعی کنید
            } catch(Exception e){
                erreur("Lecture Salaire",e,4);
            }// try
        }// در حالی که

            //محاسبه تعداد سهام
        double NbParts;
        if(Marie) NbParts=(double)NbEnfants/2+2;
            else NbParts=(double)NbEnfants/2+1;
        if (NbEnfants>=3) NbParts+=0.5;
        
            // درآمد مشمول مالیات
        double Revenu;
        Revenu=0.72*Salaire;

            // ضریب خانوادگی
        double QF;
        QF=Revenu/NbParts;
        
            // جستجو برای رده مالیاتی متناظر با QF
        int i;
        int NbTranches=Limites.length;
        Limites[NbTranches-1]=QF;
        i=0;
        while(QF>Limites[i]) i++;
            // مالیات
        long impots=(long)(i*0.05*Revenu-Coeffn[i]*NbParts);

        // نمایش نتیجه
        System.out.println("Impôt à payer : " + impots);
    }// اصلی

    // ------------ خطا
    private static void erreur(String msg, Exception e, int exitCode){
        System.err.println(msg+"("+e+")");
        System.exit(exitCode);
    }// خطا

}// کلاس

نتایج به‌دست‌آمده به شرح زیر است:

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