3 سال پیش / خواندن دقیقه

۳۰ نکته درباره برنامه نویسی جاوا و بهترین تمرین ها برای مبتدیان و تازه کاران

۳۰ نکته درباره برنامه نویسی جاوا و بهترین تمرین ها برای مبتدیان و تازه کاران

جاوا یکی از محبوب ترین زبان های برنامه نویسی است – برنامه های ویندوز، برنامه های وب، موبایل، شبکه، کالاهای الکترونیکی مصرفی و تنظیم دستگاه های جعبه تنظیم- جاوا همه جا است.

بیش از ۳ میلیارد دستگاه با جاوا کار می کنند. براساس گفته اوراکل ۵ میلیارد جاوا کارت در حال استفاده است. بیش از ۹ میلیون توسعه دهنده جاوا را برای نوشتن کد خود انتخاب کرده اند و در بین توسعه دهندگان محبوبیت زیادی دارد و همچنین محبوب ترین پلتفرم توسعه است.

برای تعلیم توسعه دهندگان جاوا در آینده، این مقاله مجموعه ای از بهترین روش ها را ارائه می دهد:

۱- به جای Null از مجموعه های خالی بازگشتی استفاده کنید.

اگر برنامه مجموعه ای را برمی گرداند که هیچ مقداری ندارد، مطمئن شوید که مجموعه خالی به جای عناصر Null برگردانده شده است. این باعث می شود تا تعداد زیادی “if else” برای تست عناصرNull حذف شوند.

public class getLocationName {
    return (null==cityName ? “”: cityName);
}

۲- رشته ها را با دقت استفاده کنید.

اگر دو رشته با استفاده از عملگر “+” در یک حلقه “for” به هم متصل شوند، در هر تکرار حلقه یک شی رشته ای جدید ایجاد می شود. این باعث اتلاف حافظه و افزایش زمان اجرا می شود. همچنین هنگام ساخت نمونه از یک شی رشته ای باید از سازنده ها اجتناب کنید و آن باید به طور مستقیم ساخته شود. برای مثال:

//Slower Instantiation
String bad = new String(“Yet another string object”);
//Faster Instantiation
String good = “Yet another string object”

۳- از اشیای غیر ضروری خودداری کنید.

یکی از پر هزینه ترین عملیات (از نظر استفاده از حافظه) در جاوا، Object Creation یا همان ساخت شی است. بنابراین توصیه می شود، اشیا را فقط در صورت لزوم ایجاد یا مقدار اولیه شوند. کد زیر مثالی ارائه می دهد:

import java.util.ArrayList;
import java.util.List;
public class Employees {
    private List Employees;
    public List getEmployees() {
        //initialize only when required
        if(null == Employees) {
            Employees = new ArrayList();
        }
        return Employees;
    }
}

۴- دوراهی بین آرایه (Array) و آرایه لیستی (ArrayList)

اغلب برای توسعه دهندگان تصمیم گیری درباره استفاده از ساختار ArrayList برای نوع داده آرایه سخت است. هر دوی آنها نقاط قوت و ضعف خود را دارند. انتخاب واقعاً به شرایط مورد نیاز بستگی دارد.

import java.util.ArrayList;
public class arrayVsArrayList {
    public static void main(String[] args) {
        int[] myArray = new int[6];
        myArray[7]= 10; // ArraysOutOfBoundException
        //Declaration of ArrayList. Add and Remove of elements is easy.
        ArrayList<Integer> myArrayList = new ArrayList<>();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(4);
        myArrayList.add(5);
        myArrayList.remove(0);
        for(int i = 0; i < myArrayList.size(); i++) {
        System.out.println(“Element: ” + myArrayList.get(i));
        }
        //Multi-dimensional Array
        int[][][] multiArray = new int [3][3][3];
    }
}

۱- آرایه ها اندازه ثابتی دارند اما اندازه در ArrayListها متغیر است. از آنجا که اندازه آرایه ثابت است، حافظه برای متغیر نوع آرایه در زمان اعلان و تعریف آن اختصاص می یابد. در نتیجه آرایه ها بسیار سریع هستند.

از طرف دیگر اگر اندازه داده معلوم نباشد، در آرایه برای تعداد داده های بیشتر منجر به خطای ایندکس خارج از محدوه اندازه آرایه می شود و تعداد داده های کمتر باعث اتلاف فضای ذخیره سازی می شود.

