یاد بگیرید که چگونه از حاشیه نویسی جاوا برای مرتبط کردن ابرداده با کلاس ها، روش ها و سایر عناصر برنامه در برنامه های جاوا استفاده کنید.
مواقعی وجود دارد که شما نیاز دارید فراداده یا دادههایی را که دادهها را توصیف میکنند، با کلاسها، متدها یا عناصر دیگر در کد جاوا خود مرتبط کنید. برای مثال، تیم شما ممکن است نیاز به شناسایی کلاس های ناتمام در یک برنامه بزرگ داشته باشد. برای هر کلاس ناتمام، فراداده شامل نام توسعهدهنده مسئول تکمیل کلاس و تاریخ تکمیل مورد انتظار کلاس است.
قبل از جاوا ۵، نظرات تنها مکانیزم منعطف جاوا برای مرتبط کردن ابرداده با عناصر برنامه بود. اما چون کامپایلر آنها را نادیده می گیرد، نظرات در زمان اجرا در دسترس نیستند. و حتی اگر آنها در دسترس بودند، باید متن را تجزیه کنید تا موارد داده مهم را به دست آورید. بدون استاندارد کردن نحوه تعیین اقلام داده، ممکن است تجزیه آنها غیرممکن باشد.
جاوا ۵ با معرفی حاشیه نویسی، مکانیزم استانداردی برای مرتبط کردن ابرداده با عناصر مختلف برنامه، همه چیز را تغییر داد. این آموزش شما را با حاشیه نویسی جاوا آشنا می کند.
آنچه در این آموزش جاوا خواهید آموخت
- چهار عنصر حاشیه نویسی جاوا
- استفاده از
@interface
برای اعلام انواع حاشیه نویسی - انواع متا حاشیه نویسی و مشکل انعطاف پذیری
- نحوه پردازش حاشیه نویسی
- انواع حاشیه نویسی از پیش تعریف شده جاوا
عناصر حاشیه نویسی جاوا
یک حاشیه نویسی در جاوا از چهار عنصر تشکیل شده است:
- یک مکانیسم
@interface
برای اعلام انواع حاشیه نویسی. - انواع متا حاشیه نویسی، که می توانید برای شناسایی عناصر برنامه کاربردی که یک نوع حاشیه نویسی روی آنها اعمال می شود، شناسایی طول عمر حاشیه (نمونه ای از یک نوع حاشیه نویسی) و موارد دیگر استفاده کنید. li>
- پشتیبانی از پردازش حاشیه نویسی از طریق یک برنامه افزودنی به Java Reflection API و یک ابزار عمومی برای پردازش حاشیه نویسی.
- انواع حاشیه نویسی استاندارد (از پیش تعریف شده) جاوا.
میآموزید که چگونه از هر یک از این عناصر در حاشیهنویسیهای جاوا خود استفاده کنید.
استفاده از @interface برای اعلام انواع حاشیه نویسی
می توانید با مشخص کردن نماد @
بلافاصله پس از آن کلمه رزرو شده interface
و یک شناسه، نوع حاشیه نویسی را اعلام کنید. به عنوان مثال، فهرست ۱ یک نوع حاشیه نویسی ساده را اعلام می کند که ممکن است از آن برای حاشیه نویسی کد ایمن رشته استفاده کنید.
public @interface ThreadSafe
{
}
پس از اعلام این نوع حاشیه نویسی، با افزودن نماد @
و به دنبال آن نام نوع به سربرگ های روش، پیشوند روش هایی را که برای رشته ای ایمن در نظر می گرفتید با نمونه هایی از این نوع قرار دهید.
>
فهرست ۲ مثال ساده ای را نشان می دهد که در آن روش main()
به صورت @ThreadSafe
حاشیه نویسی شده است.
public class AnnDemo
{
@ThreadSafe
public static void main(String[] args)
{
}
}
نمونه های
ThreadSafe
هیچ فراداده ای به جز نام نوع حاشیه نویسی ارائه نمی دهند. با این حال، میتوانید ابردادهها را با افزودن عناصر به این نوع، که در آن یک element سرصفحه روشی است که در بدنه نوع حاشیهنویسی قرار داده شده است، ارائه دهید.
علاوه بر نداشتن متن کد، عناصر مشمول محدودیتهای زیر نیز هستند:
- سرصفحه روش نمی تواند پارامترها را اعلام کند.
- سرصفحه روش نمیتواند یک بند پرتاب ارائه کند.
- نوع برگشتی هدر روش باید یک نوع اولیه باشد (به عنوان مثال،
int
)،java.lang.String
،java.lang.Class
، یک enum، یک نوع حاشیه نویسی، یا آرایه ای از یکی از این انواع. هیچ نوع دیگری را نمی توان برای نوع برگشتی تعیین کرد.
به عنوان مثالی دیگر، لیست ۳ یک نوع حاشیه نویسی ToDo
را با سه عنصر برای شناسایی یک کار کدگذاری خاص، مشخص کردن تاریخ اتمام کار و نامگذاری رمزگذار مسئول تکمیل کار ارائه می کند. .
public @interface ToDo
{
int id();
String finishDate();
String coder() default "n/a";
}
توجه داشته باشید که هر عنصر هیچ پارامتر(ها) یا بند پرتابی را اعلام نمی کند، دارای یک نوع بازگشتی قانونی است (int
یا String
)، و با یک نقطه ویرگول خاتمه می یابد. همچنین، عنصر نهایی نشان می دهد که یک مقدار بازگشتی پیش فرض می تواند مشخص شود. هنگامی که یک حاشیه نویسی مقداری را به عنصر اختصاص نمی دهد، این مقدار برگردانده می شود.
فهرست ۴ از ToDo
برای حاشیه نویسی روش کلاس ناتمام استفاده می کند.
public class AnnDemo
{
public static void main(String[] args)
{
String[] cities = { "New York", "Melbourne", "Beijing", "Moscow",
"Paris", "London" };
sort(cities);
}
@ToDo(id = 1000, finishDate = "10/10/2019", coder = "John Doe")
static void sort(Object[] objects)
{
}
}
فهرست ۴ یک مورد فراداده را به هر عنصر اختصاص می دهد. برای مثال، ۱۰۰۰
به id
اختصاص داده شده است. برخلاف coder
، عناصر id
و finishDate
باید مشخص شوند. در غیر این صورت، کامپایلر یک خطا را گزارش خواهد کرد. وقتی به coder
مقداری اختصاص داده نمیشود، مقدار پیشفرض "n/a"
را در نظر میگیرد.
جاوا یک عنصر String value()
ویژه ارائه میکند که میتواند برای برگرداندن فهرستی از موارد فوق داده با کاما از هم استفاده شود. فهرست ۵ این عنصر را در نسخه بازسازی شده ToDo
نشان می دهد.
public @interface ToDo
{
String value();
}
وقتی value()
تنها عنصر یک نوع حاشیه نویسی است، لازم نیست هنگام تخصیص value
و عملگر تخصیص =
را مشخص کنید. یک رشته به این عنصر فهرست ۶ هر دو رویکرد را نشان می دهد.
public class AnnDemo
{
public static void main(String[] args)
{
String[] cities = { "New York", "Melbourne", "Beijing", "Moscow",
"Paris", "London" };
sort(cities);
}
@ToDo(value = "1000,10/10/2019,John Doe")
static void sort(Object[] objects)
{
}
@ToDo("1000,10/10/2019,John Doe")
static boolean search(Object[] objects, Object key)
{
return false;
}
}
انواع متا حاشیه نویسی و مشکل انعطاف پذیری
می توانید انواع (مانند کلاس ها)، روش ها، متغیرهای محلی و موارد دیگر را حاشیه نویسی کنید. با این حال، این انعطاف پذیری می تواند مشکل ساز باشد. برای مثال، ممکن است بخواهید ToDo
را فقط به روشها محدود کنید، اما هیچ چیز مانع از استفاده آن برای حاشیهنویسی سایر عناصر برنامه نمیشود، همانطور که در فهرست ۷ نشان داده شده است.
@ToDo("1000,10/10/2019,John Doe")
public class AnnDemo
{
public static void main(String[] args)
{
@ToDo(value = "1000,10/10/2019,John Doe")
String[] cities = { "New York", "Melbourne", "Beijing", "Moscow",
"Paris", "London" };
sort(cities);
}
@ToDo(value = "1000,10/10/2019,John Doe")
static void sort(Object[] objects)
{
}
@ToDo("1000,10/10/2019,John Doe")
static boolean search(Object[] objects, Object key)
{
return false;
}
}
در فهرست ۷، ToDo
همچنین برای حاشیه نویسی کلاس AnnDemo
و متغیر محلی cities
استفاده می شود. وجود این حاشیهنویسیهای اشتباه ممکن است کسی را که کد شما یا حتی ابزارهای پردازش حاشیهنویسی شما را بررسی میکند سردرگم کند. برای مواقعی که باید انعطافپذیری نوع حاشیهنویسی را محدود کنید، جاوا نوع حاشیهنویسی Target
را در بسته java.lang.annotation
خود ارائه میکند.
هدف
یک نوع متا حاشیه نویسی است—یک نوع حاشیه نویسی برای انواع حاشیه نویسی. این با یک نوع غیر متا حاشیه نویسی متفاوت است، که حاشیه نویسی آن عناصر کاربردی مانند کلاس ها و روش ها را حاشیه نویسی می کند. نوع حاشیه نویسی Target
انواع عناصر برنامه کاربردی را مشخص می کند که یک نوع حاشیه نویسی برای آنها قابل اعمال است. این عناصر با عنصر ElementValue[] value()
Target
شناسایی می شوند.
java.lang.annotation.ElementType
یک عدد است که ثابت های آن عناصر برنامه را توصیف می کنند. برای مثال، CONSTRUCTOR
برای سازنده ها و PARAMETER
برای پارامترها اعمال می شود. فهرست کردن ۸ refactors فهرست کردن نوع حاشیه نویسی ToDo
۵ تا فقط به روشها محدود شود.
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
public @interface ToDo
{
String value();
}
با توجه به نوع حاشیه نویسی اصلاح شده ToDo
، تلاش برای کامپایل لیست ۷ اکنون به پیام خطای زیر منجر می شود:
AnnDemo.java:1: error: annotation type not applicable to this kind of declaration
@ToDo("1000,10/10/2019,John Doe")
^
AnnDemo.java:6: error: annotation type not applicable to this kind of declaration
@ToDo(value="1000,10/10/2019,John Doe")
^
۲ errors
انواع meta-annotation اضافی
جاوا ۵ سه نوع مهم متا حاشیه نویسی را معرفی کرد که در بسته java.lang.annotation
یافت می شوند:
حفظ
نشان می دهد که حاشیه نویسی با نوع حاشیه نویسی چه مدت باید حفظ شود. enumjava.lang.annotation.RetentionPolicy
مرتبط با این نوع، ثابت های زیر را اعلام می کند:CLASS
: کامپایلر حاشیه نویسی ها را در یک فایل کلاس ثبت می کند و ماشین مجازی آنها را حفظ نمی کند. این خط مشی پیش فرض استRUNTIME
: کامپایلر حاشیه نویسی ها را در یک فایل کلاس ثبت می کند و ماشین مجازی آنها را حفظ می کند.SOURCE
: کامپایلر حاشیه نویسی را کنار می گذارد.
مستند شده
نشان میدهد که نمونههایی از حاشیهنویسیهایمستند شده
باید توسطjavadoc
و ابزارهای مشابه مستند شوند.ارثی
نشان می دهد که یک نوع حاشیه نویسی به طور خودکار به ارث می رسد.
CLASS
: کامپایلر حاشیه نویسی ها را در یک فایل کلاس ثبت می کند و ماشین مجازی آنها را حفظ نمی کند. این خط مشی پیش فرض استRUNTIME
: کامپایلر حاشیه نویسی ها را در یک فایل کلاس ثبت می کند و ماشین مجازی آنها را حفظ می کند.SOURCE
: کامپایلر حاشیه نویسی را کنار می گذارد.
یک نوع متا حاشیه نویسی دیگر که در جاوا ۸ معرفی شده است، java.lang.annotation.Repeatable
است. Repeatable
برای نشان دادن اینکه نوع حاشیه نویسی که اعلان آن (meta-) حاشیه نویسی می کند، قابل تکرار است استفاده می شود. به عبارت دیگر، همانطور که در اینجا نشان داده شده است، می توانید چندین حاشیه نویسی را از یک نوع حاشیه نویسی تکرارپذیر به یک عنصر برنامه اعمال کنید:
@ToDo(value = "1000,10/10/2019,John Doe")
@ToDo(value = "1001,10/10/2019,Kate Doe")
static void sort(Object[] objects)
{
}
این مثال فرض می کند که ToDo
با نوع حاشیه نویسی Repeatable
حاشیه نویسی شده است.
نحوه پردازش حاشیه نویسی
حاشیه نویسی باید پردازش شود. در غیر این صورت، داشتن آنها فایده ای ندارد. جاوا ۵ Java Reflection API را گسترش داد تا به شما کمک کند ابزارهای پردازش حاشیه نویسی خود را ایجاد کنید. برای مثال، Class
یک Annotation[]
که آرایه ای از نمونه های
متد getAnnotations()java.lang.Annotation
را برمی گرداند. این نمونه ها حاشیه نویسی های موجود در عنصر توصیف شده توسط شی Class
را توصیف می کنند.
فهرست ۹ یک برنامه کاربردی ساده را ارائه میکند که یک فایل کلاس را بارگیری میکند، روشهای آن را برای حاشیهنویسیهای ToDo
بازجویی میکند، و اجزای هر حاشیهنویسی یافت شده را خروجی میدهد.
import java.lang.reflect.Method;
public class AnnProcDemo
{
public static void main(String[] args) throws Exception
{
if (args.length != 1)
{
System.err.println("usage: java AnnProcDemo classfile");
return;
}
Method[] methods = Class.forName(args[0]).getMethods();
for (int i = 0; i < methods.length; i++)
{
if (methods[i].isAnnotationPresent(ToDo.class))
{
ToDo todo = methods[i].getAnnotation(ToDo.class);
String[] components = todo.value().split(",");
System.out.printf("ID = %s%n", components[0]);
System.out.printf("Finish date = %s%n", components[1]);
System.out.printf("Coder = %s%n%n", components[2]);
}
}
}
}
پس از تأیید اینکه دقیقاً یک آرگومان خط فرمان (شناسایی یک فایل کلاس) مشخص شده است، main()
فایل کلاس را از طریق Class.forName()
بارگیری می کند، getMethods()
را فراخوانی می کند تا آرایه ای از اشیاء java.lang.reflect.Method
را که همه متدهای public
را در فایل کلاس شناسایی می کند، برگرداند و اینها را پردازش می کند. روش ها.
پردازش روش با فراخوانی روش
boolean isAnnotationPresent(Class extensions) آغاز می شود
روش Annotation> annotationClass)
برای تعیین اینکه آیا حاشیه نویسی توصیف شده توسط ToDo.class
در روش وجود دارد یا خیر. اگر چنین است، روش
برای به دست آوردن حاشیه نویسی فراخوانی می شود.
روش annotationClass)
یادداشتهای ToDo
که پردازش میشوند، آنهایی هستند که انواع آنها یک عنصر String value()
را اعلام میکنند (به فهرست ۵ مراجعه کنید). از آنجا که ابرداده مبتنی بر رشته این عنصر با کاما از هم جدا شده است، باید به آرایه ای از مقادیر مؤلفه تقسیم شود. سپس به هر یک از سه مقدار مؤلفه دسترسی یافته و خروجی می شود.
این کد منبع (javac AnnProcDemo.java
) را کامپایل کنید. قبل از اینکه بتوانید برنامه را اجرا کنید، به یک فایل کلاس مناسب با حاشیه نویسی @ToDo
در روش های public
آن نیاز دارید. برای مثال، میتوانید کد منبع فهرست ۶ AnnDemo
را تغییر دهید تا public
را در sort()
و search()
سرصفحه های روش. همچنین به نوع حاشیه نویسی ToDo
Listing 10 نیاز دارید که به خط مشی حفظ RUNTIME
نیاز دارد:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ToDo
{
String value();
}
AnnDemo.java
و لیست ۱۰ تغییر یافته را کامپایل کنید و دستور زیر را برای پردازش حاشیه نویسی های AnnDemo
ToDo
اجرا کنید:
java AnnProcDemo AnnDemo
اگر همه چیز خوب پیش رفت، باید خروجی زیر را مشاهده کنید:
ID = 1000
Finish date = 10/10/2019
Coder = John Doe
ID = 1000
Finish date = 10/10/2019
Coder = John Doe
انواع حاشیه نویسی از پیش تعریف شده جاوا
جاوا ۵ همراه با انواع متا حاشیه نویسی هدف
، Retention
، مستند شده
و ارثی
معرفی شد. منسوخ شده
، لغو
و SuppressWarnings
به عنوان انواع حاشیه نویسی از پیش تعریف شده. این سه نوع حاشیه نویسی فقط برای استفاده در زمینه کامپایلر طراحی شده اند، بنابراین سیاست های حفظ آنها روی SOURCE
تنظیم شده است.
منسوخ شده
منسوخ شده
عناصر برنامه را که قرار است منسوخ شوند، حاشیه نویسی می کند، به این معنی که آنها به تدریج حذف خواهند شد و نباید استفاده شوند. هنگامی که یک عنصر منسوخ شده در دسترس باشد، کامپایلر به شما هشدار می دهد.
سازنده java.util.Date
زیر منسوخ شده
را نشان می دهد:
@Deprecated
public Date(int year, int month, int date, int hrs, int min)
{
// ... body of this constructor
}
جاوا ۹ یک جفت عنصر را در این نوع حاشیه نویسی معرفی کرد:
boolean forRemoval
: نشان می دهد که آیا عنصر حاشیه نویسی در نسخه بعدی حذف می شود یا خیر. مقدار پیش فرضنادرست
است.رشته از
: نسخهای را برمیگرداند که در آن عنصر حاشیهنویسی منسوخ شده است. رشته نسخه در قالب و فضای نامی با مقدار تگ@since
javadoc
است. مقدار پیش فرض رشته خالی است.
این عناصر برای هشدار به توسعهدهندگان استفاده میشوند که بخشهایی از APIهای استاندارد جاوا برای حذف در نسخه جاوای آینده برنامهریزی شدهاند و به ترتیب در حال حذف شدن هستند. به عنوان مثال، جاوا ۹ از عنصر since
برای شناسایی نسخه ای استفاده کرد که در آن java.io.FileInputStream
و java.io.FileOutputStream
‘ روشهای void finalize()
ابتدا منسوخ شدند:
@Deprecated(since="9")
protected void finalize() throws IOException
جاوا ۱۰ همچنین از عنصر forRemoval
استفاده کرد تا نشان دهد که این روشهای API در نسخه جاوا آینده حذف خواهند شد. این روش ها در جاوا ۱۲ حذف شدند:
@Deprecated(since="9",forRemoval=true)
protected void finalize() throws IOException
لغو
Override
روشهای زیر کلاسی را که همتایان سوپرکلاس خود را نادیده میگیرند، حاشیهنویسی میکند. هنگامی که متد subclass روش superclass را لغو نمیکند، کامپایلر یک خطا گزارش میکند.
مثال زیر Override
را نشان میدهد که در آن روش public void run()
رابط java.lang.Runnable
توسط یک کلاس ناشناس لغو میشود:
Runnable r = new Runnable()
{
@Override
public void run()
{
// ... body of this method
}
};
SuppressWarnings
SuppressWarnings
عناصر برنامه (و همه عناصر موجود در این عناصر برنامه) را که در آن هر یک از هشدارهای کامپایلر نامگذاری شده (به عنوان مثال، بررسی نشده
) باید سرکوب شود، حاشیهنویسی میکند.
مثال زیر از SuppressWarnings
برای سرکوب اخطار علامتنشده در زمینه بازیگران (E[])
استفاده میکند:
public class Container<E>
{
private E[] elements;
// ...
@SuppressWarnings("unchecked")
public Container(int size)
{
// ...
elements = (E[]) new Object[size];
}
// ...
}
بدون حاشیهنویسی @SuppressWarnings("علامتگذاری نشده")
، کامپایلر هشداری در مورد یک بازیگر انتخاب نشده ایجاد میکند. به طور خاص، (E[])
ارسال از Object[]
به E[]
.
ممکن است تعجب کنید که چرا به جای عبارت حاوی بازیگران، سازنده را حاشیه نویسی کردم. من این کار را انجام دادم زیرا جاوا اجازه اعمال حاشیه نویسی روی عبارات را نمی دهد.
شروع به کار با ژنریک در جاوا
نحوهای E[]
و
در مثال قبلی با ویژگی زبان عمومی در جاوا.
پست های مرتبط
نحوه توصیف کد جاوا با حاشیه نویسی
نحوه توصیف کد جاوا با حاشیه نویسی
نحوه توصیف کد جاوا با حاشیه نویسی