مقدمة في Java
ما هي Java؟
Java هي لغة برمجة كائنية التوجه (Object-Oriented Programming) طورتها شركة Sun Microsystems في عام 1995، والآن مملوكة لشركة Oracle.
تاريخ Java:
تم تطوير Java في البداية من قبل جيمس جوسلينج (James Gosling) وفريقه في Sun Microsystems. كان الهدف الأساسي هو إنشاء لغة برمجة يمكن استخدامها في الأجهزة الإلكترونية المختلفة.
مميزات Java:
- البرمجة الكائنية: تدعم مفاهيم الوراثة والتغليف والتعددية بشكل كامل
- المنصة المستقلة: "اكتب مرة واحدة، شغل في أي مكان" (Write Once, Run Anywhere) بفضل JVM
- الذاكرة التلقائية: إدارة تلقائية للذاكرة (Garbage Collection) مما يسهل على المطورين
- الأمان: بيئة آمنة لتطوير التطبيقات مع حماية من الوصول غير المصرح به
- قوية ومتعددة الاستخدامات: يمكن استخدامها لتطوير تطبيقات الويب وسطح المكتب والموبايل
مجالات استخدام Java:
- تطوير تطبيقات الويب (Server-side)
- تطبيقات Android
- تطبيقات المؤسسات الكبيرة
- الأنظمة المالية والمصرفية
- الألعاب والتطبيقات العلمية
بيئة التطوير JDK
ما هو JDK؟
JDK (Java Development Kit) هي مجموعة من الأدوات البرمجية اللازمة لتطوير تطبيقات Java.
مكونات JDK:
- JRE (Java Runtime Environment): البيئة المطلوبة لتشغيل تطبيقات Java
- JVM (Java Virtual Machine): الآلة الافتراضية التي تنفذ كود Java
- Compiler (javac): المترجم الذي يحول كود Java إلى Bytecode
- Libraries: مكتبات Java القياسية (Java API)
كيفية تثبيت JDK:
- قم بتحميل JDK من الموقع الرسمي لـ Oracle
- قم بتثبيت JDK على جهازك
- قم بتعيين متغيرات البيئة (Environment Variables)
- تحقق من التثبيت باستخدام الأمر:
java -version
بيئات التطوير المتكاملة (IDEs):
- IntelliJ IDEA: واحدة من أفضل IDEs لتطوير Java
- Eclipse: بيئة تطوير شائعة ومجانية
- NetBeans: بيئة تطوير رسمية من Oracle
- Visual Studio Code: محرر نصوص خفيف مع إضافات Java
أول برنامج في Java
بنية البرنامج الأساسية:
كل برنامج Java يجب أن يحتوي على كلاس (class) واحد على الأقل يحتوي على دالة main.
مثال برنامج Hello World:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("مرحباً بكم في Java!");
System.out.println("هذا أول برنامج لي");
}
}
شرح الكود:
public class HelloWorld: تعريف كلاس باسم HelloWorld. يجب أن يطابق اسم الكلاس اسم الملفpublic static void main(String[] args): دالة main هي نقطة بداية تنفيذ البرنامجSystem.out.println(): أمر طباعة النص على الشاشة مع الانتقال لسطر جديد
خطوات التشغيل:
- احفظ الملف باسم
HelloWorld.java - افتح Terminal/Command Prompt
- انتقل إلى مجلد الملف
- قم بالتجميع:
javac HelloWorld.java - قم بالتشغيل:
java HelloWorld
المتغيرات وأنواع البيانات الأساسية
ما هي المتغيرات؟
المتغيرات هي أماكن في الذاكرة تستخدم لتخزين البيانات التي يمكن تغييرها أثناء تنفيذ البرنامج.
أنواع البيانات الأساسية (Primitive Types):
| النوع | الحجم | الوصف | مثال |
|---|---|---|---|
byte |
1 byte | أعداد صحيحة من -128 إلى 127 | byte age = 25; |
short |
2 bytes | أعداد صحيحة من -32,768 إلى 32,767 | short count = 1000; |
int |
4 bytes | أعداد صحيحة من -2^31 إلى 2^31-1 | int number = 100000; |
long |
8 bytes | أعداد صحيحة كبيرة | long bigNumber = 1000000L; |
float |
4 bytes | أعداد عشرية (دقة بسيطة) | float price = 99.99f; |
double |
8 bytes | أعداد عشرية (دقة عالية) | double salary = 5000.50; |
char |
2 bytes | حرف واحد (Unicode) | char grade = 'A'; |
boolean |
1 bit | true أو false | boolean isActive = true; |
مثال شامل:
public class Variables {
public static void main(String[] args) {
// تعريف المتغيرات
String name = "أحمد";
int age = 25;
double salary = 5000.50;
boolean isEmployed = true;
char gender = 'M';
// عرض القيم
System.out.println("الاسم: " + name);
System.out.println("العمر: " + age);
System.out.println("الراتب: " + salary);
System.out.println("موظف: " + isEmployed);
System.out.println("الجنس: " + gender);
}
}
قواعد تسمية المتغيرات:
- يجب أن تبدأ بحرف أو underscore (_) أو دولار ($)
- لا يمكن أن تحتوي على مسافات
- لا يمكن استخدام الكلمات المحجوزة (reserved words)
- استخدم camelCase للأسماء المركبة:
firstName
المعاملات والتعبيرات
أنواع المعاملات في Java:
المعاملات (Operators) هي رموز تستخدم لإجراء عمليات على المتغيرات والقيم.
1. المعاملات الحسابية:
int a = 10, b = 3;
int sum = a + b; // 13
int diff = a - b; // 7
int product = a * b; // 30
int quotient = a / b; // 3
int remainder = a % b; // 1
2. معاملات المقارنة:
int x = 5, y = 10;
boolean isEqual = (x == y); // false
boolean notEqual = (x != y); // true
boolean greater = (x > y); // false
boolean less = (x < y); // true
boolean greaterEqual = (x >= y); // false
boolean lessEqual = (x <= y); // true
3. المعاملات المنطقية:
boolean a = true, b = false;
boolean and = a && b; // false (AND)
boolean or = a || b; // true (OR)
boolean not = !a; // false (NOT)
4. معاملات التعيين:
int x = 10;
x += 5; // x = x + 5 → 15
x -= 3; // x = x - 3 → 12
x *= 2; // x = x * 2 → 24
x /= 4; // x = x / 4 → 6
x %= 4; // x = x % 4 → 2
5. معاملات الزيادة والنقصان:
int a = 5;
int b = ++a; // a = 6, b = 6 (Pre-increment)
int c = a++; // a = 7, c = 6 (Post-increment)
int d = --a; // a = 6, d = 6 (Pre-decrement)
int e = a--; // a = 5, e = 6 (Post-decrement)
عبارات الشرط if-else
عبارات الشرط في Java:
تستخدم عبارات الشرط لاتخاذ قرارات في البرنامج بناءً على شروط معينة.
1. if Statement:
int score = 85;
if (score >= 90) {
System.out.println("ممتاز!");
}
2. if-else Statement:
int age = 18;
if (age >= 18) {
System.out.println("أنت بالغ");
} else {
System.out.println("أنت قاصر");
}
3. if-else if-else:
int score = 85;
if (score >= 90) {
System.out.println("ممتاز!");
} else if (score >= 75) {
System.out.println("جيد جداً!");
} else if (score >= 60) {
System.out.println("جيد");
} else {
System.out.println("راسب");
}
4. Nested if (if متداخل):
int age = 25;
boolean hasLicense = true;
if (age >= 18) {
if (hasLicense) {
System.out.println("يمكنك القيادة");
} else {
System.out.println("تحتاج رخصة قيادة");
}
} else {
System.out.println("أنت قاصر");
}
5. Ternary Operator (معامل شرطي):
int age = 20;
String status = (age >= 18) ? "بالغ" : "قاصر";
System.out.println(status); // بالغ
عبارة switch-case
عبارة switch في Java:
تُستخدم عبارة switch عندما تريد تنفيذ كود مختلف بناءً على قيمة متغيرة.
صيغة switch الأساسية:
int day = 3;
switch (day) {
case 1:
System.out.println("الإثنين");
break;
case 2:
System.out.println("الثلاثاء");
break;
case 3:
System.out.println("الأربعاء");
break;
case 4:
System.out.println("الخميس");
break;
case 5:
System.out.println("الجمعة");
break;
default:
System.out.println("يوم آخر");
}
switch مع String (Java 7+):
String language = "Java";
switch (language) {
case "Java":
System.out.println("لغة Java");
break;
case "Python":
System.out.println("لغة Python");
break;
default:
System.out.println("لغة أخرى");
}
switch مع Fall-through (بدون break):
int month = 2;
switch (month) {
case 12:
case 1:
case 2:
System.out.println("الشتاء");
break;
case 3:
case 4:
case 5:
System.out.println("الربيع");
break;
default:
System.out.println("فصل آخر");
}
حلقة for
حلقة for في Java:
تُستخدم حلقة for لتكرار تنفيذ كتلة من الكود لعدد محدد من المرات.
صيغة for الأساسية:
// طباعة الأعداد من 1 إلى 10
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
مثال آخر - حساب المجموع:
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println("المجموع: " + sum); // 5050
for متداخلة (Nested for):
// طباعة جدول الضرب
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 10; j++) {
System.out.print(i * j + "\t");
}
System.out.println();
}
Enhanced for (for-each):
int[] numbers = {10, 20, 30, 40, 50};
for (int number : numbers) {
System.out.println(number);
}
حلقة while و do-while
حلقات while و do-while:
تُستخدم عندما لا تعرف عدد مرات التكرار مسبقاً، وتعتمد على شرط.
1. حلقة while:
int count = 1;
while (count <= 5) {
System.out.println("العدد: " + count);
count++;
}
2. حلقة do-while:
int num = 1;
do {
System.out.println(num);
num++;
} while (num <= 5);
الفرق بين while و do-while:
- while: يتحقق من الشرط أولاً، قد لا ينفذ الكود أبداً
- do-while: ينفذ الكود مرة واحدة على الأقل ثم يتحقق من الشرط
مثال عملي - قراءة من المستخدم:
Scanner scanner = new Scanner(System.in);
int number;
do {
System.out.print("أدخل عدداً موجباً: ");
number = scanner.nextInt();
} while (number <= 0);
System.out.println("شكراً! العدد: " + number);
المصفوفات Arrays
المصفوفات في Java:
المصفوفة هي بنية بيانات لتخزين مجموعة من العناصر من نفس النوع.
1. إنشاء مصفوفة:
// طريقة 1: إنشاء ثم تعيين
int[] numbers = new int[5];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
// طريقة 2: إنشاء وتعيين مباشرة
int[] numbers2 = {10, 20, 30, 40, 50};
2. الوصول للعناصر:
int[] arr = {10, 20, 30};
System.out.println(arr[0]); // 10
System.out.println(arr[1]); // 20
System.out.println(arr.length); // 3
3. المرور على المصفوفة:
int[] numbers = {10, 20, 30, 40, 50};
// استخدام for عادية
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
// استخدام for-each
for (int num : numbers) {
System.out.println(num);
}
4. المصفوفات متعددة الأبعاد:
// مصفوفة ثنائية (2D Array)
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// الوصول للعناصر
System.out.println(matrix[0][0]); // 1
System.out.println(matrix[1][2]); // 6
// المرور على المصفوفة الثنائية
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
المصفوفات متعددة الأبعاد
المصفوفات متعددة الأبعاد في Java:
المصفوفات متعددة الأبعاد تسمح بتخزين البيانات في شكل جدول أو مصفوفة من المصفوفات.
1. إنشاء مصفوفة ثنائية:
// طريقة 1: إنشاء ثم تعيين
int[][] matrix = new int[3][3];
matrix[0][0] = 1;
matrix[0][1] = 2;
matrix[0][2] = 3;
// طريقة 2: إنشاء وتعيين مباشرة
int[][] matrix2 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
2. المرور على المصفوفة الثنائية:
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// طباعة جميع العناصر
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + "\t");
}
System.out.println();
}
3. مصفوفات غير منتظمة (Jagged Arrays):
// مصفوفة بأطوال مختلفة
int[][] jagged = new int[3][];
jagged[0] = new int[2];
jagged[1] = new int[4];
jagged[2] = new int[3];
4. مثال عملي - جدول الضرب:
int[][] multiplicationTable = new int[10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
multiplicationTable[i][j] = (i + 1) * (j + 1);
}
}
// طباعة الجدول
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.printf("%4d", multiplicationTable[i][j]);
}
System.out.println();
}
الدوال Methods
الدوال في Java:
الدوال (Methods) هي كتل من الكود قابلة لإعادة الاستخدام تؤدي وظيفة محددة.
1. تعريف دالة بسيطة:
public class MethodsExample {
// دالة بلا معاملات وبلا قيمة إرجاع
public static void greet() {
System.out.println("مرحباً!");
}
// دالة بمعاملات
public static void greetPerson(String name) {
System.out.println("مرحباً " + name + "!");
}
// دالة تُرجع قيمة
public static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
greet();
greetPerson("أحمد");
int result = add(5, 3);
System.out.println("النتيجة: " + result); // 8
}
}
2. أنواع الدوال:
- Static Methods: تنتمي للكلاس وليس للكائن
- Instance Methods: تنتمي لكائن محدد
- Void Methods: لا ترجع قيمة
- Return Methods: ترجع قيمة محددة
3. مثال شامل:
public class Calculator {
public static int multiply(int x, int y) {
return x * y;
}
public static double divide(double a, double b) {
if (b != 0) {
return a / b;
} else {
System.out.println("لا يمكن القسمة على صفر!");
return 0;
}
}
public static void printResult(String operation, double result) {
System.out.println(operation + " = " + result);
}
}
معاملات الدوال Overloading
Method Overloading في Java:
Method Overloading يعني تعريف عدة دوال بنفس الاسم لكن بمعاملات مختلفة.
مثال على Method Overloading:
public class MathUtils {
// دالة add للمتغيرات int
public static int add(int a, int b) {
return a + b;
}
// نفس الاسم لكن مع double
public static double add(double a, double b) {
return a + b;
}
// نفس الاسم لكن بثلاثة معاملات
public static int add(int a, int b, int c) {
return a + b + c;
}
public static void main(String[] args) {
System.out.println(add(5, 3)); // 8
System.out.println(add(5.5, 3.2)); // 8.7
System.out.println(add(1, 2, 3)); // 6
}
}
قواعد Method Overloading:
- يجب أن يكون الاسم نفسه
- يجب أن تختلف المعاملات في: العدد، النوع، أو الترتيب
- لا يمكن الاعتماد فقط على نوع الإرجاع
مثال عملي - طباعة:
public class Printer {
public static void print(int value) {
System.out.println("عدد صحيح: " + value);
}
public static void print(double value) {
System.out.println("عدد عشري: " + value);
}
public static void print(String text) {
System.out.println("نص: " + text);
}
public static void print(int[] array) {
System.out.print("مصفوفة: ");
for (int num : array) {
System.out.print(num + " ");
}
System.out.println();
}
}
مفهوم الكائنات والكلاسات
البرمجة الكائنية التوجه (OOP):
Java لغة برمجة كائنية التوجه، حيث كل شيء في Java هو كائن (Object) أو ينتمي لكلاس (Class).
مفاهيم OOP الأساسية:
- Class (الكلاس): قالب لإنشاء الكائنات
- Object (الكائن): مثال محدد من الكلاس
- Encapsulation (التغليف): إخفاء تفاصيل التنفيذ
- Inheritance (الوراثة): نقل الصفات من كلاس لآخر
- Polymorphism (تعدد الأشكال): نفس الواجهة، تنفيذ مختلف
مثال بسيط:
// تعريف كلاس
public class Car {
// Attributes (الخصائص)
String brand;
String color;
int year;
// Methods (الوظائف)
public void start() {
System.out.println("السيارة تعمل");
}
public void stop() {
System.out.println("السيارة متوقفة");
}
}
// إنشاء كائنات
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.brand = "Toyota";
myCar.color = "أحمر";
myCar.year = 2023;
myCar.start();
myCar.stop();
}
}
البنائين Constructors
Constructors في Java:
Constructor هو دالة خاصة تُستدعى تلقائياً عند إنشاء كائن جديد من الكلاس.
1. Default Constructor:
public class Person {
String name;
int age;
// Default Constructor (يُنشأ تلقائياً إذا لم نحدده)
public Person() {
name = "غير محدد";
age = 0;
}
}
2. Parameterized Constructor:
public class Person {
String name;
int age;
// Constructor بمعاملات
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void display() {
System.out.println("الاسم: " + name + ", العمر: " + age);
}
public static void main(String[] args) {
Person person1 = new Person("أحمد", 25);
person1.display();
}
}
3. Constructor Overloading:
public class Rectangle {
int width;
int height;
// Constructor بدون معاملات
public Rectangle() {
this.width = 1;
this.height = 1;
}
// Constructor بمعامل واحد (مربع)
public Rectangle(int side) {
this.width = side;
this.height = side;
}
// Constructor بمعاملين
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}
this تشير إلى الكائن الحالي.
التغليف Encapsulation
Encapsulation في Java:
Encapsulation يعني إخفاء تفاصيل التنفيذ وإتاحة الوصول للبيانات من خلال methods محددة.
Access Modifiers:
public: متاح من أي مكانprivate: متاح فقط داخل الكلاس نفسهprotected: متاح داخل الكلاس والكلاسات الموروثةdefault: متاح داخل نفس الحزمة (package)
مثال على Encapsulation:
public class BankAccount {
// Private attributes
private double balance;
private String accountNumber;
// Constructor
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
if (initialBalance >= 0) {
this.balance = initialBalance;
} else {
this.balance = 0;
}
}
// Getter method
public double getBalance() {
return balance;
}
// Setter method مع التحقق
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("تم الإيداع: " + amount);
} else {
System.out.println("المبلغ غير صحيح!");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("تم السحب: " + amount);
} else {
System.out.println("المبلغ غير متاح!");
}
}
}
الوراثة Inheritance
Inheritance في Java:
Inheritance تسمح لكلاس بالحصول على صفات ووظائف كلاس آخر.
مثال على Inheritance:
// Parent Class (الكلاس الأب)
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " يأكل");
}
public void sleep() {
System.out.println(name + " ينام");
}
}
// Child Class (الكلاس الابن)
public class Dog extends Animal {
String breed;
public Dog(String name, String breed) {
super(name); // استدعاء constructor الأب
this.breed = breed;
}
public void bark() {
System.out.println(name + " ينبح");
}
// Method Overriding
@Override
public void eat() {
System.out.println(name + " يأكل الطعام المخصص للكلاب");
}
}
// استخدام
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("ريكس", "جيرمن شيبرد");
myDog.eat(); // من الأب (معدّل)
myDog.sleep(); // من الأب
myDog.bark(); // خاص بالكلب
}
}
كلمات مفتاحية مهمة:
extends: للوراثةsuper: للإشارة للكلاس الأب@Override: لتجاوز method من الأب
تعدد الأشكال Polymorphism
Polymorphism في Java:
Polymorphism يعني قدرة الكائنات على أخذ أشكال متعددة، نفس الواجهة لكن تنفيذ مختلف.
Runtime Polymorphism (Method Overriding):
public class Shape {
public void draw() {
System.out.println("رسم شكل");
}
}
public class Circle extends Shape {
@Override
public void draw() {
System.out.println("رسم دائرة");
}
}
public class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("رسم مستطيل");
}
}
// استخدام Polymorphism
public class Main {
public static void main(String[] args) {
Shape shape1 = new Circle();
Shape shape2 = new Rectangle();
shape1.draw(); // رسم دائرة
shape2.draw(); // رسم مستطيل
}
}
مثال عملي:
public class Employee {
protected String name;
public Employee(String name) {
this.name = name;
}
public double calculateSalary() {
return 0;
}
}
public class FullTimeEmployee extends Employee {
private double monthlySalary;
public FullTimeEmployee(String name, double monthlySalary) {
super(name);
this.monthlySalary = monthlySalary;
}
@Override
public double calculateSalary() {
return monthlySalary;
}
}
public class PartTimeEmployee extends Employee {
private double hourlyRate;
private int hoursWorked;
public PartTimeEmployee(String name, double hourlyRate, int hoursWorked) {
super(name);
this.hourlyRate = hourlyRate;
this.hoursWorked = hoursWorked;
}
@Override
public double calculateSalary() {
return hourlyRate * hoursWorked;
}
}
الواجهات Interfaces
Interfaces في Java:
Interface هو عقد يحدد ما يجب أن تفعله الكلاسات دون تحديد كيفية التنفيذ.
تعريف Interface:
// تعريف Interface
public interface Drawable {
void draw(); // method بلا تنفيذ (implicitly public abstract)
void resize(int size);
}
// تنفيذ Interface
public class Circle implements Drawable {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("رسم دائرة بنصف قطر: " + radius);
}
@Override
public void resize(int size) {
this.radius = size;
System.out.println("تم تغيير نصف القطر إلى: " + size);
}
}
Java 8+ - Default Methods:
public interface Calculator {
int add(int a, int b);
// Default method (له تنفيذ افتراضي)
default int multiply(int a, int b) {
return a * b;
}
// Static method
static void printInfo() {
System.out.println("آلة حاسبة");
}
}
تنفيذ عدة Interfaces:
public interface Flyable {
void fly();
}
public interface Swimmable {
void swim();
}
public class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("البطة تطير");
}
@Override
public void swim() {
System.out.println("البطة تسبح");
}
}
الكلاسات المجردة Abstract Classes
Abstract Classes في Java:
Abstract Class هي كلاس لا يمكن إنشاء كائنات منه مباشرة، ويحتوي على methods مجردة و/أو عادية.
مثال على Abstract Class:
// Abstract Class
public abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
// Concrete method (له تنفيذ)
public void sleep() {
System.out.println(name + " ينام");
}
// Abstract method (لا له تنفيذ)
public abstract void makeSound();
}
// تنفيذ Abstract Class
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " ينبح: واو واو!");
}
}
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " يموء: مياو!");
}
}
الفرق بين Abstract Class و Interface:
| Abstract Class | Interface |
|---|---|
| يمكن أن تحتوي على متغيرات instance | يمكن أن تحتوي على constants فقط |
| يمكن أن تحتوي على methods عادية ومجردة | كل methods مجردة (قبل Java 8) |
| تدعم واحدة فقط (single inheritance) | تدعم عدة interfaces (multiple inheritance) |
| يمكن أن يكون لها constructor | لا يمكن أن يكون لها constructor |
String و StringBuffer
String في Java:
String هي فئة في Java لتمثيل النصوص، وهي immutable (غير قابلة للتعديل).
1. إنشاء Strings:
String str1 = "مرحباً";
String str2 = new String("العالم");
String str3 = str1 + " " + str2; // "مرحباً العالم"
2. Methods مهمة في String:
String text = "Hello World";
System.out.println(text.length()); // 11
System.out.println(text.charAt(0)); // 'H'
System.out.println(text.substring(0, 5)); // "Hello"
System.out.println(text.toUpperCase()); // "HELLO WORLD"
System.out.println(text.toLowerCase()); // "hello world"
System.out.println(text.contains("World")); // true
System.out.println(text.replace("World", "Java")); // "Hello Java"
3. StringBuffer (قابل للتعديل):
StringBuffer sb = new StringBuffer("مرحباً");
sb.append(" بالعالم");
sb.insert(7, " ");
sb.reverse();
System.out.println(sb.toString());
ArrayList - الجزء الأول
ArrayList في Java:
ArrayList هي قائمة ديناميكية يمكنها النمو أو التقلص حسب الحاجة، أفضل من Arrays في معظم الحالات.
1. إنشاء ArrayList:
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();
ArrayList<Integer> numbers = new ArrayList<Integer>();
2. العمليات الأساسية:
ArrayList<String> list = new ArrayList<>();
// إضافة عناصر
list.add("أحمد");
list.add("محمد");
list.add("فاطمة");
// الحصول على العنصر
String name = list.get(0); // "أحمد"
// الحجم
int size = list.size(); // 3
// حذف عنصر
list.remove(0); // حذف "أحمد"
// التحقق من وجود عنصر
boolean exists = list.contains("محمد"); // true
3. المرور على ArrayList:
// باستخدام for-each
for (String name : list) {
System.out.println(name);
}
// باستخدام for عادية
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
ArrayList - الجزء الثاني
عمليات متقدمة في ArrayList:
1. إضافة في موضع محدد:
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(30);
numbers.add(2, 20); // إضافة 20 في الفهرس 2
// النتيجة: [10, 30, 20]
2. تحديث قيمة:
numbers.set(0, 15); // تغيير العنصر في الفهرس 0 إلى 15
3. حذف جميع العناصر:
numbers.clear(); // حذف جميع العناصر
4. مثال شامل:
import java.util.ArrayList;
import java.util.Collections;
ArrayList<Integer> scores = new ArrayList<>();
scores.add(85);
scores.add(92);
scores.add(78);
scores.add(95);
// ترتيب القائمة
Collections.sort(scores);
// البحث
int index = Collections.binarySearch(scores, 85);
// العثور على أكبر وأصغر قيمة
int max = Collections.max(scores);
int min = Collections.min(scores);
HashMap و HashTable
HashMap في Java:
HashMap تخزن البيانات في أزواج Key-Value، وتوفر وصول سريع للبيانات.
1. إنشاء واستخدام HashMap:
import java.util.HashMap;
HashMap<String, Integer> ages = new HashMap<>();
// إضافة عناصر
ages.put("أحمد", 25);
ages.put("محمد", 30);
ages.put("فاطمة", 22);
// الحصول على قيمة
int age = ages.get("أحمد"); // 25
// التحقق من وجود مفتاح
boolean exists = ages.containsKey("أحمد"); // true
// حذف عنصر
ages.remove("محمد");
// الحجم
int size = ages.size();
2. المرور على HashMap:
// المرور على Keys
for (String name : ages.keySet()) {
System.out.println(name + ": " + ages.get(name));
}
// المرور على Entries
for (Map.Entry<String, Integer> entry : ages.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
3. HashTable vs HashMap:
- HashMap: غير متزامن، أسرع، يسمح بقيمة null
- HashTable: متزامن، أبطأ، لا يسمح بقيمة null
معالجة الاستثناءات Exceptions
Exception Handling في Java:
Exception Handling يسمح للبرنامج بالتعامل مع الأخطاء بشكل مناسب بدلاً من التوقف.
1. try-catch:
try {
int result = 10 / 0; // سيحدث ArithmeticException
} catch (ArithmeticException e) {
System.out.println("خطأ: لا يمكن القسمة على صفر");
System.out.println("التفاصيل: " + e.getMessage());
}
2. try-catch-finally:
try {
// كود قد يسبب خطأ
int[] arr = new int[5];
arr[10] = 100; // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("فهرس خارج النطاق");
} finally {
// يُنفذ دائماً
System.out.println("تم الانتهاء من try-catch");
}
3. Multiple catch blocks:
try {
// كود
} catch (ArithmeticException e) {
System.out.println("خطأ حسابي");
} catch (NullPointerException e) {
System.out.println("مرجع فارغ");
} catch (Exception e) {
System.out.println("خطأ عام: " + e.getMessage());
}
try-catch-finally
مزيد من التفاصيل حول Exception Handling:
1. Custom Exceptions:
// إنشاء Exception مخصص
public class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
// استخدام
public class Person {
private int age;
public void setAge(int age) throws InvalidAgeException {
if (age < 0 || age > 150) {
throw new InvalidAgeException("العمر غير صحيح: " + age);
}
this.age = age;
}
}
2. throws Keyword:
public void readFile(String filename) throws IOException {
FileReader file = new FileReader(filename);
// ...
}
3. مثال عملي شامل:
import java.util.Scanner;
public class ExceptionExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("أدخل عدداً: ");
int number = scanner.nextInt();
System.out.print("أدخل عدداً آخر: ");
int divisor = scanner.nextInt();
int result = number / divisor;
System.out.println("النتيجة: " + result);
} catch (java.util.InputMismatchException e) {
System.out.println("خطأ: يجب إدخال عدد صحيح");
} catch (ArithmeticException e) {
System.out.println("خطأ: لا يمكن القسمة على صفر");
} catch (Exception e) {
System.out.println("حدث خطأ غير متوقع: " + e.getMessage());
} finally {
scanner.close();
System.out.println("تم إغلاق الماسح الضوئي");
}
}
}
الملفات File I/O
File Input/Output في Java:
Java توفر عدة طرق للتعامل مع الملفات: قراءة وكتابة البيانات.
1. قراءة من ملف باستخدام FileReader:
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
try {
FileReader fileReader = new FileReader("data.txt");
BufferedReader reader = new BufferedReader(fileReader);
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
} catch (IOException e) {
System.out.println("خطأ في قراءة الملف: " + e.getMessage());
}
2. الكتابة إلى ملف:
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;
try {
FileWriter fileWriter = new FileWriter("output.txt");
BufferedWriter writer = new BufferedWriter(fileWriter);
writer.write("مرحباً بالعالم");
writer.newLine();
writer.write("هذا سطر جديد");
writer.close();
} catch (IOException e) {
System.out.println("خطأ في الكتابة: " + e.getMessage());
}
3. استخدام try-with-resources (موصى به):
try (FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} // الملف يُغلق تلقائياً
Multithreading الأساسيات
Multithreading في Java:
Multithreading يسمح بتنفيذ عدة عمليات في نفس الوقت، مما يحسن الأداء.
1. إنشاء Thread بطريقتين:
// الطريقة 1: Extend Thread
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Thread: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// الطريقة 2: Implement Runnable
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Runnable: " + i);
}
}
}
// الاستخدام
public class Main {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
thread1.start();
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
}
}
2. Thread Methods:
Thread thread = new Thread(() -> {
System.out.println("Thread يعمل");
});
thread.start(); // بدء Thread
thread.join(); // انتظار انتهاء Thread
thread.sleep(1000); // توقيف Thread لمدة معينة
Swing و GUI
Java Swing:
Swing هي مكتبة Java لإنشاء واجهات المستخدم الرسومية (GUI).
مثال بسيط - نافذة:
import javax.swing.*;
public class SimpleGUI {
public static void main(String[] args) {
JFrame frame = new JFrame("تطبيق بسيط");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("مرحباً بكم!");
JButton button = new JButton("اضغط هنا");
button.addActionListener(e -> {
label.setText("تم الضغط على الزر!");
});
frame.add(label);
frame.add(button);
frame.setLayout(new FlowLayout());
frame.setVisible(true);
}
}
مكونات Swing الأساسية:
JFrame: النافذة الرئيسيةJLabel: نص أو صورةJButton: زرJTextField: حقل إدخال نصJTextArea: منطقة نص كبيرةJPanel: لوحة لتجميع المكونات
مشروع تطبيقي شامل
مشروع: نظام إدارة طلاب
مشروع شامل يجمع معظم المفاهيم التي تعلمناها في الكورس.
البنية المقترحة:
// Student Class
public class Student {
private String name;
private int id;
private ArrayList<Double> grades;
public Student(String name, int id) {
this.name = name;
this.id = id;
this.grades = new ArrayList<>();
}
public void addGrade(double grade) {
if (grade >= 0 && grade <= 100) {
grades.add(grade);
}
}
public double getAverage() {
if (grades.isEmpty()) return 0;
double sum = 0;
for (double grade : grades) {
sum += grade;
}
return sum / grades.size();
}
// Getters and Setters
// ...
}
// StudentManager Class
import java.util.ArrayList;
import java.util.HashMap;
public class StudentManager {
private HashMap<Integer, Student> students;
public StudentManager() {
this.students = new HashMap<>();
}
public void addStudent(Student student) {
students.put(student.getId(), student);
}
public Student getStudent(int id) {
return students.get(id);
}
public void displayAllStudents() {
for (Student student : students.values()) {
System.out.println(student);
}
}
}
// Main Class
public class Main {
public static void main(String[] args) {
StudentManager manager = new StudentManager();
Student student1 = new Student("أحمد", 1001);
student1.addGrade(85);
student1.addGrade(90);
student1.addGrade(88);
manager.addStudent(student1);
manager.displayAllStudents();
}
}
ميزات المشروع:
- استخدام Classes و Objects
- Encapsulation (Private attributes, Public methods)
- Collections (ArrayList, HashMap)
- Exception Handling
- File I/O (حفظ وقراءة البيانات)
- GUI (واجهة مستخدم بسيطة)