۲- اضافه یا حذف عناصر از ArrayList بسیار ساده تر از آرایه است.

۳- آرایه می تواند چند بعدی باشد اما ArrayList تنها می تواند یک بعد داشته باشد.

۵- چه زمانی کد Finally در Try اجرا نمی شود؟

قطعه کد زیر را در نظر بگیرید:

public class shutDownHooksDemo {
    public static void main(String[] args) {
        for(int i=0;i<5;i++)
        {
            try {
                if(i==4) {
                    System.out.println(“Inside Try Block.Exiting without executing Finally block.”);
                    System.exit(0);
                }
            }
            finally {
                System.out.println(“Inside Finally Block.”);
            }
        }
    }
}

در برنامه بالا به نظر می رسد که “println” در بلاکfinally ، ۵ بار اجرا می شود. اما در صورت اجرای برنامه، کاربر متوجه می شود که بلاکfinally  فقط ۴ بار فراخوانی می شود. در تکرار پنجم تابع exit فراخوانی می شود و finally  هرگز برای بار پنجم فراخوانی نمی شود. دلیلش این است که اجرای تابع System.exit اجرای تمام موضوعات در حال اجرا از جمله جریان فعلی را متوقف می کند. حتی بلاک finally که بعد از try قرار دارد با اجرای exit اجرا نمی شود.

وقتی System.exit فراخوانی می شود، JVM دو کار پاکسازی قبل از توقف برنامه انجام می دهد:

  • در ابتدا همه ماژول های ثبت شده در Runtime.addShutdownHook را متوقف می کند. این بسیار مفید است زیرا منابع را به بیرون از JVM منتقل می کند.
  • دومی مربوط بهFinalizers (فینالیزرها)، چه System.runFinalizerOnExit و چه Runtime.runFinalizersOnExit باشد. استفاده از فینالیزرها برای مدت زمان طولانی است که منسوخ شده است. فینالیزرها می توانند روی اشیاء زنده در زمان استفاده توسط تریدهای دیگر اجرا شوند. این کار منجر به نتایج نامطلوب یا حتی بن بست می شود.
public class shutDownHooksDemo {
    public static void main(String[] args) {
            for(int i=0;i<5;i++)
            {
                    final int final_i = i;
                    try {
                            Runtime.getRuntime().addShutdownHook(
                                            new Thread() {
                                            public void run() {
                                            if(final_i==4) {
                                            System.out.println(“Inside Try Block.Exiting without executing Finally block.”);
                                            System.exit(0);
                                            }
                                            }
                                            });
                    }
                    finally {
                            System.out.println(“Inside Finally Block.”);
                    }
            }
    }
}

۶- بررسی فرد بودن عدد

به کدهای زیر نگاهی بیندازید و تعیین کنید که آیا می توان از آنها برای شناسایی دقیق یک عدد فرد استفاده کرد؟

public boolean oddOrNot(int num) {
    return num % 2 == 1;
}

این کدها صحیح به نظر می رسند اما هر چهار بار یک بار نتایج نادرست برمی گرداند (از نظر آماری). یک عدد فرد منفی را در نظر بگیرید، باقیمانده تقسیم بر ۲ آن عدد برابر با ۱ نخواهد بود. بنابراین، نتیجه بازگشتی فالس (false) خواهد بود که نادرست است!

می تواند آن را به صورت زیر درست کرد:

public boolean oddOrNot(int num) {
    return (num & 1) != 0;
}

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

۷- تفاوت بین نقل قول ها با تک کوتیشن و دابل کوتیشن

public class Haha {
    public static void main(String args[]) {
    System.out.print(“H” + “a”);
    System.out.print(‘H’ + ‘a’);
    }
}

از کد نوشته شده به نظر می رسد “HaHa” برگردانده می شود اما در واقع ۱۶۹ Ha را برمی گرداند. دلیل این امر این است که اگر از نقل قول با دو کوتیشن استفاده شود، کاراکترها به عنوان یک رشته مورد استفاده قرار می گیرند اما در صورت استفاده از نقل قول های تک کوتیشن، عملوندهای ( ‘H’و ‘a’) از طریق فرایندی به نام به “تبدیل داده اولیه بزرگتر” به مقادیر عدد صحیح (int) مقداردهی می شود. پس از تبدیل عدد صحیح، اعداد اضافه می شوند و مقدار ۱۶۹ را برمی گردند.

۸- جلوگیری از اتلاف حافظه با ترفندهای ساده

