1.  
    بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
     
    في هذا الموضوع، سنستعرض ال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); } }  
     
    وهنا نصل الى ختام موضوعنا، أسأل الله لي ولكم التوفيق والسداد.
    مستوى المقال: محترف
  2. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته،
    سنتحدث في هذا الموضوع عن مفهوم ال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
     
    هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.
    مستوى المقال: مبتدئ
  3. السلام عليكم ورحمة الله وبركاته،
    هذا الدرس البسيط سيشرح باذن الله مفهوم ال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.
     
    هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.
    مستوى المقال: مبتدئ
  4. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
     
    استأنافا لما بدأنا عنه حول مواضيع هياكل البيانات سنتقطرق اليوم على نوع من أنواع الـ 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 الى حد بعيد.
     
     
    اتمنى من الله أني وفقت لإصال المعلومة
    في حفظ الله
    مستوى المقال: مبتدئ
  5. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
    سنتطرق في هذا الموضوع لل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
     
    مستوى المقال: محترف
  6. بسم الله الرحمن الرحيم 
    السلام عليكم ورحمة الله وبركاته
     
    ستحتاج إلى قراءة الموضوع السابق الخاص بـالـ 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); } }  
    المخرج النهائي :

    مستوى المقال: محترف
  7. السلام عليكم ورحمة الله وبركاته
    في هذه المقاله سنناقش انواع ال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  
    الى هنا نصل الى ختام موضوعنا.
    وفق الله الحميع لما يحبه ويرضاه.
    مستوى المقال: متوسط
  8. بسم الله الرحمن الرحيم
    السلام عليكم ورحمة الله وبركاته
     
    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]); }  
    المخرج النهائي 

     
    مستوى المقال: متوسط
  9. السلام عليكم،
    في هذه المقالة سنطلع على مقدمة لأهم ما قدمته ال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)  
    الى هنا نصل لختام هذا الموضوع.
    وفق الله الجميع لما يحبه ويرضاه.
    مستوى المقال: محترف
  10. بسم الله الرحمن الرحيم
    في 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/
    مستوى المقال: متوسط
  11. بسم الله الرحمن الرحيم
    اختبار المساواة والذي نطبقه غالبا باستخدام "== " لتأكد من تساوي البيانات التي نود التحقق منها
    غير أن هذه المقارنة لا تتم دائما كما نتوقع ولنبدأ بالتجربة والتأكد والتعليل
    في البداية لدينا هذا الكود
    int a = 5 ; int b = 5 ; System.out.print(a==b); ونتيجة هذه المقارنة تبدو واضحة جدا حيث يقوم compiler بالقيام بعملية المقارنة وإرجاع true or false حسب النتيجة
    لكن هذا لا يكون إلا في حال كان نوع البيانات التي نتعامل معها هو primitive data types بمعنى أن المقارنة بهذه الطريقة مع object type ستكون نتيجتها مختلفة تمام عن المتوقع
    ولنأخذ هذا المثال
    Integer a = new Integer(5); Integer b = new Integer(5); System.out.println(a == b); قد تفاجأ حين تظهر لك نتيجة هذه المقارنة false ولكن يعود السبب في هذه النتيجة أنه عندما تنشئ متغير من نوع object فأنت لا تسند له القيمة و إنما المرجع (reference)
    ففي المثال السابق لا تتم المقارنة بهذه الصورة (5 ==5 ) و إنما نقول تجوزا بهذه الصورة (0x24 == 0x33) فالمقارنة على تتم علىobject  reference و ليست على قيمة object
    إذا مالحل ؟
    الحل هو استخدام equals method كما في المثال التالي
    Integer a = new Integer(5); Integer b = new Integer(5); System.out.println(a.equals(b)); فنتيجة هذه المقارنة ستكون true حيث أن equals method ستقوم بمقارنة القيم وتعطي نتائج سليمة 
    إذا هل استخدم equals method مع جميع المتغيرات من نوع object ؟
    الجواب لا , ف equals method هي من class object وهذا class هو superclass لجميع classes في java
    إذا ف equals method ستورث لأي class ينشأ, لكن في حال لم يتم عمل override لها داخل class فلن تعطيك نتائج سليمة
    ولنأخذ هذا المثال
    String a = new String ("test"); String b = new String ("test"); StringBuilder c = new StringBuilder("test"); StringBuilder d = new StringBuilder("test"); System.out.println("String: "+a.equals(b)); System.out.println("StringBuilder: "+c.equals(d)); فسيكون output كالتالي
    String: true StringBuilder: false و السبب يعود كما أسلفت لأنه في class String تم عمل override ل equals method وهذا لم يتم في StringBuilder class
    ويمكنك التأكد من هنا
    String : https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#equals(java.lang.Object)
    StringBuilder : https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html
    جميل جداً وهذا يقودنا إلى تساؤل , كيف يمكن أن أعمل override ل equals method داخل class الذي أنشأته ؟
    لنأخذ هذا المثال لنفرض أن لدينا class اسمه Student وفيه two data member وهما name & address
    public class Student { String name ; String address ; //constructor Student (){ name = "abdulaziz" ; address = "riyadh" ; } //override of equals method in our class public boolean equals (Object other){ boolean result = false ; if(other instanceof Student){ Student S2 = (Student)other ; result = S2.name.equals(this.name) && S2.address.equals(this.address) ; } return result ; } public static void main(String[] args) { Student a =new Student() ; Student b =new Student(); System.out.println(a.equals(b)); } } فكما نشاهد في هذا المثال فقد تم عمل override ل equals method واستخدامها داخل class الذي قمنا بإنشائه
    نقطة أخيره أختم بها هذه المقالة لا يمكن استخدام equals method مع null object وإلا ستحصل على java.lang.NullPointerException كما في هذا المثال
    Student a =null ; Student b =null; System.out.println(a.equals(b));  
    وختاما إن وفقت في الطرح والمعلومات فمن الله وإن أخطأت فمن نفسي والشيطان
    والسلام عليكم ورحمة الله وبركاته
    المصادر:
    https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
    https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html
    https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
    https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
    مستوى المقال: مبتدئ
  12. في هذه المقالة سأتحدث عن Constructors وأنواعها وطريقة كتابتها وتفاصيل أخرى في لغة Java .
    بدايةً : سبب كتابة المقال عن constructor 
    كثير ممن بدأ بتعلم البرمجة يجد صعوبة في فهم ال constructor وحقيقة أنا كنت منهم ولكن مع التطبيق المتواصل لعدة أفكار برمجية فهمت الصورة لذلك لا تكتفي فقط بالقراءة وتظن انك استطعت استيعاب الموضوع كاملاً .
    بعد قرائتك لهذا المقال افتح المحرر الموجود عندك وطبق مباشرة .
    ماهو constructor ؟ 
    هو عبارة عن دالة من نوع خاص في لغات  Object Oriented حيث يتم تجهيز أي Object سوف نستخدمه من هذا الكلاس عن طريقه ونستطيع كتابة متغيرات فيه يستطيع الأوبجكت أن يستخدمها في كلاس آخر و عند تعريف الـ  object بكلمة new يعمل ال constructor أولاً .
    نقاط مهمة لابد من معرفتها 
    أولها : أن constructor يأخذ نفس اسم الكلاس وقد يكون في الكلاس الواحد أكثر من constructor  ولكن بمتغيرات مختلفة النوع أو العدد وهذا مايسمى ب overloading .
    ثانيها : عند استخدام constructor يوجد بداخله متغيرات بنفس أسماء المتغيرات الموجودة في نفس الكلاس لابد أن نستخدم كلمة this تعبيراً عن أن القيمة التي تحملها الدالة هي نفسها القيمة في داخل الكلاس .
    سؤال : مالذي سيحصل عند عدم استخدام كلمة this ؟
    سوف يقوم المتغير داخل الدالة باخفاء قيمة المتغير الموجود بداخل الكلاس وهذا العملية تسمى Instance Variable hiding حيث يقوم المتغير بداخل أي دالة الذي اسمه بنفس اسم المتغير الموجود في الكلاس باخفاء قيمة المتغير الموجود بالكلاس .
    للمعلومية : هذا يحصل حتى في الدوال الأخرى ليس constructor فقط .
    public class ConstructorDemo{ String name; public ConstructorDemo() { } public ConstructorDemo(String name) { this.name=name; } أما الآخر فيحمل متغير بنفس اسم المتغير داخل الكلاس واستخدمنا كلمة this للدلالة على أنه يحمل نفس القيمة لكن لو كان اسم المتغير بالدالة مختلف فلا مشكلة من عدم استخدام this .
    لمعلوماتك : 
    المتغيرات داخل أي دالة تسمى Local Varaibles  وهذه المتغيرات لا نستطيع استخدامها الا داخل الدالة فقط . المتغيرات داخل أي كلاس تسمى Instance variables ونستطيع اسخدامها في الدوال الخارجية والكلاسات الأخرى وأي block آخر مهما كان . ثالثها : أن constructor لا يرجع قيمة ولا يمكن أن نكتب قبله كلمة void حتى .
    رابعها : كل كلاس داخل الجافا يوجد به constructor حتى لو لم يعرفه المبرمج ، حيث يقوم الجافا بعمل constructor افتراضي .
    خامسها : تستطيع استخدام أي Access modifier عند كتابة constructors , سواءاً كان ذلك public , private or protected أو تجعله افتراضي حيث يستخدام داخل packge فقط ولكن عند استخدام private فانك لاتستطيع اخذ اوبجكت من الكلاس ولاتستطيع عمل اكستند للكلاس لانها تسمى super constructor وعادتاً تستخدم مع الـ singleton pattern
    سادسها : ال constructors في الجافا لا يمكن أن تكون static , abstract , final or synchronized كلها غير مسموح بها .
    سابعها : ال constructors تستطيع عمل ThrowsException في الجافا .
    ثامنها : لا يوجد destructor في الجافا بعكس لغة ++c .
    بعض أنواع دوال constructors : 
    parameterised constructors : من اسمه يدل على أن بداخله متغير أو أكثر واذا أنشأنا أوبجكت من هذا الكلاس فلابد من كتابة نفس نوع المتغيرات الموجودة في هذا constructor .
    مثال : 
    class Example { int x, y; Example() { } // parameterized constructor Example(int a, int b) { x = a; y = b; } } وعند انشاء أوبجكت من هذا الكلاس يصبح كالتالي :
     Example e=new Example(); Example e =new Example(0, 50);   
    Default constructors : اذا المبرمج لم ينشئ constructor ستقوم الجافا بانشاء كلاس افتراضي وسيقوم بانشاء متغيرات افتراضية فمثلاً
    reference type = null numreical type = 0 or 0.0 or 0.0f boolean = false مثال :
    class Student3{ int id; String name; void display(){ System.out.println(id+” “+name); } public static void main(String args[]){ Student3 s1=new Student3(); s1.display(); } } 0 null صيغة كتابة constructor :  
    Access modifiers _ className() { Statement ; } مالذي يحدث داخل الذاكرة ؟ 
    عند انشاء constructor ثم انشاء object يتم تخزينه بتركيب بيانات يسمى heap الذي يقوم بتخزين جميع أنواع reference types التي تؤشر على قيمها ال primitive types في تركيب البيانات المسمى stack .
    مالفرق بين constructor و methods ؟ 
    ال constructor يستخدم لتهيئة ال object أما الدوال فتقوم بوصف المتغيرات . ال constructor لاترجع أي قيم أما الميثود فقد ترجع قيم . أخيراً : هل تقتصر وظيفة ال constructor على تهيئة objects فقط ؟ 
    الجواب على هذا السؤال لا طبعاً ، ال constructor يقوم ببدء thread مثلاً وهذا موضوع آخر طبعاً ، أيضاً ال constructor يستطيع استدعاء دوال وإلى آخره .
    إلى هنا وأكتفي بهذا القدر من المعلومات ، قد تكون هذه المعلومات معروفة لدي المبرمجين غالباً لكن أعرف أن هناك الكثير من المبتدئين الذين يواجهون صعوبة في فهم هذا الموضوع وأتمنى أن أكون قد أفدتهم ولو بشئ بسيط .
    مستوى المقال: مبتدئ

عالم البرمجة

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