preloder
دانستنی‌ها

ده اشتباه رایج توسعه‌دهندگان جاوا

در این مطلب لیستی از ده اشتباهی که مکررا توسعه‌دهندگان جاوا مرتکب می‌شوند را مرور می‌کنیم:

۱. تبدیل آرایه به ArrayList

برای تبدیل آرایه به ArrayList توسعه دهندگان اغلب رویکرد زیر را دنبال می‌کنند.

Arrays.asList() یک ‌ArrayList برمی‌گرداند که یک کلاس استاتیک private درون Arrays است و java.util.ArrayList نیست. java.util.Arrays.ArrayList توابع set() و get() و contains() دارد اما هیچ متدی برای اضافه کردن المان ندارد و سایز آن ثابت است. برای ساختن یک ArrayList واقعی باید این کار را کرد:

۲. بررسی اینکه آیا یک آرایه یک مقدار دارد

توسعه‌دهندگان اغلب این چنین می‌کنند:

این کد کار می‌کند اما نیازی نیست که لیست را اول به set تبدیل کنید. تبدیل لیست به set زمان اضافی نیاز دارد. می‌تواند به سادگی زیر باشد:

یا

اولی از دومی خواناتر است.

۳. حذف یک المان از یک لیست درون حلقه

کد زیر را در نظر بگیرید که در تکرار حلقه المان‌های آن را حذف می‌کند.

خروجی به شکل زیر است:

یک مشکل جدی در این تابع وجود دارد. وقتی یک المان حذف می‌شود، سایز لیست کوچک می‌شود و اندیس تغییر می‌کند. بنابراین اگر بخواهید چند المان را با استفاده از اندیس درون حلقه حذف کنید، به درستی کار نخواهد کرد.

ممکن است  بدانید که استفاده از iterator برای حذف کار درستی است و می‌دانید که حلقه foreach در جاوا مثل iterator کار می‌کند اما این طور نیست کد زیر را در نظر بگیرید:

که خطای ConcurrentModificationException برمی‌گرداند.

اما کد زیر درست است:

.next باید قبل از .remove صدا زده شود. در حلقه foreach کامپایلر .next را بعد از حذف صدا می‌زند و منجر به خطا می‌شود. می‌توانید نگاهی به کد ArrayList.iterator بیندازید.

۴. Hashtable در مقابل HashMap

در واقع در تئوری الگوریتم‌ها، Hashtable نام یک داده ساختار است. اما در جاوا HashMap یک داده‌ساختار است. یکی از تفاوت‌های اصلی بین Hashtable و HashMap این است که Hashtable سنکرون است. به همین دلیل خیلی وقت‌ها نیازی به آن ندارید و HashMap باید استفاده شود.

۵. استفاده از نوع خام مجموعه‌ها

در جاوا نوع raw type و unbound wildcard type خیلی مواقع اشتباه گرفته می‌شوند. به عنوان مثال Set را در نظر بگیرید، Set یک داده خام است در حالیکه Set<?> یک داده unbound wildcard است.

کد زیر که از داده خام List به عنوان پارامتر استفاده می‌کند را در نظر بگیرید:

این کد خطای زیر را پرتاب می‌کند.

استفاده از مجموعه داده خام خطرناک است چرا که چک کردن عام نوع داده را انجام نداده و امن نیست. تفاوت‌های بسیاری بین Set، Set<?> و Set<Object> وجود دارد که در اینجا می‌توانید بررسی کنید.

۶. سطح دسترسی

توسعه‌دهندگان در بسیاری از موارد از public برای فیلد کلاس استفاده می‌کنند. دریافت مقدار فیلد با ارجاع مستقیم به آن خیلی ساده است اما یک طراحی بسیار بد است. یک قانون سرانگشتی این است که برای اعضا مینیمم سطح دسترسی را قائل شوید.

۷. ArrayList در مقابل LinkedList

وقتی توسعه‌دهندگان تفاوت بین ArrayList و LinkedList را نمی‌دانند، اغلب از ArrayList استفاده می‌کنند چرا که آشناتر به نظر می‌رسد. هرچند تفاوت کارایی چشمگیری بین آن‌ها وجود دارد. به طور خلاصه، LinkedList باید در صورتی که تعداد عملگرهای حذف/اضافه زیاد است و تعداد عملگرهای دسترسی تصادفی کم است، ترجیح داده شود. می‌توانید اینجا را برای مقایسه کارایی آنان نگاه کنید.