اتلاف حافظه اغلب باعث تخریب عملکرد نرم افزار می شود. از آنجا که جاوا به طور خودکار حافظه را مدیریت می کند، توسعه دهندگان کنترل زیادی ندارند. اما هنوز تعدادی روش استاندارد برای جلوگیری از اتلاف حافظه وجود دارد.

  • پس از تکمیل درخواست، اتصالات پایگاه داده را آزاد کنید.
  • از بلاک Finally به عنوان یک امکان همیشگی استفاده کنید.
  • موارد ذخیره شده در جدول ها پویا را آزاد کنید.

۹- جلوگیری از بن بست ها در جاوا

بن بست ممکن است به دلایل مختلف رخ دهد. هیچ دستور العمل واحدی برای جلوگیری از بن بست وجود ندارد. معمولا بن بست زمانی اتفاق می افتد که یک شیء هماهنگ شده منتظر آزاد شدن منابع قفل شده توسط یک شی دیگر هماهنگ شده است.

برنامه زیر را اجرا کنید. این برنامه یک بن بست را نشان می دهد. در اینجا بن بست به وجود می آید زیرا هر دو ترید منتظر منابعی هستند که توسط ترید دیگری گرفته شده است. هر دو آنها منتظر هستند و هیچ منبعی آزاد نمی شود.

public class DeadlockDemo {
   public static Object addLock = new Object();
   public static Object subLock = new Object();
   public static void main(String args[]) {
      MyAdditionThread add = new MyAdditionThread();
      MySubtractionThread sub = new MySubtractionThread();
      add.start();
      sub.start();
   }
private static class MyAdditionThread extends Thread {
      public void run() {
         synchronized (addLock) {
        int a = 10, b = 3;
        int c = a + b;
            System.out.println(“Addition Thread: ” + c);
            System.out.println(“Holding First Lock…”);
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println(“Addition Thread: Waiting for AddLock…”);
            synchronized (subLock) {
               System.out.println(“Threads: Holding Add and Sub Locks…”);
            }
         }
      }
   }
   private static class MySubtractionThread extends Thread {
      public void run() {
         synchronized (subLock) {
        int a = 10, b = 3;
        int c = a – b;
            System.out.println(“Subtraction Thread: ” + c);
            System.out.println(“Holding Second Lock…”);
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println(“Subtraction  Thread: Waiting for SubLock…”);
            synchronized (addLock) {
               System.out.println(“Threads: Holding Add and Sub Locks…”);
            }
         }
      }
   }
}

خروجی

=====

Addition Thread: 13

Subtraction Thread: 7

Holding First Lock…

Holding Second Lock…

Addition Thread: Waiting for AddLock…

Subtraction  Thread: Waiting for SubLock…

اما اگر نظم فراخوانی نخ ها تغییر یابد، مسئله بن بست حل می شود.

public class DeadlockSolutionDemo {
   public static Object addLock = new Object();
   public static Object subLock = new Object();
   public static void main(String args[]) {
      MyAdditionThread add = new MyAdditionThread();
      MySubtractionThread sub = new MySubtractionThread();
      add.start();
      sub.start();
   }
private static class MyAdditionThread extends Thread {
      public void run() {
         synchronized (addLock) {
        int a = 10, b = 3;
        int c = a + b;
            System.out.println(“Addition Thread: ” + c);
            System.out.println(“Holding First Lock…”);
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println(“Addition Thread: Waiting for AddLock…”);
            synchronized (subLock) {
               System.out.println(“Threads: Holding Add and Sub Locks…”);
            }
         }
      }
   }
   private static class MySubtractionThread extends Thread {
      public void run() {
         synchronized (addLock) {
        int a = 10, b = 3;
        int c = a – b;
            System.out.println(“Subtraction Thread: ” + c);
            System.out.println(“Holding Second Lock…”);
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println(“Subtraction  Thread: Waiting for SubLock…”);
            synchronized (subLock) {
               System.out.println(“Threads: Holding Add and Sub Locks…”);
            }
         }
      }
   }
}

خروجی

=====

Addition Thread: 13

Holding First Lock…

Addition Thread: Waiting for AddLock…

Threads: Holding Add and Sub Locks…

Subtraction Thread: 7

Holding Second Lock…

Subtraction  Thread: Waiting for SubLock…

Threads: Holding Add and Sub Locks…

۱۰- برای جاوا حافظه رزرو کنید.

