1. بسم الله الرحمن الرحيم
    عندما نريد إنشاء  instance من class معين فإننا غالبا ما نقوم بإستخدام public constructor, لكن هنا طريقة أخرى, يجب أن يكون المبرمج ملماً بها, ألا وهي  public static factory method. ببساطة شديدة هي دالة static تقوم بإرجاع -return- لـ instance   من  class, على سبيل المثال:
    public class Client { public static Client getInstance() { return new Client(); } } كما نلاحظ أن المفهوم في غاية البساطة, لكن متى أحتاج أن أستخدمه ؟ , سنقوم الان بالمقارنة بينه وبين  Constructor, ونستعرض المميزات والعيوب.
    أولا, تتميز static factory method بكونها قابلة لتسمية, فعلى سبيل المثال لو كان لدينا مركز رياضي ونوعين من العملاء, مشترك وزائر, المشترك ندخل أسمه, أما الزائر فنكتب فقط زائر, فسيكون شكل class كالتالي
    public class Client { private String name; public static Client getVisitorInstance() { Client client = new Client(); client.name = "visitor"; return client; } public static Client getSubscribedInstance(String name) { Client client = new Client(); client.name = name; return client; } } دعنا نقوم بإستدعائها, واستدعاء constructor.
    Client client1 = Client.getVisitorInstance(); Client client2 = Client.getSubscribedInstance("Abdulaziz"); Client client3 = new Client(); Client client4 = new Client("Abdulziz"); كما نلاحظ, في static factory method من النظرة الأولى, تمكنت من معرفة نوع العميل, بالإضافة إلى أنه لو أراد شخص ما إكمال تطوير المشروع, سيتمكن من التعامل مع class الذي قمت ببنائه دون النظر فيه -Readability-, على عكس  public constructor.
    ثانيا, من خلال static factory method يمكنك أن تجبر مستخدم الـ class على إنشاء instance واحد فقطلهذا الـ class, وهو ما نسميه بـ singleton, كما في المثال
    public class Client { private static final Client client = new Client(); private Client(){ } public static Client getClient() { return client; } } كما نلاحظ أن constructor private, بمعنى أنه لا يمكنك إنشاء instance عن طريقه, لكن تستخدم static factory method والتي دائما ستعيد لك نفس  object الذي هو client, وبهذا لن تحصل إلا على object واحد فقط عن طريق هذا class.
    ثالثا, يمكن لـ static factory method أن يقوم بعمل return لـ  instance من sub-type لـ class, على سبيل المثال لدينا class يقوم بإزالة الزوائد من القيم الداخلة إليه, مثلا لو تلقى قيمة 0010 يقوم بحذف الأصفار, ولو تلقى “محمد  ” يقوم بحذف space وهكذا, لنبدأ في الكود.
    بداية سنقوم بإنشاء Interface بإسم  trimmer
    public interface Trimmer<T> { T trim(); } الان, سنقوم بإنشاء class لتعامل مع String
    public class StringTrim implements Trimmer<String> { String value; StringTrim(String value) { this.value = value; } @Override public String trim() {...} } وأخر لتعامل مع Integer
    public class IntegerTrim implements Trimmer<Integer> { Integer value ; IntegerTrim(Integer value) { this.value = value; } @Override public Integer trim() {...} } نلاحظ أن access modifier  لـ constructor من نوع  package-private أي لا يمكن الوصول إليه من خارج  package,  ثم نقوم بإنشاء class  نستخدمه إذا ما أردنا الإستفادة من classes السابقة
    public class Trimmers { private Trimmers(){} public static Trimmer<String> getTrimString(String s){ return new StringTrim(s); } public static Trimmer<Integer> getTrimInteger(Integer i){ return new IntegerTrim(i); } } نلاحظ هنا كيف استفدنا من static factory method, بحث أنه قام بإرجاع object, عبارة عن sub-type لـ return type.
    وفي main نستدعيه بالطريقة التالية:
    Integer i = Trimmers.getTrimInteger(0150).trim(); String s = Trimmers.getTrimString(" abdulaziz").trim(); وهذا الأسلوب يسمى  interface-based API أو interface-based frameworks
    بعد استعراضات المميزات لـ static factory method, لنستعرض السلبيات, وهما اثنتين.
    الأولى, لا يمكن الوراثة -inheritance- من class لا يوجد فيه public or protected constructor, ففي هذه الحالة لا يمكن لـ static factory method أن تعوض constructor.
    الثانية, أن static factory method قد لا يمكن تمييزها بسهولة عن بقية static methods التي بداخل class,  لذلك تستخدم عادة بعض التسميات المتعارف عليها, لتحل هذه المشكلة.
    الان, لنمثل علىstatic factory method في Android, فلو أردنا أن نقوم بإنشاء activity داخلها fragment سيكون الكود كالتالي
    public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentManager manager = getSupportFragmentManager(); Fragment fragment = manager.findFragmentById(R.id.fragment); if (fragment == null){ fragment = new BlankFragment(); manager.beginTransaction().add(R.id.fragment,fragment).commit(); } } } وفي Activity أخرى
    public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_secound); FragmentManager manager = getSupportFragmentManager(); Fragment fragment = manager.findFragmentById(R.id.fragment); if (fragment == null){ fragment = new BlankFragment(); manager.beginTransaction().add(R.id.fragment,fragment).commit(); } } } لنقوم الان بتحسين هذا الكود, سنقوم بالتالي, أولا بناء static factory method داخل fragment
    public static BlankFragment newInstance() { BlankFragment fragment = new BlankFragment(); return fragment; } ثم نقوم ببناء BaseActivity كالتالي
    public abstract class BaseActivity extends AppCompatActivity { protected abstract Fragment createFragment(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity); FragmentManager manager = getSupportFragmentManager(); Fragment fragment = manager.findFragmentById(R.id.fragment); if (fragment == null){ fragment = createFragment(); manager.beginTransaction() .add(R.id.fragment,fragment) .commit(); } } } لاحظ هنا أن هناك دالة ستعيد لنا fragment سنستخدمها داخل  oncreate, وستظهر فائدة هذا الشيء عندما نجعل MainActivityb و SecoundActivity ترث منها, فيكون شكل الكود  كالتالي
    public class SecondActivity extends BaseActivity { @Override protected Fragment createFragment() { return BlankFragment.newInstance(); } } public class MainActivity extends BaseActivity { @Override protected Fragment createFragment() { return BlankFragment.newInstance(); } } إلى هنا أتمنى أن أكون وفقت في تبسيط هذا المفهوم,
    والسلام عليكم ورحمة الله وبركاته.المصادر:
    Big nerd ranch Android
    Effective java
    Static factory methods vs traditional constructors
    مستوى المقال: محترف
  2. شرح الـ Interface في جافا
     
    ما هو الـ interface؟
    الـ interface يشبه كثيرا الـ abstract class في أنه يحدد خصائص مشتركة للكائنات (objects) في كلاسات لها علاقةوراثية ببعضها (Inheratance) بالإضافة إلى أنه يحدد يحدد خصائص مشتركة للكائنات (objects) في كلاسات ليس بالضرورة  أن يكون لها علاقة ببعضها وهو ما يميز الـ Interface.
    لم تضح الصورة لك بعد؟ لا بأس سأشرح لك بمثال
    لو كان عندي Abstract class اسميته Fruits وهو (parent class (super class لمجموعة من الفواكه هي الموز والبرتقال (child classes) وأنشأت Abstract class آخر أسميته Animals  وهو (parent class (super class لمجموعة من الحيوانات الدجاجة والأسد (child classes)، ثم أنشأت Interface أسميته Eddible (قابل للأكل).
    لاحظ أن الموز والبرتقال بإمكاننا أن نقول أنها فواكه لأن العلاقة هنا وراثية (Inheratance) فأي موزة هي فاكهة وأي برتقال هو فاكهة، وأيضا بإمكاننا أن نقول أن الموز والبرتقال قابلان للأكل.
    والشئ نفسه ينطبق على الدجاجة والأسد في كونهما حيوانات لأن العلاقة وراثية فأي دجاجة هي حيوان وأي أسد هو حيوان،وأيضا بإمكاننا أن نقول أن الدجاجة قابلة للأكل لكن لا يمكننا القول بأن الأسد قابل للأكل فهنا الـEdible interface سيصلح فقط للدجاجة دون الأسد.
    إن ما أردت توضيحه هو أن الفواكه والحيوانات ليس لها رابطة واضحة أو خصائص مشتركة لكن الـ Interface أوجد خاصية مشتركة بينها وهي قابلية الأكل وهذا ما يميز الـInterface عن الـabstract class.
     
    لماذا نستخدم الـ interface؟
    ببساطة لأن Java لايدعم Multiple Inheratance (الوراثة المتعددة)، وفي أغلب الأحيان نحتاج لأكثر من كلاس لنأخذ منه خصائص مشتركة فالحل هو الـInterface.
    *ملاحظة: بإمكان الكلاس أن يكون له علاقة وراثية واحدة فقط أي أن يكون له Super classs واحد فقط، بينما بإمكانه أن يكون متعدد الـInterfaces وتسمى هذه العلاقة Interface Inheratance.
     
    كيف ننشئ الـ interface؟
    الصيغة العامة للـInterface هي:

    مثال:

     
    كيف نستخدم الـ interface؟
    ليستخدم الكلاس الـInterface المطلوب نستخدم كلمة implements بعد اسم الكلاس وقبل اسم الـ Ineterface كما هو موضح في المثال.
    وبطبيعة الحال بما أن في الـInterface يوجد Abstarct Method فيجب علينا أن ننفذ Implementation للميثود في الكلاس الذي استدعى الـInterface وإلا ستبقى الميثود abstract وسيتحول الكلاس إلى abstract class.
    مثال:

    main class:

    Output:

     
     
    *المصادر:
    كتاب  Introduction to Java programming, Tenth Edition, Y. Daniel Liang.
    مستوى المقال: مبتدئ

  3.  
    بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
     
    في هذا الموضوع، سنستعرض الStreams، وهي عبارة عن API جديدة ورائعه تم اضافتها في التحديث الأخير للJava 8.
    باستخدام الStreams، ستستطيع معالجة بيانات الCollections كأنك تقوم بعمل Query في احد الSQL databases، وذلك بطريقة تعريفية بسيطة دون الحاجة لكتابة Loop في كل مرة تريد معالجة البيانات لتخرج بنتيجة معينة (جمع عناصر الArrayList على سبيل المثال)، وذلك بكتابة سطر برمجي واحد فقط!
    هناك ميزة أخرى أيضا للStreams، وهي امكانية تفعيل جميع أنوية المعالج لتسريع عملية تنفيذ البرنامج دون الحاجة الى كتابة سطر واحد من كلاس الThreads المزعج!
     
    ما هو الStream؟                                             
    سنذكر تاليا أهم سمات الStream في الجافا:
    تسلسل عناصر: الStream هو عبارة عن تسلسل لعناصر يتم استخلاصها من أحد المصادر (Sources) -قد تكون Array أو ArrayList الخ-، حيث يقوم الStream بـ قراءة/معالجة بيانات هذه المصادر عند الحاجة فقط المصادر: قد تكون Collection, Arrays, I/O العمليات: يدعم الStream مجموعة من العمليات (أو methods) على سبيل المثال لا الحصر: filter, map, limit, reduce, find, match تكرارات تلقائية: الStreams تدعم التكرارات التلقائية (Automatic Iterations)، أي كما قلنا سابقا، لن تكتب المزيد من الloops، كل ماعليك فعله هو كتابة سطر واحد باستعمال الStreams والجافا ستقوم بالباقي  
    إنشاء الStream                                               
    في الجافا 8، هناك طريقتان لإنشاء Stream:
    ()stream: ستنشئ ستريم تسلسلي مربوط بcollection، ولكن بدون الاستفادة من ميزة تعدد أنوية المعالج في التنفيذ ()parallelStream: ستنشئ ستريم متوازي مربوط بcollection، مستفيدًا من ميزة تعدد أنوية المعالج في التنفيذ مثال:
    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());  
    أهم ميثودز الStream                                         
    ()forEach:
    هذه الميثود تعطيك امكانية المرور بجميع عناصر الستريم للقيام بعملية معينة، في المثال التالي سنقوم بطباعة 10 ارقام عشوائية باستخدام forEach:
    Random random = new Random(); random.ints().limit(10).forEach(System.out::println); ()map:
    بهذه الميثود تستخدم لربط كل عنصر بالستريم مع نتيجة خاصة به. في المثال التالي سنقوم بطباعة مربعات ارقام مميزة باستخدام map:
    List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of unique squares List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); ()filter:
    يتم استخدام هذه الميثود للتخلص من بعض عناصر الستريم بناء على شروط معينة، المثال التالي يقوم بطباعة عدد ال Strings الفارغة:
    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.stream().filter(string -> string.isEmpty()).count(); ()limit:
    هذه الميثود تستخدم للحد من حجم الستريم بدون أي شروط، في المثال التالي سنقوم بطباعة 10 ارقام عشوائية باستخدام  limit:
    Random random = new Random(); random.ints().limit(10).forEach(System.out::println);  ()sorted:
    يتم استخدام هذه الميثود لترتيب الستريم، الكود التالي يظهر كيف تقوم بطباعة 10 ارقام عشوائية مرتبة:
    Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);  ( لاحظ كيف أنجزنا المهمة بسطر واحد فقط، تخيل لو أردت أن تقوم بطباعة 10 ارقام عشوائية مرتبة بالطريقة التقليدية! )
     
    Parallel Processing:                                        
    هذه هي الطريقة الثانية لإنشاء الستريم الموازي (استعمال جميع أنوية المعالج لتنفيذ البرنامج) كما هو مذكور بالأعلى:
    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.parallelStream().filter(string -> string.isEmpty()).count(); لاحظ أنك تستطيع التبديل بين الStream والparallelStream بسهولة تامة.
     
    Collectors:                                                       
    نستخدم الCollectors لجمع نتائج معالجة بيانات الستريم واعادتها على شكل List.
    List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered List: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString);  
     
    في المثال التالي، سنقوم بعمل مقارنة بين الJava 7 والJava 8 في برنامج يقوم بضم الStrings غير الفارغة. import java.util.*; public class Java8StreamTest { public static void main(String[] args) { // Java 7 approach System.out.println("Using Java 7: "); List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); System.out.println("List: " +strings); StringBuilder stringBuilder = new StringBuilder(); for (String string: strings) { if (!string.isEmpty()) { stringBuilder.append(string); stringBuilder.append(", "); } } String mergedString = stringBuilder.toString(); System.out.println("Merged String: " + mergedString); // Java 8 approach System.out.println("Using Java 8: "); System.out.println("List: " +strings); mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString); } }  
     
    وهنا نصل الى ختام موضوعنا، أسأل الله لي ولكم التوفيق والسداد.
    مستوى المقال: محترف
  4. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته،
    سنتحدث في هذا الموضوع عن مفهوم الAbstract عامة وبالتحديد في لغة الJava، وكيفية استخدامه وتطبيقه مع امثلة توضيحية
     
    ماهو الAbstraction؟
    اذا بحثنا في القاموس عن معنى كلمة Abstract (تجريد)، فسنجد انها تعني [ خاصية التعامل مع الفكرة لا الحدث ]. بمعنى اهمال التفاصيل الغير لازمة واستبدالها بما هو مهم وواضح.
    مثال على ذلك: عندما تحاول ان ترسل ايميل الى شخص ما، فانك لن تهتم بالتفاصيل الصغيرة مثل مالذي يحدث بالضبط عندما تضغط على زر ارسال او البروتوكول المستخدم لنقل الرسالة. كل ما تريد عمله هو ان تكتب عنوان الرسالة والمحتوى ومستقبل الرسالة وترسلها. 
    نفس الشيء ينطبق في مفاهيم ال Object-Oriented. في الabstraction نهدف الى اخفاء تفاصيل الimplementation عن المستخدم، بمعنى اخر، المستخدم سيهتم بما الغرض من الobject بدلا عن كيفية قيامه به.
    في الجافا، يمكننا تطبيق هذا المفهوم عن طريق انشاء abstract class او abstract interface، (عكسها concrete class او normal class)
     
    Abstract Classes
    الكلاس الذي يحتوي على كلمة abstract في تعريفه يعتبر abstract class، وسيتبع القوانين التالية:
    من الممكن للAbstract class أن يحتوي على abstract methods (ليس اجباريا)، وهي الميثودز التي لا تحتوي على تعريف مثل ( ;()public abstract void get ) ولكن، اذا احتوى الكلاس على abstract method، فيجب تعريفه ك abstract class اذا تم تعريف الكلاس ك abstract، فلا يمكن انشاء objects منه لتستخدم ال abstract class وخصائصه، يجب عليك ان ترثه (inherit it) من كلاس آخر، ويجب عليك اعادة تعريف كل ال abstract methods مثال:
    سننشئ abstract class باضافة الكلمة abstract الى تعريف الكلاس:
    public abstract class Employee { private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public double computePay() { System.out.println("Inside Employee computePay"); return 0.0; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address); } public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; } } لاحظ ان الabstract class السابق لا يختلف ابدا عن الكلاس العادي، فهو يحتوي على attributes, constructor, normal methods. الفرق الوحيد هو كلمة abstract بالتعريف
    الآن لنحاول انشاء اوبجكت من الكلاس السابق:
    public class AbstractDemo { public static void main(String [] args) { Employee e = new Employee("George W.", "Houston, TX", 43); e.computePay(); } } عند تشغيل البرنامج سنحصل على الخطأ التالي:
    Employee.java:46: Employee is abstract; cannot be instantiated Employee e = new Employee("George W.", "Houston, TX", 43); ^ 1 error لأنه لا يمكن انشاء اوبجكت من abstract class حتى وان احتوى على constructor.
     
    Inheriting Abstract Classes
    نستطيع اعادة استخدام خصائص وميثودز الabstract class تماما كأي كلاس آخر عن طريق وراثته (extends):
    public class Salary extends Employee { private double salary; // Annual salary public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } } هنا لا يمكننا انشاء اوبجكت من كلاس Employee، ولكن يمكننا انشاء اوبجكت من كلاس Salary واستخدام جميع خصائص وميثودز كلاس Employee:
    public class AbstractDemo { public static void main(String [] args) { Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00); Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); System.out.println("Call mailCheck using Salary reference --"); s.mailCheck(); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); } } والOutput سيكون كالتالي:
    Constructing an Employee Constructing an Employee Call mailCheck using Salary reference -- Within mailCheck of Salary class Mailing check to Mohd Mohtashim with salary 3600.0 Call mailCheck using Employee reference-- Within mailCheck of Salary class Mailing check to John Adams with salary 2400.0  
    Abstract Methods
    اذا اردت انشاء ميثود ولكنك تريد تعريفها بالكلاس الإبن (Inheriting class)، يمكنك استخدام كلمة abstract في تعريف الميثود، مثال:
    public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); } تعريف الميثود (مثل ()computePay) ك abstract method له آثار يجب الانتباه لها:
    الكلاس الذي يحتويها يجب أن يكون abstract الكلاس الذي يرث الكلاس الذي يحتويها يجب أن يعيد تعريفها مثال، كلاس Salary سيرث كلاس Employee السابق:
    public class Salary extends Employee { private double salary; // Annual salary public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } } نلاحظ أن الميثود ()computePay تمت اعادة تعريفها لتحصل على implementation جديد خاص بكلاس Salary
     
    هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.
    مستوى المقال: مبتدئ
  5. السلام عليكم ورحمة الله وبركاته،
    هذا الدرس البسيط سيشرح باذن الله مفهوم الOverloading وطريقة تطبيقه على لغة الJava 
    ماهو الOverloading؟
    هي ميزة تقدمها العديد من لغات البرمجة، تتيح للمبرمج كتابة اثنين او اكثر من الmethods المتكررة (تحمل نفس الاسم) ولكن تختلف بخصائصها.
     
    كيف نفرق بين هذه الmethods المتشابهة؟
    صحيح ان الOverloaded methods تتشابه في الاسم، ولكنها يجب أن تختلف في أحد أو كل ما يلي:
    عدد الParameters  نوع الParameters ترتيب الParameters  
    أمثلة للMethod overloading:
    كما ذكرنا بالأعلى، فإن الOverloaded methods يجب ان تختلف في الArgument list
    وسنرى الآن مثال لكل حالة ممكنة للOverloading.
    مثال 1: اختلاف عدد الParameters
    class DisplayOverloading { public void disp(char c) { System.out.println(c); } public void disp(char c, int num) { System.out.println(c + " "+num); } } class Sample { public static void main(String args[]) { DisplayOverloading obj = new DisplayOverloading(); obj.disp('a'); obj.disp('a',10); } } Output:
    a a 10 في المثال السابق، قمنا بكتابة الميثود ()disp مرتين، مرة باستخدام Parameter واحد ومرة باستخدام اثنين.
    نلاحظ ان الcompiler ذكي كفاية ليربط لنا كل استدعاء بالميثود المناسبة له حسب الArgument list المستخدمة.
     
    مثال 2: اختلاف نوع الParameters
    class DisplayOverloading2 { public void disp(char c) { System.out.println(c); } public void disp(int c) { System.out.println(c ); } } class Sample2 { public static void main(String args[]) { DisplayOverloading2 obj = new DisplayOverloading2(); obj.disp('a'); obj.disp(5); } } Output:
    a 5 كما المثال السابق، نلاحظ هنا ان الميثود ()disp كتبت مرتين، مرة مع Parameter من نوع char ومرة من نوع int.
     
    مثال 3: اختلاف ترتيب الParameters
    في هذا المثال، قمنا بتغيير ترتيب الParameters لكتابة اكثر من نسخة من الميثود ()disp، في المرة الأولى كانت تحتوي على (char, int) وفي الثانية اصبحت (int, char).
    class DisplayOverloading3 { public void disp(char c, int num) { System.out.println("I’m the first definition of method disp"); } public void disp(int num, char c) { System.out.println("I’m the second definition of method disp" ); } } class Sample3 { public static void main(String args[]) { DisplayOverloading3 obj = new DisplayOverloading3(); obj.disp('x', 51 ); obj.disp(52, 'y'); } } Output:
    I’m the first definition of method disp I’m the second definition of method disp  
     
    لنرى امثلة على طرق overload خاطئة:
    الحالة 1:
    int mymethod(int a, int b, float c) int mymethod(int var1, int var2, float var3) النتيجة: خطأ في الCompilation، كلا الميثودين يحملان نفس عدد ونوع وترتيب الParameters.
     
    الحالة 2:
    int mymethod(int a, int b) float mymethod(int var1, int var2) النتيجة: خطأ في الCompilation، اختلاف الreturn type للميثودين لا يهم في الoverloading.
     
    هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.
    مستوى المقال: مبتدئ
  6. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
     
    استأنافا لما بدأنا عنه حول مواضيع هياكل البيانات سنتقطرق اليوم على نوع من أنواع الـ Methods واللتي لها علاقة
    بما يليها من مواضيع حول هياكل البيانات، كما ولها طبيقات رياضية كثيرة، والتي سنذكر منه ها هنا.
     
    ماذا نعني بـ Recursion ؟
    المعنى الحرفي لكلمة Recursion  هو الإستدعاء الذاتي وهذا المعنى لوحده يكفي لتعريفها، فبكل بساطة هو نوع من
    أنواع الـMethods والتي تقوم بنداء نفسها، ولهذه Method هيكلة وأساسيات لابد من توافرها في هذه Method.
     
    الشكل العام للـRecursion Methods:
    public void Test1(int i){ //أي عدد من اسطر الأكواد if(){//الحالة الأساسية والتي تقوم بإنهاء النداء الذاتي } Test1(/*any Value To pass*/);//النداء الذاتي //أي عدد من أسطر الأكواد } الأمر المهم الذي يجب عدم نسيانه هو الحالة الأساسية وهي عبارة عن شرط هذا الشرط
    يجعل لنداء الميثود لنفسها نهاية فليس من المعقول أن نقوم بنداء إلى مالنهاية. وهذا الشرط
    شبيه بالشرط الذي نضعه لإنها loop. وعند نسيان هذا الشرط سوف نواجه نداء لا نهائي من ثم انهيار التطبيق.
     
    لفهم معنى Recursion أفضل سوف نقفز مباشرة الى عدد من الأمثلة:
     
    ١. مضروب العدد Factorial (س!):
    ونعني به هنا هو مجموع حاصل ضرب جميع الأرقام من 1 الى العدد س.
    ويمكننا حل هذه العملية الحسابية بكل بساطة باستخدام التالي:
    public int Factorial (int i){ if(i == 0){ return 1; } else { return i * Factorial (i-1); } } هذه الميثود تأخذ عدد من نوع int وتقوم بإرجاع عدد من نوع int كذلك.
    أولا علينا تحديد الحالة الأساسية وفي هذه الحالة ستكون عندما يكون المضروب 0 فإن الناتج هو 1، 
    أي عندما نرسل للميثود 0 فإنها تعطينا الناتج 1.
    في حال لم نقم بإرسال 0 الى الميثود فإنها ستذهب للخيار الآخر وهو نداء الميثود لنفسها لكن هذا النداء
    يحتوي على بعض الأمور التي يجب أخذها بعين الاعتبار، اولها بأننا قمنا بتحديث قيمة i فقمنا بإنقاصها 1؛
    وهذا التحديث مهم حيث أنه في حال نسيانه سنواجه نداء لانهائي. الأمر الآخر بأننا قمنا بضرب العدد الحالي بسابقه.
     
    لنفرض بأننا قمنا بنداء هذه الميثود كالتالي:
    System.out.println(Factorial(4)); في النداء الأول بما أن 4 لا تساوي 0 فإننا سنقوم بالخطوة الثانية:
    4 * Factorial(4-1) وهذا يرسلنا الى النداء الثاني، ومن هذا النداء يتولد لنا:
    3 * Factorial(3-1) وندخل بعدها للنداء الثالث:
    2 * Factorial(2-1) ومنه للنداء الرابع:
    1 * Factorial(1-1) في النداء الخامس قيمة i تساوي 0 وهذا يحقق شرطنا فعندها سنقوم
    بإعادة 1 الى آخر نداء لنا أي أننا سنقوم بالتالي وليكن في البال بأننا في حال
    قمنا بأكثر من لنداء لنفس الميثود فإنا النداءات سوف تترب في stack أي أن
    آخر نداء سوف يحصل على الإجابة قبل غيره. وهذا ينتج لنا التالي:

    ٢. المجموع للعدد س:
    كما فعلنا في مثالنا السابق سنقوم هاهنا باستدعاء متكرر لنفس الميثود والتي ستقوم بدورها بجمع الأعداد من 0 إلى س.
    public int SUM(int i){ if(i == 0){ return 0; } else{ return i + SUM(i -1); } }  
    ٣. طباعة الأعداد:
    هنا المستخدم يرسل رقم (س) ونقوم بطباعة الأرقام من س الى 1 بشكل تنازلي :
    public void printInt(int i){ if(i == 1){ System.out.println(1); }else{ System.out.println(i); printInt(i-1); } } أما في حال أردنا الطباعة بشكل تصاعدي فكل ما علينا فعله هو عكس آخر سطري كود لينتج لدينا:
    public void printInt(int i){ if(i == 1){ System.out.println(1); }else{ printInt(i-1); System.out.println(i); } } ملاحظة: نداء الميثود لنفسها لا يقتصر على الأرقام فحسب (كما سنرى في المواضيع القادمة بإذن الله) بل إنه أوسع من ذلك؛ لكن لتبسيط الأمور استعنت بمجموعة
    من الأمثلة تحتوي على أرقام فهي أبسط للفهم، كذلك في حال الملاحظة فإن نداء الميثود لنفسها شبيه بالـ loop الى حد بعيد.
     
     
    اتمنى من الله أني وفقت لإصال المعلومة
    في حفظ الله
    مستوى المقال: مبتدئ
  7. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
    سنتطرق في هذا الموضوع للGenerics (الميثودز العامة)، مقدمة عن ماهي، ما فائدتها، وكيفية استخدامها بالجافا.
     
    مقدمة                                                                                   
    في أي مشروع او برنامج تعمل عليه بالجافا، ستواجه مشاكل في الcompiling وستواجه الكثير من الexceptions. لذلك من مهام المسؤولين عن لغة الجافا أن يساعدوا المطورين في مواجهة هذه الأخطاء والتقليل منها بقدر المستطاع.
    أحد أهم ما قدم في تحديث الJava 1.5 كان هو الGenerics. طريقة جديدة لتجنب مشاكل قد تواجهك في تطويرك لمشروعك.
     
    فائدتها                                                                                  
    ماهي هذه المشاكل التي قد تواجهك؟ 
    أكبر مشكلة أتت هذه الGenerics لحلها هي الأنواع المستخدمة في المجموعات (Collections)، كالArrayList, LinkedLists الخ..
    المشكلة تكمن (ما قبل Java 1.5) في النوع المستخدم لعناصر الCollection غير قابل للتحديد من قبل الكلاس، لذلك عندما يأتي المستخدم وينشئ اوبجكت من هذا الكلاس ويستخدم الميثودز الخاصة به، قد يستخدم cast خاطئ لعنصر في collection معينة، فمثلا قد يعمل كاست لعنصر (Integer) ك(String)
    مثلا:
    static void expurgate(Collection c) { for (Iterator i = c.iterator(); i.hasNext(); ) if (((String) i.next()).length() == 4) i.remove(); } في المثال السابق، الميثود expurgate ستفترض دائما أن العناصر المقروءة من المجموعة c هي Strings. بالتالي في حالة أن اخطأ المستخدم بادخال مجموعة تحتوي على عناصر من نوع آخر سنواجه Casting exceptions.
    سنعدل المثال السابق باستخدام الgenerics لنرى كيف نتفادى مشاكل الcasting:
    static void expurgate(Collection<String> c) { for (Iterator<String> i = c.iterator(); i.hasNext(); ) if (i.next().length() == 4) i.remove(); } لاحظ تحديد نوع العناصر في الانبوت لتكون من نوع String، ولاحظ أيضا عدم الحاجة للCast داخل اللوب، وبذلك نلغي احتمالية حدوث Cast exceptions.
    سنتحدث عن الSyntax وأنواع الجينات لاحقا.
    لكن لنخلص أهم فوائد الGenerics أولا:
    مساعدة الCompiler في تحديد الأخطاء وقت الCompilation التخلص من الCasts  مساعدة المطورين على كتابة ميثودز عامة، وعدم الحاجة لكتابة أكثر من ميثود لاستقبال أكثر من نوع من الparameters.  
    طريقة استخدامها                                                                
    لاشك أنك لاحظت أن الGenerics تستعمل نوع خاص من الأقواس <> (الدايموند)، هذا صحيح. يجب استعمال هذه الأقواس عند الرغبة باستخدام الGenerics في كتابة الكلاسات وعند الرغبة بانشاء Objects منها.
    لنأخذ مثال كلاس الArrayList الموجود في مكاتب الجافا الافتراضية، مكتوب بالشكل التالي:
    public class ArrayList<E> implements List<E> .... { // Constructor public ArraList() { ...... } // Public methods public boolean add(E e) { ...... } public void add(int index, E element) { ...... } public boolean addAll(int index, Collection<? extends E> c) public abstract E get(int index) { ...... } public E remove(int index) ....... } نلاحظ استخدام الGeneric من نوع <E> للاستغناء عن تخصيص نوع معين لعناصر الArrayList وترك الخيار للمستخدم.
    لإنشاء اوبجكت ArrayList:
    ArrayList<Integer> lst1 = new ArrayList<Integer>(); // E substituted with Integer lst1.add(0, new Integer(88)); lst1.get(0); ArrayList<String> lst2 = new ArrayList<String>(); // E substituted with String lst2.add(0, "Hello"); lst2.get(0); قمنا هنا بانشاء اوبجكتين من الArrayList الأول بعناصر من نوع Integer والثاني بعناصر من نوع String، وذلك باستخدام الكلاس والميثودز نفسها.
    إذا اردت انشاء كلاس خاص فيك وربط الاوبجكت بنوع عام (وترك التخصيص للمستخدم) يمكنك عمل التالي:
    public class GenericBox<E> { // Private variable private E content; // Constructor public GenericBox(E content) { this.content = content; } public E getContent() { return content; } public void setContent(E content) { this.content = content; } public String toString() { return content + " (" + content.getClass() + ")"; } } نلاحظ مرة أخرى استخدام الGeneric من نوع <E> للاستغناء عن تخصيص نوع معين وترك الخيار للمستخدم.
    لاحظ في ميثود الtoString() قمنا باستدعاء الكلاس الخاص بالGeneric (أيا كان) لطباعته.
    لإنشاء أوبجكت من الكلاس السابق:
    public class TestGenericBox { public static void main(String[] args) { GenericBox<String> box1 = new GenericBox<String>("Hello"); String str = box1.getContent(); System.out.println(box1); GenericBox<Integer> box2 = new GenericBox<Integer>(123); // autobox int to Integer int i = box2.getContent(); System.out.println(box2); GenericBox<Double> box3 = new GenericBox<Double>(55.66); // autobox double to Double double d = box3.getContent(); System.out.println(box3); } } قمنا بالكود السابق انشاء 3 اوبجكتات من الكلاس GenericBox بانواع مختلفة، وأيضا باستخدام الكلاس والمثودز نفسها .
     
    أنواعها                                                                                  
    للGenerics أنواع عديدة أهمها:
    <Element - <E تستخدم كثيرا في مكتبات الجافا الافتراضية <Type - <T مقاربة للنوع الأول وأكثر الأنواع استخداما من قبل المطورين <Key & Value - <K, V للأنواع المتعددة (مفتاح وقيمة) ...  
    مثال على استخدام Generic الأنواع المتعددة:
    public interface Pair<K, V> { public K getKey(); public V getValue(); } public class OrderedPair<K, V> implements Pair<K, V> { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } } ولإنشاء اوبجكت من الPair class:
    Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8); Pair<String, String> p2 = new OrderedPair<String, String>("hello", "world");  
    اختصار يمكن الإستغناء عن تحديد انواع العناصر عند استدعاء الConstructor والاكتفاء بتحديدها عند التعريف، حيث يمكن للCompiler ان يربطهما.
    OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8); OrderedPair<String, String> p2 = new OrderedPair<>("hello", "world");  
    المراجع                                                                                  
     Oracle : The Java™ Tutorials: Generics (Updated)s
    ntu : Java Programming Tutorial: Generics
     
    مستوى المقال: محترف
  8. بسم الله الرحمن الرحيم 
    السلام عليكم ورحمة الله وبركاته
     
    ستحتاج إلى قراءة الموضوع السابق الخاص بـالـ Hashing Algorithm لكي تستطيع المتابعة من خلال الرابط التالي هنا
     
    Hashing
    سنتعرف معاً في هذا المقال على :
    -          طريقة الـ Open Addressing.
    -          طريقة التطبيق في لغة برمجة Java.
     
    تكلمنا في المقالة السابقة عن الـ Hashing Algorthim وكيف يمكننا حل مشكلة تكرار الـ Data وتم مناقشة فكرة واحدة وهي الـ Separate Chaining .
    وللتذكير فإن طريقة الـ Separate Chaining هي طريقة تعتمد على بناء ArrayList بشكل خاص أو أي Structure آخر بشكل عام داخل كل خلية في الـ Hash Table. ومن ثم يتم تخزين القيم اللي تمتلك نفس قيمة الـ Index في هذا الـ Structure. ولكن !!! 
    طريقة الـ Separate Chaining لها العديد من الميزات والعيوب مثل :
    الميزات :
    1 - مطلق الحرية في استخدام الـ Structure الذي يناسبك سواء كان Tree أو ArrayList على سبيل المثال. 
    2 - سهولة تطبيق فكرة الـ Separate Chaining داخل أي لغة برمجة.
    العيوب : 
    1 - ماذا لو أدخل المستخدم 10 أرقام على سبيل المثال والتي تملك نفس الـ Index. فـ على سبيل المثال لنقل بأننا نريد ملئ HashTable بحجم خليتين بالأرقام التالية : 2-4-6-8-10-12. عند تطبيق الدالة Index = number % arrayLength سنجد بأن كل الأرقام ستوضع في خانة 0 في الجدول كما في الصورة التالية : 

     
    ولكن لحظة !! الـ ArrayList الموجودة بالصورة هي عبارة عن Array عادية موضوعة داخل Index 0 والفكرة الاساسية من الـ Hashing لم يتم تطبيقها للأسف لأننا في حال أردنا البحث عن رقم 12 مثلاً سنضطر للبحث داخل كل الـ Array داخل Index 0. تخيل بأنك أضفت أكثر من الف Record وجميع هذه الـ Records تمتلك نفس الـ Index ستستغرق نفس الفترة الزمنية المستغرقة في حال إضافة هذه الـ Records في Array عادية بدون التطرق لفكرة الـ Hashing. 
    لذلك نستطيع القول بأن فكرة الـ Separate Chaining ليست ممتازة في جميع الأحوال. فما الحل ؟
    الحل يتمثل في الطريقة الثانية وهي Open Addressing.
     
    الطريقة الثانية : Open Addressing.
    ميزة هذه الطريقة بأن كل الـ Records سيتم توزيعها على كل الخانات الفارغة داخل الـ Table. وفكرتها تعتمد على إضافة رقم معين يتم نقل الـ Record المتكرر إلى خلية ثانية بمقدار هذا الرقم. هذا الرقم يعتمد على عدة دوال وهي :
    1 - Linear probing وهذه الطريقة التي سنناقشها في هذه المقالة.
    2 - Quadratic probing وهي زيادة بمقدار مربع i كل مرة. بحيث i = 0 , 1 , 2 , etc بالشكل التالي i^2 +/- . بمعنى آخر سنقوم في البداية بالتحرك بمقدار i إلى اليمين ومن ثم بمقدار i إلى اليسار. 
    3 - Double hashing وهي زيادة بحسب دالة أخرى.
    Linear probing أو زيادة خطية بمعنى زيادة عدد معين تختاره أنت من البداية يطلق عليه i على كل Record متكرر. لكي تتوضح الصورة لنأخذ المثال التالي: 
    نريد إضافة هذه الأرقام 5 - 10 - 21 - 31 إلى جدول مكون من 5 خانات. ونريد تحديد الـ i لكي تكون 1 في حالة التكرار. سيكون المخرج النهائي كالتالي :
    1 - عند إضافة 5 .. لن يكون هناك أي مشاكل لأن الجدول يفتقر لوجود أي Data وسيتم وضعه في Index 0.
    2 - عند إضافة 10 .. سنلاحظ وجود 5 في خانة Index 0 ولذلك لا يمكننا وضع 10 أيضاً فنقوم بزيادة الـ Index بـ قيمة i المختارة سابقاً وهي 1 فيصبح الـ Index هو Index 1. 
    3 - عند إضافة 21 .. يجب علينا إضافتها إلى Index 1 ولكنه ممتلئ بالقيمة 10 .. فنقوم بالزيادة بـ 1 ونقوم بوضعها بخانة Index 2.
    4 - عند إضافة 31 .. يجب علينا إضافتها إلى Index 1 ولكنه ممتلئ بالقيمة 10 .. نقوم بزيادة 1 ونضيف 31 إلى Index 2 ولكنه ممتلئ أيضاً بالقيمة 21 فنقوم بزيادة 1 مرة أخرى ونضع 31 في Index 3. 
    المخرج النهائي :
     
     
    ولكن طريقة الـ Open Addressing فتحت لنا الباب لظهور مشكلة جديدة وهي مشكلة الحذف. ماذا لو أردنا في المثال السابق حذف الرقم 21. ومن ثم نريد إيجاد الرقم 31. سنقوم بالبحث بداية داخل Index 1 ولكننا سنجد 10 فـ سننتقل إلى Index 2 لنفاجئ بأن القيمة هي Null لأننا سبق وحذفنا الرقم 21. وهذا خطأ .. لأننا اتفقنا في البداية بأن الـ Index إذا كان Null "فارغ" يجب علينا ملء هذا الـ Index قبل الانتقال إلى Index جديد. ستخبرني بأنه من الممكن إكمال البحث حتى العودة للـ Index الذي بدأنا عنده للتأكد بأن 31 غير موجودة ولكن ماذا لو كان 31 غير موجود فعلاً و Index 2 فارغ بسبب إنه لم يتم إضافة 31 بعد .. في هذه الحالة ستقوم بتضييع الكثير من الوقت رغم علمك المسبق بأن 31 غير موجود. تبدو الفكرة محيرة فعلاً فما الحل؟ الحل يتمثل بإضافة " حالة " أو Status إلى الجدول الموجود في المثال السابق. سنقوم بتغيير حالة الـ 21 في حالة الحذف إلى D دلالة إلى Deleted بدون حذفها بشكل نهائي. في هذه الحالة لن يتعطل البحث أو يتوقف وستحل المشكلة. 
    في البداية ستكون الـ Status الخاصة بكل الخلايا E دلالة إلى Empty او فارغ. إذا تم وضع عنصر جديد داخلها سيتم تغيير حالتها إلى O دلالة إلى Occupied او ممتلئ.
    الآن في حالة البحث عن 31 بعد حذف 21. سنقوم بالذهاب إلى Index 1 لنجد 10 فننتقل إلى Index 2 لنجد 21 فننتقل إلى Index 3 فنجد 31. 
    ماذا لو أردنا البحث عن 21 بعد حذفها ؟ لا يمكنك عمل return true في حالة البحث إلا في حالة واحدة فقط إذا كان القيمة الموجودة في الخلية = القيمة المبحوث عنها + الحالة أو الـ Status = O. لو كانت D كما في مثالنا يجب علينا عمل return false.
     
    - التطبيق بلغة Java.
     
    سنتحتاج إلى عمل 3 كلاسات. الكلاس الأول Cell والكلاس الثاني HashTable والثالث عبارة عن TestClass.
     
    كلاس Cell : الخلية هنا تتكون من القيمة وحالتها كما أسلفنا سابقاً بالإضافة إلى بعض الـ Methods المهمة.
    public class Cell { Object dataObject ; // value String status ; // status E for empty, D for deleted, or O for occupied public Cell(){ status = "E"; // default value for a null cell } public Cell(Object obj){ status = "O"; dataObject = obj ; } public String toString(){ return "Object : "+dataObject.toString()+"\t\t "+status+"\n" ; } public int getHash(){ // we are going to use hashCode() method that exists in Object class return dataObject.hashCode(); } public void setStatus(String s){ status = s ; } }  
    كلاس HashTable : يتكون من كل ماله علاقة بالجدول المراد إنشائه من Methods. 
    أولا: Instance Variables and Constructors 
    private int size ; private Cell [] list ; public HashTable(){ // default size for empty hash table size = 0 ; } public HashTable(int i){ // creating hash table with a desired value list = new Cell[i]; size = i ; for (int j = 0 ; j<i ; j++) // NullPointerException !! list[j] = new Cell(); }  
    ثانياً : Insert method " إضافة "
    public void insert(Object obj){ Cell tmp = new Cell(obj); int index = obj.hashCode()%size ; if (list[index].status.equals("E") || list[index].status.equals("D")){ // empty or deleted cell list[index] = tmp ; }else{ // status = occupied int counter = 0 ; index++; while(counter <list.length){ if (list[index].status.equals("E")){ // empty cell list[index] = tmp ; list[index].setStatus("O"); break ; } counter++; index = (index+1)%size; } } }  
    ثالثاً : retrieve method " بحث " هذه الميثود تعطيك قيمة الـ Index الموجود فيها العنصر المراد البحث عنه أو -1 إشارة إلى عدم وجوده
    public int retrieve(Object obj){ // get index of obj int index = obj.hashCode()%size ; if (list[index].status.equals("E")) return -1 ; // not found int counter = 0 ; while(counter < list.length){ // till the end of the table if (list[index].status.equals("D") && list[index].dataObject.equals(obj)) return -1 ; if (list[index].status.equals("O") && list[index].dataObject.equals(obj)) return index; index = (index+1)%size; counter++ ; } return -1; // not found }  
    رابعاً : Delete Method " حذف "
    public void delete(Object obj){ int index = retrieve(obj); if (index != -1){ // if found list[index].setStatus("D"); } }  
    خامساً وأخيراً : ميثود الطباعة.
    public String toString(){ String str = ""; System.out.println("Value\tStatus"); for (int i = 0 ; i<list.length ; i++){ if (list[i].dataObject == null){ str = str+" - "; }else str = str+" "+list[i].dataObject.toString(); str = str+"\t "+list[i].status+"\n"; } return str ; }  
     
    كلاس TestClass وسنقوم بعمل التالي :
    سنقوم بعمل جدول مكون من 13 خانة ونقوم بعمل التالي:
    1 - إضافة 18 - 26 - 35 - 9 من " اليمين إلى اليسار "
    2 - البحث عن 15 - 48 " قيم غير موجودة "
    3 - حذف 35
    4 - البحث عن 9 " الخانة الصحيحة 10 " 
    5 - إضافة 64 - 47 " من اليمين إلى اليسار "
    6 - طباعة الجدول 
     
    public class test { public static void main(String [] args){ //create new hashTable HashTable hashTable = new HashTable (13); //insert 18 26 35 9 hashTable.insert(new Integer(18)); hashTable.insert(new Integer(26)); hashTable.insert(new Integer(35)); hashTable.insert(new Integer(9)); // get index of element 15 , 48 System.out.println(hashTable.retrieve(new Integer(15))); // -1 System.out.println(hashTable.retrieve(new Integer(48))); // -1 //delete element 35 " change status to D " ; hashTable.delete(new Integer(35)); // get index of element 9 System.out.println(hashTable.retrieve(new Integer(9))); // 10 //insert 64 47 hashTable.insert(new Integer(64)); hashTable.insert(new Integer(47)); //printing System.out.println(hashTable); } }  
    المخرج النهائي :

    مستوى المقال: محترف
  9. السلام عليكم ورحمة الله وبركاته
    في هذه المقاله سنناقش انواع الInner classes في الجافا
     
    في الجافا، كتابة class داخل class آخر مسموح، الكلاس الداخلي يسمى Nested class والخارجي يسمى Outer class.
    كمثال على الNested class:
    class Outer { class Nested { } }  
    يمكن تقسيم الNested classes الى نوعين:
    Non-static nested classes Static nested classes  

     
    نبدأ أولا بالInner classes
    Inner Classes (Non-static Nested Classes)
    يمكن التفكير ب الInner classes كحماية اضافية للكلاس الداخلي. 
    من المعروف أن الكلاس لا يمكن ربطه باحد الaccess modifiers مثل (public, private, etc...)، ولكن يمكننا فعل ذلك اذا كان Inner class
    للInner classes ثلاثة أنواع:
    Inner classes Method-local inner classes Anonymous inner classes  
    1- Inner classes
    انشاء Inner class بسيط جدا، كل ما عليك فعله هو أن تعرف كلاس بداخل كلاس آخر كما رأينا بالأعلى
    سنعرف Private inner class بالمثال التالي:
    class Outer { int num; // inner class private class Inner { public void print() { System.out.println("This is an inner class"); } } // Accessing he inner class from the method within void display_Inner() { Inner inner = new Inner(); inner.print(); } } public class My_class { public static void main(String args[]) { // Instantiating the outer class Outer outer = new Outer(); // Accessing the display_Inner() method. outer.display_Inner(); } } Output:
    This is an inner class. في هذا المثال استعملنا method اضافية [()display_Inner] لعمل object من الprivate inner class ومن ثم استدعاء الميثود بداخله.
     
    باختصار، الطريقة الصحيحة لعمل Instantiating للInner class كالتالي:
    Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();  
    2- Method-local Inner Classes
    في الجافا، يمكننا أيضا ان نعرف كلاس داخل ميثود معينة، ولكن هذا الكلاس لا يمكن تعريفه أو استخدامه الا داخل نفس الميثود.
    المثال التالي يشرح كيفية استخدام الmethod-local inner class:
    public class Outer { // instance method of the outer class void my_Method() { int num = 23; // method-local inner class class MethodInner { public void print() { System.out.println("This is method inner class "+num); } } // end of inner class // Accessing the inner class within the same scope MethodInner inner = new MethodInner(); inner.print(); } public static void main(String args[]) { Outerclass outer = new Outerclass(); outer.my_Method(); } } Output:
    This is method inner class 23  
    3- Anonymous Inner Class
    هو كلاس يتم انشاؤه بدون اسم محدد له (Anonymous). عموما نستخدم هذا النوع من الكلاسات عندما نريد أن نعمل override لميثود في كلاس او انترفيس.
    مثال لكيفية انشاء Anonymous inner class:
    AnonymousInner an_inner = new AnonymousInner() { public void my_method() { ........ ........ } };  
    البرنامج التالي يوضح استخدام الAnonymous inner class لعمل override لميثود موجودة بabstract class:
    abstract class AnonymousInner { public abstract void mymethod(); } public class Outer_class { public static void main(String args[]) { AnonymousInner inner = new AnonymousInner() { public void mymethod() { System.out.println("This is an example of anonymous inner class"); } }; inner.mymethod(); } } Output:
    This is an example of anonymous inner class  
    4- Static Nested Classes
    عندما نعرف الInner class ك Static، يمكننا أن ننشئ object منه بدون الحاجه لإنشاء object من الouter class
    كذلك الStatic inner class لا يمكنه الوصول او استخدام الinstance variables or methods الموجودة بالouter class
    مثال لهذا النوع من الinner classes:
    class MyOuter { static class Nested { } }  
    البرنامج التالي يوضح الفروقات بين انشاء object من static inner class و inner class:
    public class Outer { static class Nested { public void my_method() { System.out.println("This is my nested class"); } } public static void main(String args[]) { Outer.Nested nested = new Outer.Nested(); nested.my_method(); } } output:
    This is my nested class  
    الى هنا نصل الى ختام موضوعنا.
    وفق الله الحميع لما يحبه ويرضاه.
    مستوى المقال: متوسط
  10. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
     
    Hashing
     
    الكثير من الـ algorithms تستخدم في عملية البحث البسيطة عن Record معين أو Data معينة وسط الآلاف وأحيانا مئات الالاف من الملفات المخزنة في الذاكرة.
    العامل المهم في عملية اختيار الطريقة الممتازة تعتمد على الوقت وفعالية الجهاز المستخدم في عملية البحث ومدى كفائته. وواحدة من أفضل الطرق المستخدمة حالياً هي الـ Hashing .
    سنتعرف معاً في هذا المقال على :
    -          تعريف بسيط عن الـ Hashing.
    -          بعض الطرق المستخدمة في التعامل مع الـ Data في حالة التكرار في طريقة الـ Hashing.
    -          طريقة التطبيق في لغة برمجة Java.
     
    تعريف بسيط عن الـ Hashing:
    هي طريقة تستخدم لحفظ الملفات وتخزينها ومن ثم البحث عنها بأسرع طريقة ممكنة. تتميز هذه الطريقة عن غيرها بأنها قادرة على جلب الـ Data بوقت سريع جدا وسط ملفات ومعلومات كبيرة نوعاً ما مقارنة بغيرها من الطرق.
    هذه الطريقة تتميز بحفظ الـ Data في جدول بحيث يتم إعطاء كل معلومة رقم مميز يتم حفظه داخل جدول من البيانات ومن ثم يتم الوصول إليه مباشرة في حال الحاجة إلى البحث عنه. هذه الطريقة تتميز بقلة الوقت اللازم للقيام بهذه العملية بحيث يمكنك مباشرة معرفة ما إذا كان الملف الجاري البحث عنه موجود أو غير موجود دون الحاجة للبحث عنه داخل الذاكرة بأكملها.
    مثال :
    لنفرض بأن لدينا الأرقام التالية : 1-7-4-8-9-5 .
    إذا قمنا بحفظ هذه الأرقام داخل Array بشكل عشوائي مباشر على سبيل المثال فعند البحث عن رقم 9 ستضطر إلى البحث داخل الـ Array بالكامل لمعرفة ما اذا كان الرقم 9 موجود أو لا. تخيل بأن لديك أكثر من الف رقم او أكثر!! يمكنك تخيل الوقت الطويل الذي ستحتاجه للقيام بعملية البحث هذه.
    لكن باستخدام Hashing يمكننا مثلا تخزين هذه الأرقام داخل Array ولكن ليس بشكل عشوائي كما في السابق وإنما بالنسبة لباقي قسمة العدد على حجم الـ Array على سبيل المثال. لنتفرض بأننا انشأنا Array بحجم 9 خلايا، الصف الأول يوضح الـ index والصف الثاني يوضح العدد الموجود داخل هذا الـ index
    8 7 6 5 4 3 2 1 0 index                   value عند تعبئة هذه الـ Array سنستخدم العلاقة التالية : index = number % arrayLength. بمعنى آخر سيتم وضع الرقم داخل الخانة المعبرة عن باقي قسمة العدد على حجم الـ Array.
    فيكون الجدول بعد التعبئة بهذا الشكل
    8 7 6 5 4 3 2 1 0 index 8 7   5 4     1 9 value لاحظ بأن الرقم 9 وضع بخانة رقم 0 لان باقي قسمة 9 على حجم الـ Array سيعطيك صفر.
    الآن بامكانك مباشرة الذهاب حين البحث عن رقم 9 إلى الرقم المستخرج من الدالة index = number % arrayLength وهو صفر لتعرف ما اذا كان الرقم 9 موجود أو لا وبالتالي توفير الكثير من الوقت.
     
    بعض الطرق المستخدمة في التعامل مع الـ Data في حالة التكرار في طريقة الـ Hashing:
    في المثال السابق لم نصادف أي تكرار في قيمة باقي قسمة الارقام على حجم الـ array ولكن كيف من الممكن حل مشكلة تكرار القيم في حال وقوعها ؟
    هناك الكثير من الحلول التي من الممكن استخدامها لحل هذه المشكلة ولكن سيتم ذكر حل واحد في هذا المقال وسيتم الحديث عن باقي الحلول في مقالات قادمة إن شاء الله.
    1 - Separate Chaining : هذه الطريقة تعتمد على بناء ArrayList بشكل خاص أو أي Structure آخر بشكل عام داخل كل خلية في الـ Hash Table الموضح في الأمثلة السابقة.
    لنأخذ هذه الأعداد على سبيل المثال : 12 – 17 – 29 – 6 – 30 – 31 – 4 – 8 ولنقم بتوزيعها علىHash Table  بحجم 4 خلايا.

     
    في هذه الحالة يتم أولا معرفة الـ index المراد البحث داخله ومن ثم البحث داخل الـ ArrayList لمعرفة ما اذا كان الـ record المراد البحث عنه موجود أو غير موجود.
     
    طريقة التطبيق في لغة برمجة Java:
    هناك الكثير من الطرق لتطبيق فكرة الـ Hashing بواسطة الجافا ولكن سنقوم باتباع الطريقة الأسهل والأقل تعقيداً. سنحتاج إلى إنشاء كلاس List :
    List Class  : عبارة عن كلاس سيتم عمل objects منه  ويحتوي على الـ ArrayList المراد تخزين الـ Data فيها بالإضافة إلى Constructor.
    import java.util.ArrayList; public class List { private ArrayList<Integer> list = new ArrayList<Integer>(); //Constructor public List(){ } public ArrayList<Integer> getList(){ return list ; } }  
    نحتاج أيضاً لإنشاء test class للتأكد من صحة الـ HashTable 
    Test Class : في التيست كلاس سنقوم بإنشاء Array من كلاس List. لاحظ بأنه يجب عليك تعريف كل عناصر هذه الـ Array وبدون هذا التعريف سيظهر لك NullPointerException.
    //hash table List [] hashTable4 = new List [4] ; for (int i = 0 ; i<hashTable4.length ; i++) hashTable4[i] = new List();  
    ميثود print لطباعة الجدول 
    public static void print(List [] array){ for (int i = 0 ; i<array.length ; i++) System.out.println("index "+i+" : "+array[i].getList().toString()); }  
    ميثود getHashCode لمعرفة الـ index المناسب 
    public static int getHashCode(int num){ return num%4 ; }  
    نقوم بتخزين الأرقام في array لتسهيل عملية التصنيف والإدخال ومن ثم نقوم بإدخالها في object hashTable4
    //numbers we want to add int [] listOfNumbers = {12,17,29,30,6,31,4,8}; //add Numbers to the hash table for (int i = 0 ; i<listOfNumbers.length ; i++){ int index = getHashCode(listOfNumbers[i]); hashTable4[index].getList().add(listOfNumbers[i]); }  
    المخرج النهائي 

     
    مستوى المقال: متوسط
  11. السلام عليكم،
    في هذه المقالة سنطلع على مقدمة لأهم ما قدمته الJava في اصدارها الثامن الجديد ألا وهي ال Lambda Expressions.
     
    هذه المقالة ستفترض:
    بأنك على معرفة تامة بالبرمجة عن طريق الجافا في اصداراتها السابقة معرفتك عن مبادئ البرمجة المتعلقة بالObject-Oriented Languages معرفتك لأهم أساسيات الجافا (Inheritance, Polymorphism, Abstraction and Encapsulation) لن تفترض معرفتك اي شيء متعلق بالنسخة الثامنة من جافا  
    - لماذا ال Lambda ؟
    من الصعب علي أن أشرح مدى أهمية وفوائد ال Lambda Expressions، لنفهم أهميتها تماما لابد من فهمها بالأصل، لذلك عليكم أن تثقوا بي في ما سأقوله (سيتضح المعنى أكثر كلما تقدمت بالشرح):
    لمن استخدم الجافا من قبل، يعلم أنها مبنية تماما على البرمجة الموضوعية (Object-Oriented Programming)، نستطيع الآن ان نضيف اليها نوع آخر وهو البرمجة الوظيفية (Functional Programming). ستعطي المبرمج امكانية كتابة اكواد مختصرة وقابلة للقراءة أكثر. ستضيف امكانية كتابة API's بسهولة اكبر وستسهل عملية استخدامها لاحقا. ستضيف الدعم للمعالجة المتعددة (Parallel Processing). سنركز على أول فائدة ونشرحها باستفاضة تاليًا.
     
    - ما الفرق بين ال(Object-Oreiented and Functional Programming) ؟
    سأجيب على هذا السؤال باجابتي على سؤال أخر، هل فعلا الجافا تحتاج الى Functional Programming ؟
    من سنين طويلة، والجافا كانت (ولا زالت وستظل) تعتمد بشكل أساسي على ال OO-Programming، ولا يوجد أي شيء لا تستطيع فعله بالجافا وتستطيع فعله بFunctional Language أخرى.
    إذا لماذا ؟ ال Functional Programming لا تضيف أي شيء جديد، سوا امكانية كتابة كود قابل للقراءة بسهولة أكبر وتمكنك من اكتشاف الأخطاء واصلاحها بسهولة.
    إذا، فكر بالFunctional Programming كأنها أداة اضافية للOO-Programming لتساعدنا وتسهل علينا كتابة الأكواد بالجافا.
     
    - ما هي المشاكل التي تستدعي استخدام الLambda Expressions ؟
    سأوضح طريقة استعمال الLambda لحل بعض المشاكل التي تواجهنا عن طريق طرح المثال التالي:
    لنفترض بأنني أريد ان انشئ البرنامج الصغير المشهور لطباعة جملة (!Hello World) عن طريق استدعاء Method اخرى في الMain Method:
    public class Greeter { public void greet () { System.out.print("Hello World!"); { public static void main (String[] args) { Greeter greeter = new Greeter(); greeter.greet(); } } عندما يعمل هذا البرنامج الصغير، سيطبع لي جملة Hello World! بالكونسول.
    الآن، لنفترض بأني اريد ان اعدل الميثود greet() لأجعلها تأخذ انبوت معين، وبناء عليه تطبع شي مختلف لكل انبوت مختلف.
    المبرمج العادي سيفكر مباشرة بالSwitch statement وهو تقريبا الحل الأبسط للذهن ولكنه حل غير فعال.
    نريد أن نجد حل لهذه المشكلة، بحيث أننا نستطيع ان ندخل (سلوك) معين للميثود، بدلا من ان ندخل لها مجرد رقم أو جملة، نريد طريقة لإخبار الميثود مباشرة بما نريده عن طريق ادخال مجموعة من الأوامر (a block of code) مرة واحدة.
    قبل ان تأتي الجافا 8، كان بامكاننا حل هذه المشكلة عن طريق انشاء Interface و Class آخرين مساعدين كالتالي:
    public interface GreetingInterface { public void perform(); } public class GreetingClass implements GreetingInterface { @Override public void perform() { System.out.print("Hello World!"); } } ومن ثم نتجه لتعديل الClass الأول ليصبح كالتالي:
    public class Greeter { public void greet (GreetingInterface greeting) { greeting.perform(); { public static void main (String[] args) { Greeter greeter = new Greeter(); GreetingClass greetingClass = new GreetingClass(); greeter.greet(greetingClass); } } نلاحظ أن الميثود greet() الآن اصبحت تستقبل أوبجكت من Class implementeing GreetingInterface، بكلمات أخرى، أصبحت تستقبل (سلوك) لتنفذه بدلا من معطى لتتصرف بناء عليه.
    الآن نستطيع أن نعدل الميثود preform() في كلاس GreetingClass ليتعدل سلوك الميثود greet() بناء عليه.
    لكن هذه الطريقة طويلة وتتطلب انشاء Interface و Class آخرين فقط للقيام بمهمة بسيطة كهذه!
    هناك حل آخر لاختصار كل هذه الأكواد وتجاوز مشكلة انشاء كلاس جديد وهو عن طريق استخدام الAnonymous Inner Class. لن أتطرق لهذا الحل للحاجه لشرح العديد من المفاهيم بالرغم من بساطة الكود المستخدم (ولأن محور المقالة هو استخدام الLambda لحل المشكلة، وهو ما سنتحدث عنه تاليا).
     
    - كيف استخدم الLambda Expression ؟
    كل ما سبق كان مقدمة للتالي: استخدام الLambda Expression لادخال مجموعة من الأوامر كInput الى الميثود greet().
    قبل طرح الحل، تخيلوا معي لو استطعنا ان نحفظ مجموعة من الأوامر في variable معين، (لاحظوا انني قلت حفظ مجموعة من الأوامر وليس نتيجة تنفيذ هذه الأوامر).
    ماذا لو كان بامكاننا ان نكتب شيئا مثل:
    aBlockOfCode = public void printing () { System.out.print("Hello World!"); } بحيث يكون اسم الVariable عبارة عن printingFunction وبداخله 3 سطور من الأوامر. فعليا، هذا ما تتيحه لنا الLambda Expressions.
    مع تتطور الجافا، الآن أصبح الcompiler ذكي كفاية للتعرف على الميثود من دون تحديد (modifier, return type, or the name) في تعريف الميثود، كل ما عليك هو استخدام الرمز الخاص بالLambda Expressions وهو <- ليكون كالتالي:
    //nameOfTheVariable = (LIST OF INPUTS) -> {LIST OF COMMAND LINES}; printingFuncion = () -> System.out.print("Hello World!"); لكي تكتمل العبارة، لابد من اختيار النوع ال(Type) الصحيح، ولكن ماهو نوع هذا الVariable الجديد؟
    الجافا اختارت ان يكون نوع هذا الفاريابل عبارة عن Interface بحيث يحتوي هذا ال Interface على ميثود لها Signature مطابق لLambda Expression:
    public class Test { public static void main(String[] args) { GreetingInterface printingFunction = () -> System.out.print("Hello World!"); } } public interface GreetingInterface { void perform(); } لاحظ ان الLambda Expression لا تحتوي على أي انبوت (وكذلك الميثود الموجودة بال Interface)
    لاحظ أيضا ان الLambda Expression لا تعيد أي قيمة (وكذلك الميثود الموجودة بال Interface من نوع void)
    لاحظ أيضا ان اسم الميثود بال Interface غير مهم أبدا، ما يهم هو اسم الInterface نفسه لأنك ستستعمله ك Type لLambda Expression.
     
    مثال آخر لLambda Expression لجمع رقمين:
    public class Test { public static void main(String[] args) { Add addingFunction = (int a, int b) -> a + b; } } public interface Add { int addingMethod(int a, int b); }  
    بقي علينا استخدام هذا الExpression في الميثود، وتستطيع فعل ذلك عن طريق استدعاء الميثود الموجودة بالInterface.
    بالعودة الى مثال Hello World!:
    public class Greeter { public void greet (GreetingInterface greeting) { greeting.perform(); { public static void main (String[] args) { GreetingInterface printingFunction = () -> System.out.print("Hello World!"); greeter.greet(printingFunction.perform()); } } public interface GreetingInterface { void perform(); }  
    ملاحظات:
    اذا كانت الLambda تحتوي على أكثر من سطر يجب استخدام ال{}  بعد استخدام الرمز <- لا داعي لاستخدام الreturn Statement في حالة السطر الواحد (اذا اردت استخدام الreturn Statement يجب استخدام ال{}) الInterface المستعمل كType للLambda Expression يجب ان يكون Functional Interface (أي يحتوي على ميثود واحدة ففقط بsignature مطابق تماما للLambda Expression)  
    الى هنا نصل لختام هذا الموضوع.
    وفق الله الجميع لما يحبه ويرضاه.
    مستوى المقال: محترف
  12. بسم الله الرحمن الرحيم
    في java لدينا  Throwable class لديه Error و Exception ك subclass .
    Error class لا تستطيع معالجة أخطائه أو على الأقل أثناء Runtime
    لذلك سيكون حديثنا عن Exception class
    ماهو Exception ؟
    هو خطأ-يقال في بعض الأحيان حدث ويقال استثناء- يحدث أثناء تشغيل البرنامج يقطع عملية تنفيذ الأوامر الخاصة بالبرنامج.
    الان لنتطرق لعملية التحكم في الخطأ ومعالجته -catch and handle exceptions-
    بداية نبدأ مع مفهوم try-catch وكالعادة نشوف المفهوم بعدين نشرحه
    public static void main(String[] args) { int a = 5 ; int b = 0 ; System.out.println(a/b); } نلاحظ أن عندنا عملية قسمة لكن على صفر بمعنى أن الناتج راح يكون عدد لا نهائي -infinity- وهذا يعطيني exception من نوع ArithmeticException
    ليتوقف البرنامج عن العمل -crash-و الحل طبعا أنك ما تقسم على صفر لكن سنحاول أن لا يحدث crash للبرنامج باستخدام try-catch block
    public static void main(String[] args) { int a = 5 ; int b = 0 ; try{ System.out.println(a/b); }catch(ArithmeticException e){ System.out.println("divid by zero!"); } } نلاحظ أن لدينا two blocks الأول try والثاني catch يبدأ البرنامج في تنفيذ مابداخل try في حال نجح في تنفيذه بدون exception فأنه يتجاوز catch بدون تنفيذها وفي حال ظهر exception فأنه يتوقف عن أكمل تنفيذ try وينتقل إلى catch .
    جميل جدا لكن ماذا لو كان هناك احتمالية وجود أكثر من exception داخل try block أو كان لدي خطأ لا أعرف لأي نوع من exceptions ينتمي -في حال وضعت catch ل ArithmeticException ثم ظهر لك NullPointerException فإن catch block لن يستطيع التعامل معه- ففي هذه الحالة أستخدم try مع أكثر من catch block كما في المثال
    public static void main (String args[]){ int x = 0 ; Integer y = null ; try { System.out.println(5/x); x = y ; }catch(ArithmeticException e){ System.out.println("catch "+e.getMessage()); }catch (NullPointerException e) { System.out.println("catch "+e.getMessage()); } } أما في حال لم تعرف هذا خطأ لأي نوع من exceptions ينتمي فتستخدم catch block  مع Exception ك parameter لأن جميع ال Exceptions هم subclass من Exception وهذا أحد تطبيقات مبدأ polymorphism , فعلى سبيل المثل سنكرر المثال سابق ولكن نستبدل NullPointerException ب Exception
    public static void main (String args[]){ int x = 0 ; Integer y = null ; try { System.out.println(5/x); x = y ; }catch(ArithmeticException e){ System.out.println("catch "+e.getMessage()); }catch (Exception e) { System.out.println("catch "+e.getMessage()); } } في هذه الحالة في حال ظهور أي خطأ غير ArithmeticException سوف يقوم Exception بتنفيذ catch الخاصة به وهنا يأتي سىؤال لماذا لا أكتفي ب Exception ؟
    إذا كنت تريد أن تعامل كل خطأ بطريقة معينة-كإظهار رسالة معينة أو تنبيه وما إلى ذلك- فيفضل استخدام أكثر من catch block لكل catch ال Exception الخاص بها , أما في حال كان يهمك أن لا يحدث crash لتطبيق فسيكون حل مناسب لك .
    جميل الآن نحن إما أن ننفذ try أو catch لكن ماذا لو كان لدينا أمر ما نريد أن ننفذه في حال تم تنفيذ try أو catch؟ الطريقة الصحيحة ليس أن تكتبه في كلا blocks لكن أن تستخدم جملة finally كما في المثال
    tring args[]){ int x = 0 ; Integer y = null ; try { System.out.println(5/x); x = y ; }catch(ArithmeticException e){ System.out.println("catch "+e.getMessage()); }catch (Exception e) { System.out.println("catch "+e.getMessage()); }finally { System.out.println("I will show up anyway"); } } ف finally block سوف يظهر على كل حال , في حال تنفيذ أي من try أو catch .
    إذا لنلخص قسم try & catch & finally
    نستخدم try و catch واحده في حال كان هناك خطأ واحد نستخدم try وأكثر من  catch  في حال كان هناك أحتمالية وجود أكثر من خطأ  نستخدم finally في حال أردنا تنفيذ أمر معين في كل الحالات . نستخدم Exception ك نوع ل exception في حال كنا فقط نريد أن لا يحدث crash أو كانت جميع الأخطاء لها نفس التعامل -كأن تظهر جميع الأخطاء رسالة Error-  
    طيب ماذا لو أردت أن تضع exception في حال قام أحدهم بخطأ ما , وليكن قام مدخل البيانات بإدخال راتب أحد الموظفين صفر فيكون ال exception بهذه الطريقة
    public static void main (String args[]) throws Exception{ int Salary = 0 ; try{ if(Salary<= 0 ){ throw new ArithmeticException(); } }catch(ArithmeticException e){ System.out.println("R U serious!"); } } قد تكون لاحظت أننا طوال هذه المقالة نستخدم exception الخاصة بنفس اللغة , لكن ماذا لو أردنا بناء exception الخاص بنا بحيث عندما يدخل مدخل البيانات راتب خاطئ يكون هنا SalaryException
    الأمر بسيط كل ما تحتاجه هو بناء class يعمل extends ل Exception وتضع الرسالة المراد إخراجها حال ظهور exception
    public class SalaryException extends Exception { public SalaryException() { super("Salary not valid"); } } public class Salary { public static void main (String args[]) throws Exception{ int Salary = 0 ; try{ if(Salary<= 0 ){ throw new SalaryException(); } }catch(SalaryException e){ System.out.println(e); } } } في هذه الحالة سوف يظهر لك Salary not valid .
     
    Exception class لديه تصنيفين رئيسيين Checked Exception و Unchecked Exception
    - Checked Exception
    هي Exception يشير لها Compiler أثناء وقت تنفيذ الكود -Compile time-  ويجبر المبرمج على معالجتها ,مثل
    IOException SQLException DataAccessException ClassNotFoundException InvocationTargetException MalformedURLException  
    - Unchecked Exception
    على العكس فهذه Exception تكتشف أثناء عمل البرنامج -RuntimeException- مثل
    NullPointerException ArrayIndexOutOfBound IllegalArgumentException IllegalStateException  
    فحين تقوم بكتابة function وتضع داخلها throw لأحد أنواع Checked Exception فسيجبرك Compiler إما على declared exceptions باستخدام throws keyword أو استخدام try-catch كما في المثال
    class Test { static void Nmae (String name) throws IOException{ if (name == "") throw new IOException("Empty name"); } public static void main(String[] args) throws IOException { Nmae (""); } } نلاحظ أنك ستضع أيضا throws داخل أي function تستدعي فيها function التي بداخلها  exceptions كم يحدث هنا في main 
    بالمناسبة Error class الذي تحدثنا عنه بداية المقالة جميع أخطائه تصنف Unchecked Exception
     
    هذا وصلى الله وسلم وبارك على نبينا محمد
    مراجع :
    https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
    https://crunchify.com/better-understanding-on-checked-vs-unchecked-exceptions-how-to-handle-exception-better-way-in-java/
    http://beginnersbook.com/2013/12/throws-keyword-example-in-java/
    مستوى المقال: متوسط

عالم البرمجة

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