۸. Mutable در مقابل Immutable

اشیا Immutable مزایای زیادی مثل سادگی، امنیت و … دارند. اما برای هر مقدار مختلف آنان به یک شئ مجزا نیاز است و تعداد زیاد اشیاء می‌تواند هزینه زیادی برای زباله روبی ایجاد کند. به همین دلیل باید توازنی در انتخاب بین mutable و immutable وجود داشته باشد.

در حالت کلی اشیا mutable از تولید اشیا میانی اجتناب می‌کنند. یک مثال کلاسیک آن ترکیب تعداد زیادی رشته است. اگر شما از یک رشته immutable استفاده کنید، اشیا زیادی تولید می‌کنید که ممکن است فورا توسط زباله روب حذف شوند. این کار زمان و انرژی زیادی از CPU می‌گیرد، راه حل درست استفاده از mutable است مثل StringBuilder

حالت های دیگری هم هست که اشیا mutable ترجیح داده می‌شوند. برای مثال پاس دادن اشیا mutable به متدها اجازه می‌دهد نتایج زیادی را بدون پریدن به حلقه‌های ساختگی جمع‌آوری کنید. مثال دیگر مرتب کردن و فیلتر کردن است. هرچند می‌توانید متدی درست کنید که مجموعه‌های اصلی را گرفته و مرتب شده را تحویل دهد اما برای مجموعه‌های بزرگ اتلاف زیادی دارد.

۹. Constructor of Super and Sub

Implicit-super-constructor-is-undefined-for-default-constructor

در این جا خطای کامپایل رخ می‌دهد چرا که constructor پیش فرض super تعریف نشده است. در جاوا، اگر یک کلاس constructorای تعریف نکرده باشد، کامپایلر  به طور پیش‌فرض یک constructor بدون آرگومان وارد می‌کند. اگر constructor در super class تعریف شده باشد، در اینجا Super(String s) کامپایلر constructor پیش‌فرض بدون آرگومان را وارد نمی‌کند. این همان شرایط کلاس Super بالاست.

 constructor کلاس Sub چه با آرگومان و چه بدون آن، constructor بدون آرگومان کلاس Super را صدا می‌زند. از آن‌جایی که کامپایلر تلاش دارد super() را به دو constructor در کلاس Sub اضافه کند اما constructor پیش فرض کلاس Super تعریف نشده است،‌ با خطا روبرو می‌شود.

برای حل مشکل

۱) یک Super() constructor به کلاس Super به این شکل اضافه کنید:

۲) Super() constructor که خود تعریف کرده اید را حذف کنید

۳)‌ super(value) را به constructor کلاس sub اضافه کنید.

۱۰)  “” یا Constructor؟

رشته‌ها به دو طریق ساخته می‌شوند:

تفاوت آن‌ها چیست؟

مثال زیر یک جواب کوتاه ارائه می‌دهد:

برای اطلاعات بیشتر به اینجا مراجعه کنید.

این اطلاعات از تحلیل تعداد زیادی پروژه متن‌باز در گیت‌هاب، استک اور فلو و جستجو های گوگل به دست آمده است. ارزیابی دقیقی مبنی بر اینکه آیا دقیقا ده‌تای اول هستند انجام نشده است اما قطعا بسیار رایج هستند. شما هم با این مسائل روبرو شده‌اید؟

منبع:

http://www.programcreek.com/

[تعداد: 0    میانگین: 0/5]
برچسب ها
نمایش بیشتر

نوشته های مشابه

‫۳ نظرها

  1. با سلام و خسته نباشید
    خواهشآ در مورد تلفیق فریم ورک اسپرینگ و هایبرنیت سوال داشتم
    هایبرنیت کانفیگ خاص خودش را دارد و میشود در فایل hibernate.cfg.xml کانفیگش کرد ، و هم چنین اسپرینگ نیز ساپورت های خاص خود را از هایبرنیت دارد و میشود هایبرنیت را معمولا در فایل applicationContext.xml اسپرینگ نیز کانفیگ کرد ، میخواستم بدانم که به نظر شما کدام راه کاربرد بیشتری دارد و در پروژه های واقعی که هایبرنیت و اسپرینگ با هم استفاده میشوند ، هایبرنیت را چگونه کانفیگ میکنند .
    با تشکر

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا