این بخش جنبههای بیشتری از کلاسها را پوشش میدهد که بر استفاده از مراجع شیء و عملگر نقطه که در بخشهای قبلی دربارهٔ اشیا آموختید استوار هستند:
thisیک Method در یکی از این سه حالت به کد فراخوانیکننده بازمیگردد:
return رسیده باشد، یانوع خروجی Method را در اعلامیهٔ Method تعریف میکنید. در داخل بدنهٔ Method، از دستور return برای برگرداندن مقدار استفاده میکنید.
هر Methodای که void تعریف شده باشد، مقداری برنمیگرداند. نیازی به دستور return ندارد، اما میتواند داشته باشد. در چنین موردی، دستور return میتواند برای خروج از یک بلوک کنترلی و پایان Method استفاده شود و بهسادگی به این شکل نوشته میشود:
return;
اگر بخواهید مقداری از Methodای که void تعریف شده برگردانید، خطای کامپایل دریافت خواهید کرد.
هر Methodای که void نباشد، باید شامل دستور return با مقدار بازگشتی مناسب باشد، مانند:
return returnValue;
نوع دادهٔ مقدار بازگشتی باید با نوع خروجی اعلامشدهٔ Method مطابقت داشته باشد. نمیتوانید مقدار عدد صحیح را از Methodای که boolean برمیگرداند، برگردانید.
Method getArea() در کلاس Rectangle که در بخشهای قبلی دربارهٔ اشیا بررسی شد، عدد صحیح برمیگرداند:
// Method برای محاسبهٔ مساحت مستطیل
public int getArea() {
return width * height;
}
این Method عدد صحیحی را که عبارت width*height محاسبه میکند، برمیگرداند.
Method getArea() یک نوع Primitive برمیگرداند. Method همچنین میتواند یک Reference Type برگرداند. برای مثال، در برنامهای برای مدیریت اشیای Bicycle، ممکن است Methodای مثل این داشته باشیم:
public Bicycle seeWhosFastest(Bicycle myBike, Bicycle yourBike, Environment env) {
Bicycle fastest;
// کد محاسبهٔ اینکه کدام دوچرخه سریعتر است
// با در نظر گرفتن gear و cadence هر دوچرخه
// و شرایط محیطی (زمین و باد)
return fastest;
}
---
نکته: اگر این بخش گیجکننده است، از آن رد شوید و پس از اتمام بخشهای Inheritance و Interfaceها به آن بازگردید.
وقتی یک Method از نام کلاس بهعنوان نوع خروجی استفاده میکند — مانند seeWhosFastest() — کلاس شیء برگرداندهشده باید یک زیرکلاس (Subclass) از نوع خروجی باشد یا دقیقاً همان کلاس باشد. فرض کنید سلسلهمراتب کلاسی زیر وجود دارد که در آن ImaginaryNumber زیرکلاسی از java.lang.Number است و Number نیز به نوبهٔ خود زیرکلاسی از Object است، همانطور که در شکل زیر نشان داده شده است.
[تصویر: سلسلهمراتب کلاسی — Object ← Number ← ImaginaryNumber]
حالا فرض کنید Methodای دارید که نوع خروجی Number دارد:
public Number returnANumber() {
...
}
Method returnANumber() میتواند یک ImaginaryNumber برگرداند اما Object برنمیگرداند. یک نمونهٔ ImaginaryNumber همچنین یک نمونهٔ Number نیز هست، چون ImaginaryNumber زیرکلاس Number است. اما یک Object لزوماً Number نیست — ممکن است String یا نوع دیگری باشد.
میتوانید Method را Override کنید و تعریف کنید که زیرکلاسی از نوع اصلی برگرداند، مانند:
public ImaginaryNumber returnANumber() {
...
}
این تکنیک Covariant Return Type (نوع خروجی همجهت) نام دارد — یعنی نوع خروجی اجازه دارد در همان جهت زیرکلاس تغییر کند.
نکته: همچنین میتوانید نام Interface را بهعنوان نوع خروجی استفاده کنید. در این صورت، شیء برگرداندهشده باید Interface مشخصشده را پیادهسازی کرده باشد.---
در داخل یک Method Instance یا Constructor، this مرجعی به شیء فعلی است — یعنی شیئی که Method یا Constructor آن فراخوانی شده است. میتوانید با استفاده از this به هر عضوی از شیء فعلی ارجاع دهید.
رایجترین دلیل استفاده از کلمهٔ کلیدی this زمانی است که یک فیلد توسط پارامتر Method یا Constructor سایهپوشانی (Shadow) شده باشد.
برای مثال، کلاس Point به این شکل نوشته شده است:
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {
x = a;
y = b;
}
}
اما میتوانست به این شکل نیز نوشته شود:
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
هر آرگومان Constructor، یکی از فیلدهای شیء را سایهپوشانی میکند — داخل Constructor، x یک کپی محلی از آرگومان اول Constructor است. برای ارجاع به فیلد x کلاس Point، Constructor باید از this.x استفاده کند.
از داخل Constructor نیز میتوانید با استفاده از کلمهٔ کلیدی this Constructor دیگری در همان کلاس را فراخوانی کنید. به این کار فراخوانی صریح Constructor (Explicit Constructor Invocation) گفته میشود. در اینجا کلاس Rectangle دیگری با پیادهسازی متفاوت از آنچه در بخش اشیا دیدید آورده شده است.
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(0, 0, 1, 1);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
...
}
این کلاس شامل مجموعهای از Constructorهاست. هر Constructor بعضی یا همهٔ متغیرهای عضو مستطیل را مقداردهی اولیه میکند. Constructorها مقدار پیشفرضی برای هر متغیر عضوی که مقدار اولیهاش از آرگومان فراهم نشده تعیین میکنند. برای مثال، Constructor بدون پارامتر یک مستطیل 1×1 در مختصات (0,0) ایجاد میکند. Constructor دوپارامتری، Constructor چهارپارامتری را با عرض و ارتفاع دریافتی فراخوانی میکند و همیشه مختصات (0,0) را استفاده میکند. مانند قبل، کامپایلر بر اساس تعداد و نوع آرگومانها تشخیص میدهد کدام Constructor را فراخوانی کند.
نکته (JDK 25+): تا JDK 25، فراخوانی Constructor دیگر باید خط اول در Constructor باشد. از JDK 25 به بعد میتوانید کدهایی قبل از فراخوانی Constructor دیگر اضافه کنید، اما این کدها محدودیتهایی دارند. تمام کد قبل از فراخوانی Constructor دیگر، Prologue Constructor نامیده میشود. نمیتوانید از Instance تحت ساخت در این Prologue استفاده کنید مگر آنکه در حال مقداردهی اولیهٔ یک فیلد Instance باشید. اما نمیتوانید هیچ Method Instanceای را فراخوانی کنید.---
Modifierهای سطح دسترسی مشخص میکنند که آیا کلاسهای دیگر میتوانند از یک فیلد خاص استفاده کنند یا Method خاصی را فراخوانی کنند. دو سطح کنترل دسترسی وجود دارد:
public، یا Package-Private (بدون Modifier صریح).public، private، protected، یا Package-Private (بدون Modifier صریح).یک کلاس میتواند با Modifier public تعریف شود، که در این صورت آن کلاس برای تمام کلاسها در همهٔ جاها قابل مشاهده است. اگر کلاسی Modifier نداشته باشد (حالت پیشفرض، معروف به Package-Private)، فقط در داخل Package خودش قابل مشاهده است. (Packageها گروههای نامگذاریشده از کلاسهای مرتبط هستند — در بخش بعدی با آنها آشنا خواهید شد.)
در سطح عضو نیز میتوانید از Modifier public یا بدون Modifier (Package-Private) استفاده کنید، دقیقاً مانند کلاسهای سطح بالاتر و با همان معنا. برای اعضای کلاس، دو Modifier دسترسی اضافی وجود دارد: private و protected.
private مشخص میکند که عضو فقط در داخل خود کلاس قابل دسترسی است.protected مشخص میکند که عضو در داخل Package خودش (مانند Package-Private) و علاوه بر آن، توسط زیرکلاسی از کلاسش در Package دیگر قابل دسترسی است.جدول زیر دسترسی به اعضای مجاز توسط هر Modifier را نشان میدهد:
| Modifier | کلاس | Package | زیرکلاس | جهان |
|---|---|---|---|---|
public | بله | بله | بله | بله |
protected | بله | بله | بله | خیر |
| بدون Modifier | بله | بله | خیر | خیر |
private | بله | خیر | خیر | خیر |
ستون اول داده نشان میدهد که خود کلاس به عضو تعریفشده توسط سطح دسترسی دسترسی دارد. همانطور که میبینید، یک کلاس همیشه به اعضای خودش دسترسی دارد.
ستون دوم نشان میدهد که کلاسهای در یک Package با کلاس (صرفنظر از والدشان) به عضو دسترسی دارند.
ستون سوم نشان میدهد که زیرکلاسهای کلاس که خارج از این Package تعریف شدهاند به عضو دسترسی دارند.
ستون چهارم نشان میدهد که تمام کلاسها به عضو دسترسی دارند.
سطوح دسترسی به دو شکل بر شما تأثیر میگذارند. اول، هنگام استفاده از کلاسهایی که از منبع دیگری میآیند (مانند کلاسهای پلتفرم جاوا)، سطوح دسترسی مشخص میکنند کدام اعضای آن کلاسها توسط کلاسهای خودتان قابل دسترسی هستند. دوم، هنگام نوشتن یک کلاس، باید تصمیم بگیرید هر متغیر عضو و هر Method در کلاستان چه سطح دسترسیای داشته باشد.
اگر برنامهنویسان دیگر از کلاس شما استفاده کنند، میخواهید مطمئن شوید خطاهای ناشی از استفادهٔ نادرست رخ نمیدهد. سطوح دسترسی میتوانند در این کار کمکتان کنند.
از محدودترین سطح دسترسی معقول برای هر عضو خاص استفاده کنید. مگر دلیل خوبی داشته باشید، private استفاده کنید.
از فیلدهای public به جای ثابتها (Constants) اجتناب کنید. بسیاری از مثالها در این آموزش از فیلدهای public استفاده میکنند. این ممکن است برای نمایش مختصر برخی نکات مفید باشد، اما برای کد تولیدی توصیه نمیشود. این یک تمرین خوب نیست چون فیلدهای public تمایل دارند شما را به پیادهسازی خاصی ببندند و انعطافپذیریتان را در تغییر کد محدود کنند.
توجه کنید که Java Module System میتواند لایهٔ کنترلی دیگری برای قابلیت مشاهدهٔ کلاسهای public از خارج Module خودشان اضافه کند. میتوانید بخش Java Module System را برای اطلاعات بیشتر مراجعه کنید.
همچنین توجه کنید که Reflection API میتواند تحت شرایط خاصی دسترسی به کلاسها یا اعضای کلاس غیرقابل مشاهده را فراهم کند. میتوانید بخش Reflection API را برای اطلاعات بیشتر مراجعه کنید.
---در این بخش، استفاده از کلمهٔ کلیدی static برای ایجاد فیلدها و Methodهایی که به کلاس تعلق دارند (نه به یک نمونه از کلاس) بررسی میشود.
وقتی تعدادی شیء از یک نقشهٔ کلاس ایجاد میشوند، هرکدام نسخهٔ مستقل خود را از متغیرهای Instance دارند. در مورد کلاس Bicycle، متغیرهای Instance شامل cadence، gear و speed هستند. هر شیء Bicycle مقادیر خود را برای این متغیرها دارد که در مکانهای متفاوت حافظه ذخیره میشوند.
گاهی میخواهید متغیرهایی مشترک بین تمام اشیا داشته باشید. این کار با Modifier static انجام میشود. فیلدهایی که در اعلامیهٔ خود Modifier static دارند، static fields یا متغیرهای کلاس (Class Variables) نامیده میشوند. این فیلدها به کلاس تعلق دارند، نه به هیچ شیء خاصی.
هر نمونه از کلاس یک متغیر کلاس مشترک دارد که در یک مکان ثابت در حافظه قرار دارد. هر شیء میتواند مقدار متغیر کلاس را تغییر دهد. متغیرهای کلاس همچنین بدون ایجاد نمونه از کلاس قابل دسترسی و تغییر هستند.
برای مثال، فرض کنید میخواهید تعدادی شیء Bicycle ایجاد کنید و به هرکدام یک شمارهٔ سریال اختصاص دهید، از ۱ شروع شود. شمارهٔ ID منحصربهفرد هر شیء است و بنابراین یک متغیر Instance محسوب میشود. در عین حال، به فیلدی نیاز دارید که تعداد Bicycleهای ایجادشده را ردیابی کند تا بدانید شمارهٔ ID بعدی چه عددی باشد. چنین فیلدی به هیچ شیء خاصی مربوط نیست، بلکه به کلاس بهطور کلی مربوط است. برای این کار به یک متغیر کلاس به نام numberOfBicycles نیاز دارید، به این شکل:
public class Bicycle {
private int cadence;
private int gear;
private int speed;
// اضافهکردن متغیر Instance برای شناسهٔ شیء
private int id;
// اضافهکردن متغیر کلاس برای
// تعداد اشیای Bicycle ایجادشده
private static int numberOfBicycles = 0;
...
}
متغیرهای کلاس از طریق نام خود کلاس مورد ارجاع قرار میگیرند، مانند:
Bicycle.numberOfBicycles
این مشخص میکند که آنها متغیرهای کلاس هستند.
نکته: میتوانید به فیلدهای Static از طریق مرجع شیء نیز ارجاع دهید، مانند myBike.numberOfBicycles، اما این کار توصیه نمیشود چون مشخص نیست که آنها متغیرهای کلاس هستند.
میتوانید از Constructor کلاس Bicycle برای تنظیم متغیر Instance ID و افزایش متغیر کلاس numberOfBicycles استفاده کنید:
public class Bicycle {
private int cadence;
private int gear;
private int speed;
private int id;
private static int numberOfBicycles = 0;
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
// افزایش تعداد Bicycleها
// و اختصاص شمارهٔ ID
id = ++numberOfBicycles;
}
// Method جدید برای برگرداندن متغیر Instance id
public int getID() {
return id;
}
...
}
زبان برنامهنویسی جاوا علاوه بر متغیرهای Static از Methodهای Static نیز پشتیبانی میکند. Methodهای Static که در اعلامیهشان Modifier static دارند، باید با نام کلاس فراخوانی شوند، بدون نیاز به ایجاد نمونه از کلاس، مانند:
ClassName.methodName(args)
نکته: میتوانید به Methodهای Static از طریق مرجع شیء نیز ارجاع دهید، مانند instanceName.methodName(args)، اما این کار توصیه نمیشود چون مشخص نیست که آنها Methodهای کلاس هستند.
کاربرد رایج Methodهای Static، دسترسی به فیلدهای Static است. برای مثال، میتوانیم یک Method Static به کلاس Bicycle اضافه کنیم تا به فیلد Static numberOfBicycles دسترسی داشته باشد:
public static int getNumberOfBicycles() {
return numberOfBicycles;
}
ترکیبهای اعضای Instance و کلاس و Methodها که مجاز نیستند عبارتند از:
this استفاده کنند، چون Instanceای وجود ندارد که this به آن ارجاع دهد.ترکیب Modifier static با Modifier final برای تعریف ثابتها نیز استفاده میشود. Modifier final نشان میدهد مقدار این فیلد تغییر نمیکند.
برای مثال، اعلامیهٔ متغیر زیر ثابتی به نام PI تعریف میکند که مقدارش تقریبی عدد پی (نسبت محیط دایره به قطرش) است:
static final double PI = 3.141592653589793;
ثابتهایی که به این شکل تعریف شدهاند قابل تغییر مجدد نیستند و اگر برنامه سعی در انجام این کار داشته باشد، خطای کامپایل رخ میدهد. طبق قرارداد، نام مقادیر ثابت با حروف بزرگ نوشته میشود. اگر نام از بیش از یک کلمه تشکیل شده باشد، کلمات با یک زیرخط (_) از هم جدا میشوند.
نکته: اگر نوع Primitive یا String بهعنوان ثابت تعریف شده باشد و مقدارش در زمان کامپایل مشخص باشد، کامپایلر نام ثابت را در تمام نقاط کد با مقدارش جایگزین میکند. به این Compile-Time Constant گفته میشود. اگر مقدار ثابت در دنیای بیرون تغییر کند (مثلاً اگر قانوناً تصویب شود که عدد پی در واقع باید ۳.۹۷۵ باشد)، باید تمام کلاسهایی که از این ثابت استفاده میکنند را مجدداً کامپایل کنید تا مقدار فعلی را دریافت کنید.
پس از تمام تغییرات این بخش، کلاس Bicycle اکنون به این شکل است:
public class Bicycle {
private int cadence;
private int gear;
private int speed;
private int id;
private static int numberOfBicycles = 0;
public Bicycle(int startCadence,
int startSpeed,
int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
id = ++numberOfBicycles;
}
public int getID() {
return id;
}
public static int getNumberOfBicycles() {
return numberOfBicycles;
}
public int getCadence() {
return cadence;
}
public void setCadence(int newValue) {
cadence = newValue;
}
public int getGear() {
return gear;
}
public void setGear(int newValue) {
gear = newValue;
}
public int getSpeed() {
return speed;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
---
همانطور که دیدید، اغلب میتوانید مقدار اولیهٔ فیلد را مستقیماً در اعلامیهاش فراهم کنید:
public class BedAndBreakfast {
// مقداردهی اولیه به ۱۰
public static int capacity = 10;
// مقداردهی اولیه به false
private boolean full = false;
}
این روش زمانی خوب عمل میکند که مقدار اولیه در دسترس باشد و بتوان آن را در یک خط نوشت. اما این شکل سادهٔ مقداردهی اولیه به دلیل سادگیاش محدودیتهایی دارد. اگر مقداردهی اولیه به منطق خاصی نیاز داشته باشد (مثلاً مدیریت خطا یا حلقهٔ for برای پرکردن آرایهای پیچیده)، تخصیص ساده کافی نیست. متغیرهای Instance میتوانند در Constructorها مقداردهی اولیه شوند، جایی که مدیریت خطا یا منطق دیگر قابل استفاده است. برای فراهمکردن همین قابلیت برای متغیرهای کلاس، زبان برنامهنویسی جاوا بلوکهای مقداردهی اولیهٔ Static (Static Initialization Blocks) را شامل میشود.
نکته: لازم نیست فیلدها را در ابتدای تعریف کلاس اعلام کنید، اگرچه این رایجترین تمرین است. فقط لازم است قبل از استفاده اعلام و مقداردهی اولیه شده باشند.
یک بلوک مقداردهی اولیهٔ Static یک بلوک کد عادی داخل براکتها { } است که با کلمهٔ کلیدی static شروع میشود. در اینجا یک مثال آورده شده است:
static {
// هر کدی که برای مقداردهی اولیه لازم است اینجا قرار میگیرد
}
یک کلاس میتواند هر تعداد بلوک مقداردهی اولیهٔ Static داشته باشد و در هر جایی از بدنهٔ کلاس ظاهر شوند. سیستم اجرایی تضمین میکند که بلوکهای مقداردهی اولیهٔ Static به ترتیب ظاهرشان در کد منبع فراخوانی شوند.
جایگزینی برای بلوکهای Static وجود دارد — میتوانید یک Method private static بنویسید:
class Whatever {
public static varType myVar = initializeClassVariable();
private static varType initializeClassVariable() {
// کد مقداردهی اولیه اینجا قرار میگیرد
}
}
مزیت Methodهای private static این است که در صورت نیاز به مقداردهی مجدد متغیر کلاس، میتوان آنها را بازاستفاده کرد.
باید توجه داشته باشید که نمیتوانید محتوای یک بلوک Static را تعریف مجدد کنید. پس از نوشتن، نمیتوانید مانع اجرای این بلوک شوید. اگر محتوای بلوک Static به هر دلیلی قابل اجرا نباشد، برنامهتان به درستی کار نخواهد کرد، چون قادر به ایجاد نمونه از این کلاس نخواهید بود. این ممکن است زمانی اتفاق بیفتد که بلوک Static حاوی کدی باشد که به منبع خارجی مانند فایلسیستم یا شبکه دسترسی دارد.
بهطور معمول، کد مقداردهی اولیهٔ متغیر Instance را در Constructor قرار میدهید. دو جایگزین برای استفاده از Constructor وجود دارد: بلوکهای Initializer و Methodهای Final.
بلوکهای Initializer برای متغیرهای Instance دقیقاً شبیه بلوکهای مقداردهی اولیهٔ Static هستند، اما بدون کلمهٔ کلیدی static:
{
// هر کدی که برای مقداردهی اولیه لازم است اینجا قرار میگیرد
}
کامپایلر جاوا بلوکهای Initializer را در هر Constructor کپی میکند. بنابراین این روش میتواند برای اشتراکگذاری یک بلوک کد بین Constructorهای متعدد استفاده شود.
یک Method Final نمیتواند در زیرکلاس Override شود. این موضوع در بخش Inheritance بررسی خواهد شد. در اینجا مثالی از استفاده از Method Final برای مقداردهی اولیهٔ متغیر Instance آورده شده است:
class Whatever {
private varType myVar = initializeInstanceVariable();
protected final varType initializeInstanceVariable() {
// کد مقداردهی اولیه اینجا قرار میگیرد
}
}
این روش بهویژه زمانی مفید است که زیرکلاسها بخواهند Method مقداردهی اولیه را بازاستفاده کنند. Method به final تعریف شده، چون فراخوانی Methodهای non-final در حین مقداردهی اولیهٔ Instance میتواند مشکلساز باشد.
اعلامیهٔ کلاس نام کلاس را مشخص و بدنهٔ کلاس را بین براکتها محصور میکند. نام کلاس میتواند قبل از Modifierها بیاید. بدنهٔ کلاس شامل فیلدها، Methodها و Constructorها برای کلاس است. کلاس از فیلدها برای نگهداری اطلاعات وضعیت و از Methodها برای پیادهسازی رفتار استفاده میکند. Constructorهایی که نمونهٔ جدیدی از کلاس را مقداردهی اولیه میکنند، نام کلاس را دارند و شبیه Methodهایی بدون نوع خروجی هستند.
دسترسی به کلاسها و اعضایشان را به یک شکل کنترل میکنید: با استفاده از یک Modifier دسترسی مانند public در اعلامیهشان.
یک متغیر کلاس یا Method کلاس را با استفاده از کلمهٔ کلیدی static در اعلامیهٔ عضو مشخص میکنید. عضوی که به عنوان static تعریف نشده باشد، بهطور ضمنی یک عضو Instance است. متغیرهای کلاس توسط تمام نمونههای کلاس مشترک هستند و از طریق نام کلاس و همچنین مرجع Instance قابل دسترسیاند. نمونههای کلاس نسخهٔ مستقل خود را از هر متغیر Instance دارند که فقط از طریق مرجع Instance قابل دسترسی است.
شیء را از کلاس با استفاده از عملگر new و Constructor ایجاد میکنید. عملگر new مرجعی به شیء ایجادشده برمیگرداند. میتوانید مرجع را به متغیری اختصاص دهید یا مستقیماً از آن استفاده کنید.
فیلدها و Methodهای Instance که در کد خارج از کلاسی که در آن اعلام شدهاند قابل دسترسی هستند، میتوانند با استفاده از نام واجد (Qualified Name) مورد ارجاع قرار بگیرند. نام واجد یک متغیر Instance به این شکل است:
objectReference.variableName
نام واجد Method به این شکل است:
objectReference.methodName(argumentList)
یا:
objectReference.methodName()
Garbage Collector بهطور خودکار اشیای استفادهنشده را پاکسازی میکند. شیئی استفادهنشده محسوب میشود که برنامه دیگر مرجعی به آن نداشته باشد. میتوانید بهصورت صریح مرجعی را با اختصاص null به متغیر نگهدارندهٔ مرجع حذف کنید.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://dev.java/learn/