برخی از برنامه های جاوا می توانند به شدت به CPU و همچنین مقدار حافظه رم زیادی احتیاج داشته باشند. چنین برنامه هایی به دلیل نیاز به حافظه رم معمولاً کند هستند. به منظور بهبود عملکرد چنین برنامه هایی، RAM برای جاوا قابل رزرو است. به عنوان مثال، اگر یک سرویس دهنده وب Tomcat داریم و رم آن ۱۰ گیگ است. در صورت تمایل می توانیم برای تخصیص RAM برای جاوا در این دستگاه از دستور زیر استفاده کنیم:

export JAVA_OPTS=”$JAVA_OPTS -Xms5000m -Xmx6000m -XX:PermSize=1024m -XX:MaxPermSize=2048m”

  • Xms = حداقل حافظه اختصاص یافته
  • Xmx = حداکثر حافظه ختصاص یافته
  • XX: PermSize = اندازه اولیه ای که هنگام شروع JVM اختصاص داده می شود.
  • XX: MaxPermSize = حداکثر اندازه ای که می توان هنگام راه اندازی JVM اختصاص یابد.

۱۱- شیوه کار با زمان در جاوا

دو روش استاندارد برای کار با زمان در جاوا وجود دارد: ()System.currentTimeMillis و ()System.nanoTime.

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

۱- System.currentTimeMillis جایی بین ۱۰۰۰/۱ام ثانیه تا ۱۰۰۰/۱۵ام ثانیه (وابسته به سیستم) قرار می گیرد اما System.nanoTime تقریباً ۱۰۰۰۰۰۰/۱ام ثانیه (۱۰۰۰ نانوثانیه) طول می کشد.

۲-System.currentTimeMillis برای انجام عملیات خواندن تعداد چرخه ساعت کمتری دارد. از طرف دیگر System.nanoTime بیش از ۱۰۰چرخه ساعت دارد.

۳- System.currentTimeMillis زمان مطلق را نشان می دهد (تعداد میلی ثانیه ها از تاریخ ۱ ژانویه ۱۹۷۰ ساعت ۰۰:۰۰ (زمان Epoch)) اما System.nanoTime لزوماً هیچ نقطه مبدایی را نشان نمی دهد.

۱۲- انتخاب بین Float و Double

رقم های اعشاری بایت های مورد استفاده نوع داده
۷ ۴ Float
۱۵ ۸ Double

اغلب Double به float در نرم افزار ترجیح داده می شود.

بیشتر پردازنده ها تقریباً میزان زمان پردازش یکسانی برای انجام عملیات روی Float و Double دارند. Double دقت بسیار بیشتری را در همان زمان محاسبات ارائه می دهد.

۱۳- محاسبه توان

برای محاسبه توان (^)، جاوا OR اختصاصی یا همان XOR را انجام می دهد. برای محاسبه توان، جاوا دو گزینه ارائه می دهد:

۱-ضرب:

double square = double a * double a;                            // Optimized

double cube = double a * double a * double a;                   // Non-optimized

double cube = double a * double square;                         // Optimized

double quad = double a * double a * double a * double a;       // Non-optimized

double quad = double square * double square;                    // Optimized

۲- (توان ، پایه)pow: از متد‘pow’ برای محاسبه توان جایی که ضرب امکان پذیر نباشد، (توان ^ پایه)؛

double cube = Math.pow(base, exponent);

تنها در صورت لزوم باید از Math.pow استفاده شود. به عنوان مثال، توان یک مقدار کسری باشد. دلیل این است که روش Math.pow معمولاً حدود ۳۰۰ تا ۶۰۰ برابر کندتر از ضرب است.

۱۴- نحوه مدیریت استثناء Null

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

int noOfStudents = school.listStudents().count;

اگر در مثال بالا، یک NullPointerException دریافت کردید، آنگاه یاschool و یا ()listStudents  برابر با null است. ایده خوب این است که گزینه های Null را هرچه سریعتر بررسی کنید تا حذف شوند.

private int getListOfStudents(File[] files) {
      if (files == null)
        throw new NullPointerException(“File list cannot be null”);
    }

۱۵- رمزگذاری در JSON

