نکات کلیدی
1. کارخانههای استاتیک به جای سازندهها: نامگذاری، کنترل و انعطافپذیری
ارائه یک روش کارخانه استاتیک به جای یک سازنده عمومی دارای مزایا و معایبی است.
مزایای نامگذاری. روشهای کارخانه استاتیک نامهای توصیفی ارائه میدهند، بر خلاف سازندهها، که به خوانایی و قابلیت استفاده از کد کمک میکند. این موضوع بهویژه زمانی مفید است که پارامترهای سازنده بهوضوح شیء ایجاد شده را نشان ندهند. بهعنوان مثال، یک روش به نام BigInteger.probablePrime()
توصیفیتر از یک سازنده BigInteger(int, int, Random)
است.
کنترل نمونه. کارخانههای استاتیک ملزم به ایجاد اشیاء جدید در هر بار فراخوانی نیستند، که به کلاسهای غیرقابل تغییر اجازه میدهد تا نمونهها را کش کرده و از ایجاد غیرضروری اشیاء جلوگیری کنند. این میتواند بهطور قابلتوجهی عملکرد را بهبود بخشد، بهویژه برای اشیاءی که بهطور مکرر درخواست میشوند. روش Boolean.valueOf(boolean)
نمونهای از این موضوع است، زیرا همیشه همان نمونههای Boolean.TRUE
یا Boolean.FALSE
را برمیگرداند.
انعطافپذیری زیرنوع. کارخانههای استاتیک میتوانند اشیاءی از هر زیرنوع نوع بازگشتی خود را برگردانند، که به APIها اجازه میدهد اشیاء را بدون عمومی کردن کلاسهایشان برگردانند. این موضوع API را فشردهتر کرده و اجازه میدهد کلاس بازگشتی بر اساس پارامترهای ورودی یا حتی در نسخههای مختلف تغییر کند، که به نگهداری و انعطافپذیری کمک میکند. این اساس چارچوبهای ارائهدهنده خدمات مانند Java Cryptography Extension (JCE) است.
2. پیادهسازی Singleton: سازندههای خصوصی و دسترسی عمومی
یک singleton به سادگی کلاسی است که دقیقاً یک بار نمونهسازی میشود [Gamma98، ص. 127].
تضمین یکتایی. Singletonها که نمایانگر اجزای منحصر به فرد سیستم هستند، با خصوصی کردن سازنده و ارائه یک عضو استاتیک عمومی برای دسترسی، تحمیل میشوند. این موضوع تضمین میکند که تنها یک نمونه وجود دارد. دو رویکرد رایج وجود دارد: استفاده از یک فیلد نهایی یا یک روش کارخانه استاتیک.
رویکرد فیلد نهایی. عضو استاتیک عمومی یک فیلد نهایی است که با نمونه singleton مقداردهی اولیه میشود. این رویکرد ساده است و مشخص میکند که کلاس یک singleton است. بهعنوان مثال:
public static final Elvis INSTANCE = new Elvis();
رویکرد کارخانه استاتیک. یک روش کارخانه استاتیک عمومی نمونه singleton را برمیگرداند. این موضوع انعطافپذیری را برای تغییر پیادهسازی بدون تغییر API فراهم میکند. بهعنوان مثال:
public static Elvis getInstance() { return INSTANCE; }
ملاحظات سریالسازی. برای حفظ ویژگی singleton در حین سریالسازی، باید یک روش readResolve
ارائه شود تا نمونه موجود را برگرداند و از ایجاد نمونههای جدید در هنگام دسرالیزه کردن جلوگیری کند. این موضوع تضمین میکند که singleton حتی پس از سریالسازی و دسرالیزه کردن نیز منحصر به فرد باقی بماند.
3. کلاسهای کاربردی: تحمیل عدم قابلیت نمونهسازی
چنین کلاسهای کاربردی برای نمونهسازی طراحی نشدهاند: یک نمونه بیمعنا خواهد بود.
هدف کلاسهای کاربردی. کلاسهای کاربردی که متدها و فیلدهای استاتیک را گروهبندی میکنند، برای سازماندهی عملکردهای مرتبط بر روی مقادیر اولیه، آرایهها یا اشیاءی که رابطهای خاصی را پیادهسازی میکنند، خدمت میکنند. آنها برای نمونهسازی طراحی نشدهاند، زیرا نمونهها بیمعنا خواهند بود. نمونههایی از این کلاسها شامل java.lang.Math
و java.util.Arrays
هستند.
جلوگیری از نمونهسازی. برای تحمیل عدم قابلیت نمونهسازی، یک ایدئوم ساده شامل گنجاندن یک سازنده خصوصی صریح است. این موضوع از تولید یک سازنده پیشفرض عمومی و بدون پارامتر توسط کامپایلر جلوگیری میکند و تضمین میکند که کلاس نمیتواند از خارج نمونهسازی شود.
عوارض جانبی. این ایدئوم همچنین از زیرکلاسسازی جلوگیری میکند، زیرا زیرکلاسها سازندهای برای فراخوانی سازنده سوپرکلاس نخواهند داشت. بهتر است یک توضیح در مورد هدف سازنده خصوصی گنجانده شود، زیرا ممکن است بهنظر غیرمعقول بیاید.
4. استفاده مجدد از اشیاء: کارایی و عدم تغییرپذیری
اغلب مناسب است که به جای ایجاد یک شیء جدید معادل عملکردی، از یک شیء واحد استفاده مجدد شود.
مزایای استفاده مجدد. استفاده مجدد از اشیاء، بهویژه اشیاء غیرقابل تغییر، کارآمدتر و شیکتر از ایجاد مکرر آنها است. زیرا ایجاد اشیاء و جمعآوری زباله میتواند پرهزینه باشد، بهویژه برای اشیاء سنگین. بهعنوان مثال، استفاده از String s = "silly";
بهتر از String s = new String("silly");
است.
اشیاء غیرقابل تغییر. اشیاء غیرقابل تغییر همیشه میتوانند بهطور ایمن استفاده مجدد شوند. بهعنوان مثال، Boolean.valueOf(String)
به Boolean(String)
ترجیح داده میشود زیرا اولی ممکن است از نمونههای موجود استفاده مجدد کند.
اشیاء قابل تغییر. اشیاء قابل تغییر میتوانند در صورتی که مشخص باشد تغییر نخواهند کرد، استفاده مجدد شوند. بهعنوان مثال، استفاده از مقداردهی استاتیک برای ایجاد نمونههای Calendar
و Date
یک بار، به جای ایجاد آنها هر بار که یک روش فراخوانی میشود، میتواند بهطور قابلتوجهی عملکرد را بهبود بخشد.
5. مدیریت حافظه: حذف ارجاعات منسوخ
یک ارجاع منسوخ به سادگی ارجاعی است که هرگز دوباره ارجاع نخواهد شد.
نشت حافظه. نشت حافظه در زبانهای جمعآوری زباله زمانی رخ میدهد که ارجاعات به اشیاء بهطور غیرعمدی نگهداری شوند و از جمعآوری زباله جلوگیری کنند. این موضوع میتواند منجر به کاهش عملکرد، افزایش حجم حافظه و حتی OutOfMemoryError
شود.
شناسایی نشت حافظه. یک منبع رایج نشت حافظه، کلاسهایی هستند که حافظه خود را مدیریت میکنند، مانند یک کلاس Stack
. زمانی که یک عنصر آزاد میشود، هر ارجاع شیء موجود در عنصر باید به null تغییر یابد.
راهحلها. برای جلوگیری از نشت حافظه، ارجاعات را به محض منسوخ شدن به null تغییر دهید. همچنین، به کشها توجه داشته باشید، که میتوانند ارجاعات اشیاء را مدتها پس از بیربط شدن نگهداری کنند. از WeakHashMap
برای کشهایی استفاده کنید که ورودیهای آنها تنها بهمدت وجود ارجاعات به کلیدهایشان در خارج از کش مرتبط هستند.
6. قرارداد Equals: بازتابی، تقارن و انتقال
متد equals یک رابطه معادل را پیادهسازی میکند.
رابطه معادل. هنگام بازنویسی متد equals
، رعایت قرارداد عمومی آن که یک رابطه معادل را تعریف میکند، بسیار مهم است. این قرارداد شامل بازتابی (x.equals(x) باید true برگرداند)، تقارن (x.equals(y) باید true باشد اگر و تنها اگر y.equals(x) true باشد) و انتقال (اگر x.equals(y) و y.equals(z) true باشند، آنگاه x.equals(z) باید true باشد) است.
نقض تقارن. نقض تقارن میتواند منجر به رفتار غیرقابل پیشبینی شود زمانی که اشیاء در مجموعهها استفاده میشوند. بهعنوان مثال، یک کلاس CaseInsensitiveString
که سعی در تعامل با رشتههای عادی دارد، میتواند تقارن را نقض کند.
نقض انتقال. نقض انتقال میتواند زمانی رخ دهد که یک کلاس قابل نمونهسازی را گسترش داده و جنبهای را اضافه کنید که بر مقایسههای equals
تأثیر بگذارد. برای جلوگیری از این موضوع، ترکیب را به ارثبری ترجیح دهید.
عدم وجود null. متد equals
باید برای هر مقدار مرجع غیر null x زمانی که x.equals(null) فراخوانی میشود، false برگرداند. عملگر instanceof
این موضوع را بهطور خودکار مدیریت میکند.
7. بازنویسی HashCode: سازگاری با Equals
شما باید hashCode را در هر کلاسی که equals را بازنویسی میکند، بازنویسی کنید.
اهمیت HashCode. بازنویسی hashCode
زمانی که equals
را بازنویسی میکنید، ضروری است تا اطمینان حاصل شود که اشیاء برابر دارای کدهای هش برابر هستند. عدم انجام این کار قرارداد عمومی Object.hashCode
را نقض کرده و از عملکرد صحیح کلاس در مجموعههای مبتنی بر هش مانند HashMap
و HashSet
جلوگیری میکند.
تابع هش قانونی اما ضعیف. یک متد hashCode
بیمعنا که همیشه همان مقدار را برمیگرداند قانونی است اما منجر به عملکرد ضعیف برای جداول هش میشود، زیرا تمام اشیاء به همان سطل هش میشوند.
دستورالعملی برای یک تابع هش خوب. یک تابع هش خوب تمایل دارد کدهای هش نابرابر برای اشیاء نابرابر تولید کند. یک دستورالعمل ساده شامل:
- مقداردهی اولیه یک متغیر
int
به نامresult
با یک مقدار ثابت غیر صفر (بهعنوان مثال، 17). - برای هر فیلد مهم
f
در شیء، یک کد هشc
محاسبه کرده و آن را با استفاده ازresult = 37 * result + c;
بهresult
ترکیب کنید. result
را برگردانید.
8. بازنویسی ToString: نمایش مختصر و اطلاعاتی
متد toString بهطور خودکار زمانی که شیء شما به println، عملگر الحاق رشته (+) یا، از نسخه 1.4 به بعد، assert منتقل میشود، فراخوانی میشود.
اهمیت ToString. بازنویسی متد toString
یک نمایش مختصر و اطلاعاتی از یک شیء فراهم میکند که استفاده از کلاس را دلپذیرتر میسازد. این موضوع بهویژه برای اشکالزدایی و ثبت وقایع مفید است.
محتوای ToString. زمانی که عملی باشد، متد toString
باید تمام اطلاعات جالب موجود در شیء را برگرداند. اگر شیء بزرگ باشد یا حاوی حالتی باشد که برای نمایش رشتهای مناسب نیست، باید یک خلاصه برگردانده شود.
تعیین فرمت. هنگام پیادهسازی toString
، تصمیم بگیرید که آیا فرمت مقدار بازگشتی را در مستندات مشخص کنید یا خیر. مشخص کردن فرمت یک نمایش استاندارد و بدون ابهام فراهم میکند اما انعطافپذیری برای تغییرات آینده را محدود میکند. اگر فرمت را مشخص کنید، یک سازنده رشته یا کارخانه استاتیک متناسب ارائه دهید.
9. رابط Cloneable: با احتیاط پیادهسازی کنید
رابط Cloneable بهعنوان یک رابط میکسین (ماده 16) برای اشیاء طراحی شده بود تا نشان دهد که آنها اجازه کپیبرداری را میدهند.
نقصهای Cloneable. رابط Cloneable
فاقد یک متد clone
است و متد clone
کلاس Object
محافظتشده است. این موضوع فراخوانی متد clone
بر روی یک شیء صرفاً به این دلیل که Cloneable
را پیادهسازی میکند، دشوار میسازد.
قرارداد Clone. قرارداد عمومی برای متد clone
ضعیف است و بیان میکند که یک کپی از شیء ایجاد و برمیگرداند. با این حال، مشخص نمیکند که این کپی چگونه باید ساخته شود یا آیا سازندهها باید فراخوانی شوند یا خیر.
پیادهسازی Cloneable. برای پیادهسازی صحیح Cloneable
، یک کلاس باید متد clone
را با یک متد عمومی که ابتدا super.clone
را فراخوانی کرده و سپس هر فیلدی که نیاز به اصلاح دارد را اصلاح میکند، بازنویسی کند. این معمولاً به معنای کپی کردن هر شیء قابل تغییر است که ساختار داخلی "عمیق" شیء را تشکیل میدهد.
جایگزینهای Cloneable. یک رویکرد خوب برای کپیبرداری از اشیاء، ارائه یک سازنده کپی یا کارخانه استاتیک است. این رویکردها به مکانیزم ایجاد شیء پرخطر وابسته نیستند و با استفاده صحیح از فیلدهای نهایی تداخل ندارند.
10. رابط Comparable: ترتیب طبیعی
با پیادهسازی Comparable، یک کلاس نشان میدهد که نمونههای آن دارای یک ترتیب طبیعی هستند.
مزایای Comparable. پیادهسازی رابط Comparable
به یک کلاس اجازه میدهد تا با الگوریتمهای عمومی و پیادهسازیهای مجموعه که به ترتیب وابسته هستند، مانند Arrays.sort
و TreeSet
، تعامل داشته باشد.
قرارداد CompareTo. قرارداد عمومی برای متد compareTo
مشابه قرارداد متد equals
است و نیاز به بازتابی، انتقال و تقارن دارد. به شدت توصیه میشود که (x.compareTo(y)==0) == (x.equals(y))
باشد.
نوشتن یک متد CompareTo. هنگام نوشتن یک متد compareTo
، فیلدهای مرجع شیء را با فراخوانی متد compareTo
بهطور بازگشتی مقایسه کنید. فیلدهای اولیه را با استفاده از عملگرهای رابطهای <
و >
مقایسه کنید. اگر یک کلاس چندین فیلد مهم داشته باشد، آنها را به ترتیب اهمیت مقایسه کنید.
11. حداقل کردن دسترسی: پنهانسازی اطلاعات
مهمترین عاملی که یک ماژول بهخوبی طراحیشده را از یک ماژول بهبدی طراحیشده متمایز میکند، درجهای است که ماژول دادههای داخلی و سایر جزئیات پیادهسازی خود را از سایر ماژولها پنهان میکند.
مزایای پنهانسازی اطلاعات. پنهانسازی اطلاعات یا کپسولهسازی ماژولها را از هم جدا میکند و به آنها اجازه میدهد بهطور مستقل توسعه، آزمایش، بهینهسازی و تغییر یابند. این موضوع سرعت توسعه سیستم را افزایش میدهد، نگهداری را آسانتر میکند، استفاده مجدد از نرمافزار را افزایش میدهد و ریسک را کاهش میدهد.
سطوح دسترسی. زبان برنامهنویسی جاوا اصلاحکنندههای دسترسی (private
، package-private، protected
و public
) را برای کمک به پنهانسازی اطلاعات فراهم میکند. قاعده کلی این است که هر کلاس یا عضوی را تا حد ممکن غیرقابل دسترسی کنید.
فیلدهای عمومی. کلاسهای عمومی باید بهندرت، اگر هرگز، فیلدهای عمومی داشته باشند (برخلاف متدهای عمومی). استثنا برای فیلدهای عمومی استاتیک نهایی حاوی مقادیر اولیه یا ارجاعات به اشیاء غیرقابل تغییر است.
12. ترجیح عدم تغییرپذیری: سادگی و ایمنی در برابر رشتهها
یک کلاس غیرقابل تغییر به سادگی کلاسی است که نمونههای آن نمیتوانند تغییر کنند.
مزایای عدم تغییرپذیری. کلاسهای غیرقابل تغییر از کلاسهای قابل تغییر آسانتر برای طراحی، پیادهسازی و استفاده هستند. آنها کمتر مستعد خطا هستند و ایمنترند.
قوانین برای عدم تغییرپذیری. برای غیرقابل تغییر کردن یک کلاس:
- هیچ متدی که شیء را تغییر دهد (متدهای تغییر دهنده) ارائه ندهید.
- اطمینان حاصل کنید که هیچ متدی قابل بازنویسی نیست (کلاس را نهایی کنید یا از سازندههای خصوصی و کارخانههای استاتیک استفاده کنید).
- تمام فیلدها را نهایی کنید.
- تمام فیلدها را خصوصی کنید.
- اطمینان حاصل کنید که دسترسی انحصاری به هر مؤلفه قابل تغییر وجود دارد (کپیهای دفاعی ایجاد کنید).
معایب عدم تغییرپذیری. تنها عیب واقعی کلاسهای غیرقابل تغییر این است که آنها به یک شیء جداگانه برای هر مقدار متمایز نیاز دارند. برای مقابله با این موضوع، مقادیر پرکاربرد را بهعنوان ثابتهای عمومی استاتیک نهایی ارائه دهید و در نظر بگیرید که یک کلاس همراه قابل تغییر عمومی ارائه دهید.
آخرین بهروزرسانی::
FAQ
What's Effective Java about?
- Java best practices: Effective Java by Joshua Bloch is a comprehensive guide focused on best practices for Java programming. It aims to help developers write clear, correct, robust, and reusable code.
- Practical advice: The book is tailored for developers familiar with Java who wish to enhance their coding skills. It covers a wide range of topics, including object creation, methods, classes, and interfaces.
- Structured format: The content is organized into distinct items, each addressing a specific aspect of Java programming. This structure allows readers to easily navigate and apply the advice.
Why should I read Effective Java?
- Improve coding skills: Reading Effective Java can significantly enhance your Java programming abilities by providing insights not commonly found in other resources.
- Expert insights: Joshua Bloch, a key contributor to the Java platform, shares his extensive experience through practical examples and rules of thumb.
- Code quality focus: The book emphasizes writing code that is not only functional but also maintainable and efficient, leading to fewer bugs and easier code management.
What are the key takeaways of Effective Java?
- Clarity and simplicity: The book stresses the importance of writing clear and simple code, ensuring understandability and maintainability over time.
- Composition over inheritance: Bloch advises using composition instead of inheritance to create more flexible and robust code structures, reducing dependencies and potential fragility.
- Static factory methods: The book recommends using static factory methods for object creation, offering better readability and flexibility.
What are some specific rules from Effective Java?
- Static Factory Methods: Consider providing static factory methods instead of constructors for better naming and performance.
- Singleton Property: Enforce the singleton property with a private constructor to ensure a class has only one instance.
- Override Equals and HashCode: Always override
hashCode
when you overrideequals
to ensure correct functioning of hash-based collections.
How does Effective Java address object creation?
- Static Factory Methods: Suggests using static factory methods for object creation instead of constructors for better naming and performance.
- Avoiding Duplicate Objects: Advises against creating duplicate objects, especially for immutable types, to improve memory management.
- Enforcing Noninstantiability: Discusses enforcing noninstantiability with a private constructor for utility classes to prevent unnecessary instances.
What are the benefits of immutability discussed in Effective Java?
- Thread Safety: Immutable objects are inherently thread-safe, eliminating the need for synchronization and simplifying concurrent programming.
- Simplicity and Clarity: Immutability leads to simpler code, making reasoning about the code easier and reducing the likelihood of bugs.
- Reuse and Performance: Immutable objects can be shared freely, allowing for efficient memory usage and reduced overhead of object creation.
How does Effective Java suggest handling exceptions?
- Use Exceptions for Exceptional Conditions: Advises using exceptions only for exceptional conditions, not for regular control flow, to maintain clarity and avoid performance penalties.
- Document Exceptions: Emphasizes documenting exceptions that a method can throw to improve code readability and help users handle potential errors.
- Favor Standard Exceptions: Recommends using standard exceptions provided by the Java platform for consistency and familiarity.
What is the significance of the Effective Java item on interfaces?
- Define Types with Interfaces: Emphasizes using interfaces to define types, not to export constants, keeping the API clean and focused on behavior.
- Favor Interfaces Over Abstract Classes: Advises using interfaces for flexibility, allowing multiple implementations without single inheritance constraints.
- Avoid Constant Interfaces: Warns against using constant interfaces, suggesting utility classes instead to group constants.
How does Effective Java recommend designing for inheritance?
- Design and Document for Inheritance: If a class is designed for inheritance, it must document the effects of overriding methods to ensure subclass understanding.
- Prohibit Unnecessary Inheritance: Suggests making classes final or using private constructors to prevent unintended inheritance, reducing fragility.
- Provide Protected Methods: Expose protected methods judiciously to allow subclass extension while avoiding excessive implementation detail exposure.
How does Effective Java address concurrency?
- Synchronize Access to Shared Data: Emphasizes synchronizing access to shared mutable data to prevent data corruption and ensure thread safety.
- Avoid Excessive Synchronization: Advises minimizing work within synchronized blocks to enhance performance and avoid deadlocks.
- Document Thread Safety: Stresses the importance of documenting the thread safety of classes and methods for safe multithreaded use.
What is the double-checked locking idiom, and why is it problematic?
- Lazy Initialization Purpose: Used to reduce synchronization overhead when lazily initializing a resource by checking if it's initialized before locking.
- Inconsistent States Risk: Without proper synchronization, threads may see a partially constructed object, leading to inconsistent states and bugs.
- Avoidance Recommendation: Advises against using double-checked locking due to its complexity and potential pitfalls, suggesting simpler alternatives.
What are the best quotes from Effective Java and what do they mean?
- "Programs must be written for people to read, and only incidentally for machines to execute." Emphasizes writing code understandable to humans, not just optimized for machines.
- "The single most important factor that distinguishes a well-designed module from a poorly designed one is the degree to which the module hides its internal data." Highlights the principle of encapsulation for maintainable and flexible code.
- "Don't create a new object when you should reuse an existing one." Encourages object reuse, especially for immutable objects, to enhance performance and reduce memory usage.
نقد و بررسی
کتاب جاوا مؤثر به عنوان یک منبع ضروری برای توسعهدهندگان جاوا شناخته میشود و به خاطر توضیحات روشن و مشاورههای عملیاش مورد تحسین قرار گرفته است. خوانندگان از تخصص بلچ و تمرکز کتاب بر نوشتن کدهای باکیفیت و قابل نگهداری قدردانی میکنند. بسیاری آن را برای هر دو گروه مبتدیان و برنامهنویسان با تجربه یک کتاب ضروری میدانند. این کتاب به بررسی ویژگیهای مختلف جاوا، بهترین شیوهها و دامهای رایج میپردازد. در حالی که برخی بخشها را قدیمی یا بیش از حد پیشرفته میدانند، اکثر افراد بر این باورند که این کتاب به طور قابل توجهی مهارتهای کدنویسی و درک پیچیدگیهای جاوا را بهبود میبخشد.
Similar Books