JSONمخفف JavaScript Object Notation (نشانه‌گذاری شیء جاوااسکریپت) ساختاری برای ذخیره سازی و تبادل داده است. JSON یک جایگزین با کاربرد آسانتر برای XML است. Json این روزها به دلیل ویژگی ها و حجم کمش در اینترنت بسیار محبوب شده است. یک ساختار داده عادی را می توان در JSON رمزگذاری کرد و به راحتی در صفحات وب به اشتراک گذاشت. قبل از شروع به نوشتن کد، یک تجزیه کننده JSON باید نصب شده باشد. در مثال های زیر ازjson.simple استفاده کرده ایم.

(https://code.google.com/p/json-simple/)

در زیر مثال ساده زیر رمزگذاری در JSON آورده شده است:

import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
public class JsonEncodeDemo {
    public static void main(String[] args) {
        JSONObject obj = new JSONObject();
        obj.put(“Novel Name”, “Godaan”);
        obj.put(“Author”, “Munshi Premchand”);
        JSONArray novelDetails = new JSONArray();
        novelDetails.add(“Language: Hindi”);
        novelDetails.add(“Year of Publication: 1936”);
        novelDetails.add(“Publisher: Lokmanya Press”);
        obj.put(“Novel Details”, novelDetails);
        System.out.print(obj);
    }
}

خروجی

{“Novel Name”:”Godaan”,”Novel Details”:[“Language: Hindi”,”Year of Publication: 1936″,”Publisher: Lokmanya Press”],”Author”:”Munshi Premchand”}

۱۶- جستجوی ساده رشته

جاوا یک متد کتابخانه ای به نام ()indexOf را پیشنهاد می دهد. این متد با شی رشته ای استفاده می شود و موقعیت ایندکس رشته مورد نظر را برمی گرداند. اگر رشته پیدا نشد ، مقدار ۱- بازگردانده می شود.

public class StringSearch {
    public static void main(String[] args) {
        String myString = “I am a String!”;
        if(myString.indexOf(“String”) == -1) {
            System.out.println(“String not Found!”);
        }
        else {
            System.out.println(“String found at: ” + myString.indexOf(“String”));
        }
    }
}

۱۷- محتوای لیست یک دایرکتوری

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

import java.io.*;
public class ListContents {
    public static void main(String[] args) {
        File file = new File(“//home//user//Documents/”);
        String[] files = file.list();
        System.out.println(“Listing contents of ” + file.getPath());
        for(int i=0 ; i < files.length ; i++)
        {
            System.out.println(files[i]);
        }
    }
}

۱۸- ورودی و خروجی ساده

به منظور خواندن از فایل و نوشتن در فایل، Java کلاس های FileInputStream و FileOutputStream را ارائه می دهد. سازنده FileInputStream ، مسیر فایل ورودی را به عنوان آرگومان قبول می کند و جریان ورودی فایل را ایجاد می کند. به طور مشابه، سازنده FileOutputStream ، مسیر فایل خروجی را به عنوان آرگومان پذیرفته و جریان خروجی فایل را ایجاد می کند. “بستن” جریان ها پس از انجام کار با فایل مهم است.

import java.io.*;
public class myIODemo {
    public static void main(String args[]) throws IOException {
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream(“//home//user//Documents//InputFile.txt”);
            out = new FileOutputStream(“//home//user//Documents//OutputFile.txt”);
            int c;
            while((c = in.read()) != -1) {
                out.write(c);
            }
        } finally {
            if(in != null) {
                in.close();
            }
            if(out != null) {
                out.close();
            }
        }
    }
}

۱۹- اجرای دستور shell از Java

جاوا کلاس Runtime را برای اجرای دستورات Shell ارائه می دهد. از آنجا که این دستورات خارجی هستند، مدیریت استثناء بسیار مهم است. در مثال زیر این کار را با یک مثال ساده نشان می دهیم. در اینجا در حال تلاش برای باز کردن یک فایل PDF با دستور Shell هستیم.

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ShellCommandExec {
    public static void main(String[] args) {
        String gnomeOpenCommand = “gnome-open //home//user//Documents//MyDoc.pdf”;
        try {
            Runtime rt = Runtime.getRuntime();
            Process processObj = rt.exec(gnomeOpenCommand);
            InputStream stdin = processObj.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stdin);
            BufferedReader br = new BufferedReader(isr);
            String myoutput = “”;
            while ((myoutput=br.readLine()) != null) {
                myoutput = myoutput+”\n”;
            }
            System.out.println(myoutput);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

۲۰- استفاده از عبارات منظم و با قاعده

خلاصه ای از ساختارهای عبارت منظم (منبع: وب سایت اوراکل)

کاراکتر
کاراکتر x

X

کاراکتر بک اسلش

\\

کاراکتری با مقدار اوکتال یا مبنای هشت ۰n (0 <= n <= 7)

\۰n

کاراکتری با مقدار اوکتال یا مبنای هشت ۰nn (0 <= n <= 7)

\۰nn

کاراکتری با مقدار اوکتال یا مبنای هشت ۰mnn (0 <= m <= 3 , 0 <= n <= 7)

\۰mnn

کاراکتری با مقدار هگزا دسیمال یا مبنای شانزده ۰xh

\xhh

کاراکتری با مقدار هگزا دسیمال یا مبنای شانزده ۰xhhhh

\uhhhh

کارکتری با مقدار هگزا دسیمال یا مبنای شانزده ۰xh…h

(Character.MIN_CODE_POINT <= 0xh…h <= Character.MAX_CODE_POINT)

\x{h…h}

کاراکتر تب (‘\u0009’)

\t

کاراکتر خط جدید – تعویض خط (‘\u000A’)

\n

کاراکتر بازگشتی حمل (‘\u000D’)

\r

 کاراکتر تغذیه فرم (‘\u000C’)

\f

کاراکتر هشدار (زنگ) (‘\u0007’)

\a

کاراکتر اسکیپ (‘\u001B’)

\e

کاراکتر کنترل مربوط به x

\cx

 


کلاس های کاراکتر
a ، b یا c (کلاس ساده)

[abc]

همه کاراکترها به جز a ، b یا c (نقیض)

[^abc]

a تا z یا A تا Z ، شامل (دامنه)

[a-zA-Z]

a تا d یا m تا :p [a-dm-p] (اجتماع)

[a-d[m-p]]

d ، e یا f (اشتراک)

[a-z&&[def]]

A تا z به جز b و :c [ad-z] (تفریق)

[a-z&&[^bc]]

a تا z و نه m تا p : [a-lq-z] (تفریق)

[a-z&&[^m-p]]

 


کلاس های کاراکتری تعریف شده
هر کاراکتری (ممکن است با نقطه انتهای خط مطابقت داشته باشد یا نباشد) .
یک رقم: [۹-۰]

\d

کاراکتر غیرعددی: [ ۹-۰^]

\d

یک کاراکتر فضای خالی: [\t \ n \ x0B \ f \ r]

\s

بدون کاراکتر فضای خالی: [S\^]

\s

یک کاراکتر کلمه ای: [a-zA-Z_0-9]

\w

یک کاراکتر غیر کلمه ای: [w \^]

\w

 


تطابق دهنده های مرزی
ابتدای یک خط

^

پایان یک خط

$

مرز کلمه ای

\b

مرز غیر کلمه

\b

شروع ورودی

\a

انتهای تطبیق قبلی

\G

پایان ورودی اما در صورت وجود نقطه انتهای آخری

\Z

پایان ورودی

\Z

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches
{
    private static String pattern =  “^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$”;
    private static Pattern mypattern = Pattern.compile(pattern);
    public static void main( String args[] ){
        String valEmail1 = “[email protected]”;
        String invalEmail1 = “…[email protected]”;
        String invalEmail2 = “.$$%%@domain.com”;
        String valEmail2 = “[email protected]”;
        System.out.println(“Is Email ID1 valid? “+validateEMailID(valEmail1));
        System.out.println(“Is Email ID1 valid? “+validateEMailID(invalEmail1));
        System.out.println(“Is Email ID1 valid? “+validateEMailID(invalEmail2));
        System.out.println(“Is Email ID1 valid? “+validateEMailID(valEmail2));
    }
    public static boolean validateEMailID(String emailID) {
        Matcher mtch = mypattern.matcher(emailID);
        if(mtch.matches()){
            return true;
        }
        return false;
    }
}

۲۲- گرفتن خروجی به صورت PDF

اکسپورت یک جدول به PDF یک تقاضای رایج در برنامه های جاوا است. با استفاده از itextpdf، گرفتن خروجی به صورت PDF بسیار آسان می شود.

import java.io.FileOutputStream;
import com.itextpdf.text.Document;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
public class DrawPdf {
      public static void main(String[] args) throws Exception {
        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(“Employee.pdf”));
        document.open();
        Paragraph para = new Paragraph(“Employee Table”);
        para.setSpacingAfter(20);
        document.add(para);
        PdfPTable table = new PdfPTable(3);
        PdfPCell cell = new PdfPCell(new Paragraph(“First Name”));
        table.addCell(cell);
        table.addCell(“Last Name”);
        table.addCell(“Gender”);
        table.addCell(“Ram”);
        table.addCell(“Kumar”);
        table.addCell(“Male”);
        table.addCell(“Lakshmi”);
        table.addCell(“Devi”);
        table.addCell(“Female”);
        document.add(table);
        document.close();
      }
    }

۲۳- اندازه گیری زمان

بسیاری از برنامه ها نیاز به اندازه گیری بسیار دقیق زمان دارند. برای این منظور، جاوا روش های ایستایی را در کلاس System ارائه می دهد:

۱- ()currentTimeMillis: زمان فعلی را به میلی ثانیه از زمان Epoch به اندازه داده long باز می گرداند.

۱٫ long startTime = System.currentTimeMillis();

۲٫ long estimatedTime = System.currentTimeMillis() – startTime;

۲- ()nanoTime: مقدار فعلی دقیق ترین زمان سنج موجود در سیستم را به نانو ثانیه به اندازه داده long می گرداند. در مقابل ارئه زمان بندی مطلق، nanoTime برای اندازه گیری فاصله زمانی نسبی است.

۱٫ long startTime = System.nanoTime();

۲٫ long estimatedTime = System.nanoTime() – startTime;

۲۴- تغییر مقیاس تصویر

یک تصویر را می توان با استفاده از AffineTransform تغییر مقیاس داد. اول از همه، بافر تصویر از تصویر ورودی ایجاد می شود و سپس تصویر با تغییر مقیاس ارائه می شود.

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class RescaleImage {
  public static void main(String[] args) throws Exception {
    BufferedImage imgSource = ImageIO.read(new File(“images//Image3.jpg”));
    BufferedImage imgDestination = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = imgDestination.createGraphics();
    AffineTransform affinetransformation = AffineTransform.getScaleInstance(2, 2);
    g.drawRenderedImage(imgSource, affinetransformation);
    ImageIO.write(imgDestination, “JPG”, new File(“outImage.jpg”));
  }
}

۲۵- گرفتن مختصات شناور موس

با پیاده سازی رابط MouseMotionListner، می توان رویدادهای ماوس را ضبط کرد. هنگامی که ماوس وارد یک منطقه خاص می شود، رویداد MouseMoving شروع می شود و مختصات حرکت را می توان ضبط کرد. مثال زیر آن را توضیح می دهد:

import java.awt.event.*;
import javax.swing.*;
public class MouseCaptureDemo extends JFrame implements MouseMotionListener
{
    public JLabel mouseHoverStatus;
    public static void main(String args[])
    {
        new MouseCaptureDemo();
    }
    MouseCaptureDemo()
    {
        setSize(500, 500);
        setTitle(“Frame displaying Coordinates of Mouse Motion”);
        mouseHoverStatus = new JLabel(“No Mouse Hover Detected.”, JLabel.CENTER);
        add(mouseHoverStatus);
        addMouseMotionListener(this);
        setVisible(true);
    }
    public void mouseMoved(MouseEvent e)
    {
        mouseHoverStatus.setText(“Mouse Cursor Coordinates => X:”+e.getX()+” | Y:”+e.getY());
    }
    public void mouseDragged(MouseEvent e)
    {}
}

۲۶- FileOutputStream در مقابل FileWriter

نوشتن در فایل در جاوا اغلب با دو روش انجام می شود: FileOutputStream و FileWriter.. گاهی اوقات، توسعه دهندگان برای انتخاب یکی از آنها دچار چالش می کنند. این مثال به آنها در انتخاب هر کدام تحت شرایط مورد نیاز کمک می کند. بیاید نگاهی به قسمت اجرا بیندازیم:

استفاده از :FileOutputStream

File foutput = new File(file_location_string);
FileOutputStream fos = new FileOutputStream(foutput);
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(fos));
output.write(“Buffered Content”);

استفاده از :FileWriter

FileWriter fstream = new FileWriter(file_location_string);
BufferedWriter output = new BufferedWriter(fstream);
output.write(“Buffered Content”);

مطابق مشخصات Java API:

FileOutputStream برای نوشتن جریان بایت های خام مانند داده های تصویر است. برای نوشتن جریان کاراکترها از از FileWriter استفاده کنید.

این کاملاً واضح است که برای نوع داده تصویر باید از FileOutputStream و برای نوع داده متن از FileWriter استفاده شود.

پیشنهادات بیشتر

۱- از Collections (مجموعه ها) استفاده کنید.

جاوا با تعدادی کلاس های مجموعه عرضه می شود – به عنوان مثال: بردار، پشته، جدول هش، آرایه. به توسعه دهندگان توصیه می شود به دلایل زیر تا حد امکان از مجموعه ها استفاده کنند:

۱- استفاده از مجموعه باعث می شود که کد قابلیت استفاده مجدد و قابل تغییر باشد.

۲- مجموعه ها باعث می شوند تا کد ساختار یافته تر و درک و حفظ آن آسان تر شود.

۳-کلاس های مجموعه از جنبه های مختلف به خوبی آزمایش شده اند، بنابراین کیفیت کد خوب است.

۲- قانون ۵۰۰-۵۰-۱۰

در بسته های بزرگ نرم افزاری، حفظ کد بسیار چالش برانگیز می شود. توسعه دهندگان تازه واردی که در جریان پروژه های پشتیبانی به اضافه می شوند، اغلب از این موضوع شکایت دارند: کد یکپارچه، کد اسپاگتی. برای جلوگیری از این مسئله یا تمیز نگه داشتن کد یک قانون بسیار ساده وجود دارد: ۵۰۰-۵۰-۱۰٫

  • ۱۰: هیچ بسته ای نمی تواند بیش از ۱۰ کلاس داشته باشد.
  • ۵۰: هیچ متدی نمی تواند بیش از ۵۰ خط کد داشته باشد.
  • ۵۰۰: هیچ کلاس نمی تواند بیش از ۵۰۰ خط کد داشته باشد.

۳- اصول طراحی کلاس SOLID

SOLID برگرفته اصول طراحی است که توسط رابرت مارتین ابداع شده است. طبق این قانون:

توضیحات قانون
یک کلاس باید یک و تنها یک وظیفه یا مسئولیت داشته باشد. اگر کلاس بیش از یک کار را انجام دهد منجر به سردرگمی می شود. Single responsibility principle

(اصل مسئولیت پذیری واحد)

توسه دهندگان باید بیشتر تمرکز خود را بر گسترش نهادهای نرم افزاری به جای تغییر در آنها قرار دهند. Open/closed principle

(اصل باز/ بسته)

می توان کلاس مشتق شده را با کلاس پایه جایگزین کرد. Liskov substitution principle

(اصل جایگزینی لیسکوف)

مانند اصل مسئولیت پذیری واحد است اما برای رابط ها اجرا می شود. هر رابط باید مسئول یک کار خاص باشد. توسعه دهندگان باید متدهایی را که نیازی به آن ندارند، پیاده سازی کنند. Interface segregation principle

(اصل تفکیک رابط)

به انتزاع بستگی دارد- اما به پیوند بستگی ندارد. این بدان معنی است که ماژول ها باید با استفاده از لایه انتزاعی که آنها را به هم وصل می کنند، از یکدیگری جدا شوند. Dependency inversion principle

(اصل وارونگی وابستگی)

۴- استفاده از الگوهای طراحی

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

۵- ایده های سندسازی

تنها شروع به نوشتن کد نکنید. استراتژی، آماده سازی، سند، بررسی و اجرا. اول از همه نیازهای خود را بنویسید. یک سند طراحی فراهم کنید. فرضیات را به درستی ذکر کنید. اسناد را به طور دقیق بررسی کنید و آنها را تایید و تمام کنید.

۶- استفاده از دو مساوی ==

عملگر == منابع اشیا را نیز مقایسه می کند. بررسی می کند که آیا دو عملوند به یک شیء مشابه (نه اشیاء معادل دقیقا همان شیء) اشاره می کنند. از طرف دیگر مقایسه واقعی دو رشته را انجام می دهد.

۷- از اعداد اعشاری با دو رقم اعشار خودداری کنید

اعداد اعشاری با دو رقم اعشار فقط باید در صورت لزوم مورد استفاده قرار می گیرند. به عنوان مثال، در واحدهای ارزی استفاده از اعداد اعشاری می تواند مشکل ساز باشد – در عوض باید نوع داده BigDecimal ترجیح داده شود. اعداد اعشاری با دو رقم اعشار در اندازه گیری ها مفیدتر هستند.


شاید از نوشته‌های زیر خوشتان بیاید
نظر خود را درباره این پست بنویسید ...

منوی سریع