Learn Java
304 subscribers
92 photos
1 video
94 files
84 links
یاد گیری زبان برنامه نویسی جاوا و نکات و مفاهیم
کاربردی ان



@parsa8113
@bardiademon
Download Telegram
Design Pattern (الگوی طراحی) چیست؟

اگر با مفهوم Design Pattern (الگوی طراحی) آشنایی داشته باشید، به طور حتم می‌دانید که دیزاین پترن‌ها به مجموعه‌‌ای از راه‌کارها در صنعت توسعهٔ نرم‌افزار گفته می‌شوند که می‌توانید از آن‌ها در کدنویسی پروژه‌ها، اعم از کوچک و بزرگ، استفاده نمایید و استفاده از این الگوها که توسط متخصصان باتجربه در زمینهٔ شییٔ‌گرایی ابداع شده‌اند کمک می‌کنند تا سورس‌کدی انعطاف‌پذیرتر و تغییرپذیرتر داشته باشیم. چنانچه کماکان الگوهای طراحی را جزو چرخهٔ توسعه به حساب نمی‌آورید، در ادامه قصد داریم دلایلی را ذکر کنیم مبنی بر اینکه که چرا باید این سولوشن‌های تست‌‌شده را در قالب یکسری به اصطلاح Best Practice در حین توسعهٔ نرم‌افزار به کار گیرید.
اولین کسی باشید که به این سؤال پاسخ می‌دهید
برنامه نویسی موازی با cuda در vs code

اگر با مفهوم Design Pattern (الگوی طراحی) آشنایی داشته باشید، به طور حتم می‌دانید که دیزاین پترن‌ها به مجموعه‌‌ای از راه‌کارها در صنعت توسعهٔ نرم‌افزار گفته می‌شوند که می‌توانید از آن‌ها در کدنویسی پروژه‌ها، اعم از کوچک و بزرگ، استفاده نمایید و استفاده از این الگوها که توسط متخصصان باتجربه در زمینهٔ شییٔ‌گرایی ابداع شده‌اند کمک می‌کنند تا سورس‌کدی انعطاف‌پذیرتر و تغییرپذیرتر داشته باشیم.

چنانچه کماکان الگوهای طراحی را جزو چرخهٔ توسعه به حساب نمی‌آورید، در ادامه قصد داریم دلایلی را ذکر کنیم مبنی بر اینکه که چرا باید این سولوشن‌های تست‌‌شده را در قالب یکسری به اصطلاح Best Practice در حین توسعهٔ نرم‌افزار به کار گیرید.

عدم نیاز به اختراع مجدد چرخ
یک اصل ثابت در توسعهٔ نرم‌افزار وجود دارد و آن هم چیزی نیست جز اِعمال تغییرات در صورت نیاز. تغییرات هنگامی رخ می‌دهند که نیازمندی‌ها عوض می‌شوند، سیستم‌ها رشد می‌کنند، ویژگی‌های جدید اضافه می‌شوند، کارایی باید بهبود یابد و موارد دیگری از این دست اما سؤال اینجا است که چگونه می‌توان نرم‌افزاری تولید کرد به طوری که تأثیر این تغییرات در آن حداقلی باشد؟

نیاز به توضیح نیست که یکی از سخت‌ترین جنبه‌های توسعهٔ نرم‌افزاری چیزی نیست جز درک کدهای موجود، که احتمالاً توسط دولوپرهای دیگری نوشته شده‌اند، و اصلاح این کدها به نحوی که نقص‌های جدید یا نتایج ناخواسته بروز نکنند. با این توضیح، در پاسخ به سؤال فوق باید گفت که در واقع معجزه‌ای در کار نیست ولی تکنیک‌هایی وجود دارند که می‌توان از آن‌ها در برنامه‌نویسی شییٔ‌گرا استفاده کرد؛ تکنیک‌هایی که بر اثر تجربهٔ برنامه‌نویسان حرفه‌ای در شرایط سخت ابداع شده‌اند و برای استفادهٔ عموم به بازار عرضه شده‌اند که این تکنیک‌ها به Design Patterns معروف هستند و که نمایانگر سولوشن‌هایی هستند که برای حل مشکلات رایج در برنامه‌نویسی می‌توان از آن‌ها استفاده نمود.

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

مهارت‌های مربوط به شییٔ‌گرایی خود را بهبود دهید
نیاز به توضیح نیست که سنگ بنای برنامه‌نویسی شییٔ‌گرا چیزی نیست جز Abstraction ،Inheritance ،Polymorphism و Encapsulation که به ترتیب می‌توان معادل‌های «چندریختی»، «وراثت»، «انتزاع» و «کپسوله‌سازی» برای این اصطلاحات در نظر گرفت. با اینکه چنین چیزی کاملاً صحت دارد، اما طراحی سیستم‌های شییٔ‌گرا به همین جا ختم نمی‌شود زیرا همین قواعد پایه‌ای می‌توانند به سرعت باعث ایجاد مشکلاتی مثل تکرار کد، طراحی ضعیف و استفادهٔ بیش از حد از کلاس‌های مختلف شود.

به طور کلی، در مجموعه الگوهای طراحی با گروهی از قواعد دیگر آشنا خواهید شد که بهتر از پایه‌های اولیهٔ شییٔ‌گرایی به کار خواهند آمد و با شناخت این اصول و چگونگی ترکیب آن‌ها در الگوهای طراحی، به طراح و معمار بهتری در زمینه شییٔ‌گرایی بدل خواهید شد.

الگوها را در لایبرری‌ها و زبان‌های مختلف تشخیص دهید
دیزاین پترن‌ها راه‌حل‌های عمومی برای حل مشکلات رایج در برنامه‌نویسی شییٔ‌گرا (OOP) هستند به این معنا که راه‌حل‌هایی هستند برای حل چالش‌های طراحی نرم‌افزار و لازم به یادآوری است که شما نمی‌توانید یک نمونه الگوی طراحی را برای افزودن به پروژهٔ خود دانلود و نصب نمایید بلکه باید الگوی طراحی را در داخل سیستم‌تان پیاده‌سازی کنید!
برنامه‌نویسان غالباً با الگوهایی در لایبرری‌ها، پکیج‌ها و ماژول‌هایی که استفاده می‌کنند مواجه می‌شوند که از آن جمله می‌توان به پکیج I/O در جاوا اشاره کرد. زبان برنامه‌نویسی جاوا از الگوی Decorator استفاده می‌کند که اجازه می‌دهد تا یک آبجکت ورودی/خروجی از فایل اصلی گرفته و سپس آن را با امکانات جدیدی طبق نیاز خود ترکیب کنید که این روش بسیار خوبی برای طراحی یک سیستم ورودی/خروجی فایل است و اگر از قبل با الگوهای طراحی و به طور خاص الگوی دکوراتور آشنا باشید، به سادگی متوجه چگونگی طراحی این آبجکت و روش کار آن خواهید شد. در یک کلام، به کار بردن این دیزاین پترن باعث می‌شود سریع‌تر طراحی سیستم را درک کنید.

از زبانی مشترک با دیگر دولوپرها استفاده کنید
همان‌طور که در مورد بالا بیان شد، یکی از مزایای یادگیری دیزاین پترن‌ها آشنایی با نوعی از معماری نرم‌افزار است که میان دولوپرهای حرفه‌ای سراسر دنیا عمومیت دارد به طوری که اگر در تیم نرم‌افزاری خود قصد سرعت بخشیدن به کارتان را دارید، از طریق این الگوها نیروی جدیدی برای برقراری ارتباط دربارهٔ منظور خود در طرح‌های‌تان با یکدیگر به دست خواهید آورد. به عنوان مثال، فرض کنید هم‌گروهی‌تان می‌خواهد قسمت جدیدی از طراحی‌اش را برایتان شرح دهد. دو طرز بیان زیر برای این منظور امکان‌پذیر است:

من این کلاس برودکست رو ساختم که کارش پیدا کردن تمامی اشیائی هست که به آن گوش می‌دهند و هر وقت دیتای جدیدی برسه، اون پیام رو به تمامی گیرنده‌ها می‌فرسته. جالب اینجاست که گیرنده‌ها می‌تونن در هر زمانی به برودکست متصل شده یا خودشون رو حذف کنن و این روش کاملاً پویا و به اصطلاح Loosely Coupled هستش.

یا

من این کلاس برودکست را بر پایهٔ الگوی Observer ساختم.

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

با اینکه در ترکیب و ساخت سیستم‌های شییٔ‌گرا به دست خودتان چیزهای زیادی برای یادگیری وجود دارد، اما می‌توانید از مزایای شناخت و بینشی که از طریق مطالعه و استفاده از دیزاین پترن‌ها به دست می‌آید، استفاده نمایید. همان‌طور که پیش از این گفتیم، الگوهای طراحی به یک باره ابداع نشده‌اند بلکه در نتیجهٔ کار سخت و تجربهٔ عمیق از طریق ساخت تعداد زیادی سیستم مختلف به دست آمده‌اند. در حین فرایند یادگیری الگوهای طراحی، شما به دیدگاه یک معمار باتجربه نرم‌افزاری دست یابید و در عین حال به سمت ساخت نرم‌افزارهای بهتر و ماندگارتر پیش خواهید رفت.
منبع :سکان اکادمی

@this_java
الگوی Factory

همونطور که تا حدودی از اسم این الگو پیداست، با ساختن یه به اصطلاح کارخونه، این امکان رو فراهم میکنیم که زمان تولید شئ، بجای اینکه خودمون تولیدش کنیم، به اون کارخونه بگیم چی میخوایم (ویژگی های شئ مورد نظر رو بهش میدیم) و اون کارخونه خودش شئ رو میسازه و میده بهمون.

مزیت های این الگو عبارتند از کاهش خطوط کد، سهولت توی تولید اشیاء، عدم نیاز به تغییر زیاد در صورت تغییر کلاس (کارخونه خودش تغییر لازمه رو اعمال میکنه) و ...

خب بریم مثالش رو ببینیم:

فرض کنیم یه اینترفیس وسیله ی نقلیه داریم:

public interface Vehicle { void showVehicleType();}

حالا دو تا کلاس دیگه داریم، یکی ماشین و یکی دیگه موتور که هردوتاشون نوعی وسیله ی نقلیه هستن:

public class Car implements Vehicle {
@Override
public void showVehicleType() {
System.out.println("Vehicle: Car");
}
}

public class MotorCycle implements Vehicle {
@Override
public void showVehicleType() {
System.out.println("Vehicle: MotorCycle"); }
}

برای پیاده سازی الگوی Factory، یه کلاس به اسم VehicleFactory میسازیم:

public class VehicleFactory {
public Vehicle createVehicle(String vehicleType){ if(vehicleType == null){
return null;
}
else if(vehicleType.equals("Car")){
return new Car();
}
else if(vehicleType.equals("MotorCycle")){
return new MotorCycle();
}
return null; }
}


و حالا فقط کافیه زمانی که میخوایم یه ماشین یا موتور بسازیم به شکل زیر عملی کنیم:

VehicleFactory vehicleFactory = new VehicleFactory();Vehicle car = vehicleFactory.createVehicle("Car");car.showVehicleType();

خروجی: Vehicle: Car
Vehicle motorCycle = vehicleFactory.createVehicle("MotorCycle"); motorCycle.showVehicleType();
:خروجی Vehicle: MotorCycle

به همین راحتی! ما توی این مثال از رشته برای تعیین نوع وسیله نقلیه استفاده کردیم. مشخصه که هر رشته ای بجز Car یا MotorCycle استفاده کنیم، null بر میگرده.

طبیعتاً میشه شیوه های دیگه ای هم برای نشان دادن نوع وسیله نقلیه استفاده کرد، برای مثل استفاده از رشته ی استاتیک:

public class VehicleFactory { public static final String TYPE_CAR = "Car"; public static final String TYPE_MOTORCYCLE = "MotorCycle"; public Vehicle createVehicle(String vehicleType){ if(vehicleType == null){ return null; } else if(vehicleType.equals(TYPE_CAR)){ return new Car(); } else if(vehicleType.equals(TYPE_MOTORCYCLE)){ return new MotorCycle(); } return null; } }

و برای تعریف شئ به شکل زیر عمل کنیم:

Vehicle motorCycle = vehicleFactory.createVehicle(VehicleFactory.TYPE_MOTORCYCLE);

یه روش دیگه استفاده از enum برای تعیین نوع کلاس درخواستی هست:

public class VehicleFactory {
public enum VehicleTypeEnum{
CAR, MOTOR_CYCLE
}
public Vehicle createVehicle(VehicleTypeEnum vehicleTypeEnum){
if(vehicleTypeEnum== null){ return null;
}
else if(vehicleTypeEnum.equals(VehicleTypeEnum.CAR)){
return new Car();
} else if(vehicleTypeEnum.equals(VehicleTypeEnum.MOTOR_CYCLE)){
return new MotorCycle(); } return null; }}

و زمان ساخت شئ به شکل زیر عمل کنیم:

Vehicle car = vehicleFactory.createVehicle(VehicleFactory.VehicleTypeEnum.CAR);

البته برای اینکه اصل open/close از اصول پنجگانه solid رو هم رعایت کرده باشیم میتونیم کلاس کارخونمون رو به شکل زیر پیاده سازی کنیم:

public class VehicleFactory {
public Vehicle createCar(){
return new Car();
}
public Vehicle createMotorCycle(){
return new MotorCycle();
}
}

و طبیعتاً برای ساخت شئ به شکل زیر عمل میکنیم:

Vehicle carObject = vehicleFactory.createCar();Vehicle motorCycleObject = vehicleFactory.createMotorCycle();

با کلیت این الگو آشنا شدیم. مثل هر الگوی دیگه ای با توجه به زمان، نوع و دلیل استفاده از این الگو میتونیم تغییرات لازمه ی خودمون را پیاده سازی کنیم. برای مثال تابع یا توابع سازنده ی اشیاء داخل کارخونه رو استاتیک تعریف کنیم که نیازی به تعریف شئ از کلاس کارخونه نداشته باشیم، یا در صورت نیاز از الگوی سینگلتون برای اشیاء ساخته شده استفاده کنیم، یا زمان ساخت اشیاء پارامترهایی هم پاس بدیم و با توجه به اون پارامترها تغییراتی روی شئ انجام بدیم، یا حتی بریم سراغ ارثبری ها چند سطحی و ...

@this_java
👍1
انواع دیزاین پترن

اکثرا دیزاین پترن ها به سه دسته ی زیر تقسیم میشن :
تکوینی (Creational): که بیشتر به اشیا و شیوه ی ایجادشون مرتبط هستن.
ساختاری (Structural): که بیشتر به ساختار کلاسها و ترکیب اشیاء میپردازن.
رفتاری (Behavioral): که بیشتر به ارتباط اشیاء در عین جداسازی عملکردشون تأکید دارن.

برای هر کدوم چند تا مثال میزنیم :
Creational

Singleton
Factory
Factory of Factory (Abstract Factory)
Prototype
Builder
Object Pool

Structure

Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy

Behavioral


Command
Template
Memento
Observer
Mediator
Strategy
Iterator



@this_java
الگوی Singleton

سینگلتون شاید پایه ای ترین الگوی طراحی ای باشه که اکثر برنامه نویسا باهاش آشنا هستن و اغلب اینطور تعریف میشه که این الگو تضمین میکنه ما صرفاً یه شئ از روی یه کلاس خواهیم داشت و صرفاً یه راه برای دسترسی به اون شئ در سرتاسر نرم‌افزار وجود داره. اما اگه بخوایم یذره بهتر تعریف کنیم باید بگیم:
هدف اینه که نشه از کلاسی بیشتر از یک شی ساخت.

خیلیا (مثل خودِ من قبل از اینکه بیشتر با این الگو آشنا بشم) فکر میکنن مفهوم سینگلتون رو کاملاً درک کردن و کاری نداره پیاده سازیش. اما توی این مقاله میبینیم که اوضاع یذره پیچیده تر از چیزی میتونه باشه که توی نگاه اول و داخل یه خط تعریف ساده گنجونده بشه. (البته باید توجه کنیم که اغلب توی استفاده های عادی مشکلی وجود نداره و در ادامه متوجه میشیم منظور ما از پیچیده تر شدن، یسری زمان های خاصی هست که باهاشون آشنا خواهیم شد).

برای پیاده سازی این الگو راه های زیادی وجود داره که سعی میکنیم مهمتریناشون رو بررسی کنیم (یه نکته اینکه به شئ ای که قراره یکی بیشتر نشه ازش ساخت توی این الگو اصطلاحاً instance گفته میشه):
روش Eager initialization

توی این روش که ساده ترین نوع پیاده سازی الگوی سینگلتون هست، instance در زمان لود کلاس ساخته میشه. در حقیقت چه بخوایم از instance استفاده بکنیم چه نخوایم، در هر صورت ساخته میشه و زمان فراخوانی تابع شئ ای که از قبل ساخته شده برگردونده میشه. این روش بصورت زیر پیاده میشه:

public class EagerInitializedSingleton {
private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();
private EagerInitializedSingleton(){
}
public static EagerInitializedSingleton getInstance(){
return instance;
}
}

اگه کلاس سینگلتونمون ریسورس های زیادی نداره، این روش مناسبیه ولی خب متأسفانه خیلی وقتا هست که ما دسترسی به فایل ها، دیبتابیس و سایر موارد این چنینی رو توی کلاس سینگلتون میذاریم و ممکنه باعث بوجود اومدن مشکلاتی مثل کمبود حافظه یا الکی درگیر نگه داشتم کانکشن ها بشیم.
روش Static block

این روش خیلی شبیه روش قبلی هست با این تفاوت که instance داخل بلوک static ساخته میشه (که البته یکی از معایب روش قبل رو که عدم وجود امکان هندل کردن اکسپشن ها بود رو نداره، اصطلاحاً امکان exception handling رو محیا میکنه):

public class StaticBlockSingleton {
private static StaticBlockSingleton instance private StaticBlockSingleton(){
}
static{
try{
instance = new StaticBlockSingleton();
}catch(Exception e){
throw new RuntimeException("Exception occured in creating singleton instance");
}
} public static StaticBlockSingleton getInstance(){
return instance;
}
}

هردوی این روش و روش قبلی، حتی اگه از instance استفاده نشه، بازم اون رو میسازن و طبیعتاً میتونیم بگیم توی خیلی از شرایط نمیتونه بهترین انتخاب یا اصطلاحاً best practice باشه (گرچه خیلی اوقات هم از همین روش برای پیاده سازی بدون مشکل استفاده میشه).
روش Lazy Initialization

این روش برای ساخت instance زمانی که بهش نیاز داریم استفاده میشه و به این صورت قابل پیاده سازیه:

public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
private LazyInitializedSingleton(){
}
public static LazyInitializedSingleton getInstance(){
if(instance == null){ instance = new LazyInitializedSingleton();
}
return instance;
}
}

در حقیقت با این روش (بر خلاف دو روش قبلی) instance از اول ساخته نمیشه که شاید ازش استفاده بشه شاید هم نیشه، و بجای اون زمانی که میخوایم ازش استفاده کنیم چک میکنیم اگه قبلاً ساخته نشده بود میسازیمش.
روش Thread Safe Singleton

خب قبل از گفتن این روش یه مقدمه بخونیم.
تا اینجا سه روش مرسوم توی حالت عادی رو دیدیم. اما یه سوال، اگه ما بخوایم نرم افزارمون چندنخی (یا اصطلاحاً multi thread) باشه چی؟ بازم میتونیم از این روش استفاده کنیم؟
جواب منفیه! توی نوشتن برنامه های چندنخی، هر نخ میتونه instance جدا داشته باشه.

این نکته رو هم بگم که توی سری مقالات دیزاین پترن ها، فقط این توی این الگو اونم بیشتر برای آشنایی بیشتر سراغ موارد خاص میریم. توی بقیه الگوها اغلب اگه موردش پیش اومد با توجه به نکات این مقاله یا سرچ، تغییرات لازمه رو اعمال کنین.

با توجه به چیزایی که گفتیم، برای اینکه جلوگیری کنیم از اینکه هر نخ instance خودش رو بسازه، میتونیم از synchronized استفاده بکنیم. بصورت زیر:
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton(){
}
public static synchronized ThreadSafeSingleton getInstance(){ if(instance == null){
instance = new ThreadSafeSingleton();
}
return instance;
}
}

پیاده سازی بالا اصطلاحاً thread-safe هست (در برابر چند نخی مقاومت داره و اجازه نمیده چند نخی نتیجه ی متفاوتی از تک نخی داشته باشه) اما بخاطر استفاده از synchronized کارایی یا همون performance رو کاهش میده. برای اینکه هربار اصطلاحاً overhead نداشته باشیم از double checked locking استفاده میکنیم و کد بالا رو به شکل زیر تغییر میدیم:

public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
if(instance == null){
synchronized (ThreadSafeSingleton.class) {
if(instance == null){
instance = new ThreadSafeSingleton();
}
}
} return instance;
}

برای آشنایی بیشتر با اینکه چیکار کردیم میتونین نگاهی به این مقاله بندازین.
روش Bill Pugh Singleton

این روش بیشتر به نسخه های جاوا قبل از 5 مرتبط میشه که مشکلاتی در حافظه و چندنخی داشتن. به همین خاطر روش زیر مطرح شد:

public class BillPughSingleton {
private BillPughSingleton(){
}
private static class SingletonHelper{
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance(){
return SingletonHelper.INSTANCE; }
}

دقت کنیم که instance داخل یک کلاس داخلی استاتیک (یا اصطلاحاً private inner static) قرار داره. بنابراین، زمانی که در کد بالا کلاس BillPughSingleton لود میشه، کلاس SingletonHelper توی مموری لود نمیشه (زمانی که تابع getInstance صدا زده بشه لود میشه)

این روش هم خیلی خوبه و نیازی به synchronization نداره، و البته فهم و پیاده سازیش راحته نسبتاً.

@this_java
مثال برای foreach :

روش معمولی حلقه زدن در Map.
Map<String, Integer> items = new HashMap<>();
items.put("A", 10);
items.put("B", 20);
items.put("C", 30);
items.put("D", 40);
items.put("E", 50);
items.put("F", 60);

for (Map.Entry<String, Integer> entry : items.entrySet()) {
System.out.println("Item : " + entry.getKey() + " Count : " + entry.getValue());
}

در جاوا 8، شما می توانید با استفاده از foreach به همراه lambda expression درون یک Map حلقه بزنید.
Map<String, Integer> items = new HashMap<>();
items.put("A", 10);
items.put("B", 20);
items.put("C", 30);
items.put("D", 40);
items.put("E", 50);
items.put("F", 60);

items.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));

items.forEach((k,v)->{
System.out.println("Item : " + k + " Count : " + v);
if("E".equals(k)){
System.out.println("Hello E");
}
});

@this_java
تفاوت object تغییرپذیر (mutable) و تغییرناپذیر (immutable) در جاوا

1. Mutable Objects: شما می توانید وضعیت و فیلدهای شیء یا object را بعد از ایجاد شدن تغییر دهید. برای مثال: StringBuilder ،java.util.Date و غیره.

2. Immutable Object: شما نمی توانید هیچ چیزی را بعد از ایجاد شدن object تغییر دهید. برای مثال: String ،Integer ،Long و غیره.
مثال Mutable جاوا

به طور معمول، متدی برای ویرایش مقدار فیلد در خود دارد، و object می تواند گسترش پیدا کند.
package org.oruji;

public class MutableExample {
private String name;

MutableClass(String name) {
this.name = name;
}

public String getName() {
return name;
}

// this setter can modify the name
public void setName(String name) {
this.name = name;
}

public static void main(String[] args) {
MutableExample obj = new MutableExample("oruji");
System.out.println(obj.getName());

// update the name, this object is mutable
obj.setName("new oruji");
System.out.println(obj.getName());
}
}

خروجی برنامه
oruji
new oruji
مثال Immutable جاوا

برای ایجاد یک object تغییر ناپدیر (immutable)، کلاس را به صورت final تعریف کرده، و هیچ متدی برای ویرایش فیلدها ایجاد نکنید.
package org.oruji;

// make this class final, no one can extend this class
public final class ImmutableExample {
private String name;

ImmutableExample (String name) {
this.name = name;
}

public String getName() {
return name;
}

//no setter

public static void main(String[] args) {
ImmutableExample obj = new ImmutableExample("oruji");
System.out.println(obj.getName());

// there is no way to update the name after the object is created.
// obj.setName("new oruji");
// System.out.println(obj.getName());
}
}

خروجی برنامه
oruji

@this_java
تبدیل به یک رشته:
String.ValueOf()
یا + ""
کدام یک؟

غالبا دو روش کلی برای تبدیل به رشته در جاوا وجود دارد یکی استفاده از کلاس String و دیگری جمع کردن ان با یک رشته ی دیگر ...

هدف تبدیل به یک رشته است و نه پیوند رشته!
String.valueOf به یک رشته تبدیل میکند در حالی + "" با یک رشته پیوند میدهد

String.ValueOf :
مستقیما به یک رشته تبدیل میکند

+"":
یک StringBuffer تولید میکنه و بعد به String تبدیل میکنه
پس String.ValueOf روند کمتری رو طی میکنه و مناسب تره...
@this_java
بلوک استاتیک چیست؟

در کلاس های جاوا ما اجازه نداریم متغیر های ثابت استاتیک را (static final) داخل سازنده یا بلوک غیر استاتیک مقدار دهی اولیه کنیم و به ناچار باید داخل static block اونار مقدار دهی کنیم
//this is static block
static {

}

// this is non static block
{
}
اگر متغیر های static final داخل static block مقدار دهی نشه compilation error ارور میگیرید
نکته ی قابل توجه اینه که بلاک استاتیک، تنها یک بار در موقع load شدن کلاس (با اولین access به کلاس، کلاس load می‌شود) فراخوانی می‌شه
@this_java
چرا static block ها در جاوا قبل از constructor اجرا می شوند؟

بلاک استاتیک تنها یکبار و در اولین دسترسی به کلاس اجرا میشود.
درحالیکه constructor در هر زمان که از کلاس یک نمونه ساخته میشود یکبار اجرا میشود.پس لازم است ابتدا محتویات داخل استاتیک که مربوط به آماده سازی خود کلاس است ونه نمونه هاش اجرا شود و سپس یک نمونه از آن ساخته شود.
@this_java
دلیل استفاده نشدن کلمات this و super در متد هاس static چیست؟
this
اشاره به object ای دارد که از روی این کلاس «نمونه سازی» (instantiate) شده است. در حالی که متد های استاتیک، باید بتوانند بدون این که نمونه ای از کلاس ساخته شده باشد کار کنند.
@this_java
آیا اینکه تمام متد های یک سیستم را به صورت static تعریف کنیم موجب بالا بردن performance در سیستم می گردد؟


اینکه از عضو های استاتیک یک کلاس شئ ساخته نمی شود اشتباه است بلکه از اعضای استاتیک یک کلاس در زمان اجرای JVM، اشیاء خاصی در حافظه heap ساخته می شود.

تنها تفاوت performance که می تواند وجود داشته باشد این است که برنامه ای که اعضای استاتیک زیادی دارد زمان شروع بکار (startup) آن بیشتر طول می کشد و در عوض پس از اجرا شدن سریعتر کار می کند.

اما این نکته را هم در نظر بگیرید که مبحث اعضای استاتیک و غیر استاتیک یک کلاس برای طراحی بهتر برنامه تعریف شده اند نه بحث performance و نمی توان بدلیل اینکه اعضای استاتیک، performance زمان اجرای برنامه را بالا می برند تمام اعضا را استاتیک تعریف کرد.
@this_java
چرا نباید در جاوا درون Constructor متد های کلاس را فراخوانی کرد؟

دایتل در آخرین کتاب خود بر خلاف قبل صحت پارامترهای سازنده را توسط فراخوانی متدهای setter در سازنده انجام نمی دهد بلکه شروط متد setter را مجددا در سازنده بازنویسی کرده آیا این کار تاثیری در performance دارد؟

جواب:

دلیل این کار وجود یک violation در مباحث کنترل کیفیت کد است که باعث می شود نتایجی برخلاف آن چیزی که ما توقع داریم اتفاق بیوفتد. در زبان برنامه نویسی جاوا نباید درون Constructor متد هایی که قابل override شدن هستند را فراخوانی کرد (متد های private, static, یا final قابل override شدن نیستند). به این قانون به زبان انگلیسی Ensure that constructors do not call overridable methods می گویند.

در زبان برنامه نویسی جاوا اگر متد یک کلاس در کلاس فرزندش override شده باشد و در Constructor کلاس پدر متد override شده فراخوانی شود، متد override شده در کلاس فرزند استفاده خواهد شد. به کد زیر توجه کنید:

class SuperClass {
public SuperClass () {
doLogic();
}

public void doLogic() {
System.out.println("This is superclass!");
}
}

class SubClass extends SuperClass {
private String color = null;
public SubClass() {
super();
color = "Red";
}

public void doLogic() {
System.out.println("This is subclass! The color is :" + color);
// ...
}
}

public class Overridable {
public static void main(String[] args) {
SuperClass bc = new SuperClass();
// Prints "This is superclass!"
SuperClass sc = new SubClass();
// Prints "This is subclass! The color is :null"
}
}



کد بالا بدون مشکل و خطا اجرا می شود ولی در زمانی که در Constructor کلاس SubClass با استفاده از super سازنده کلاس SuperClass فراخوانی می شود بجای فراخوانی متد doLogic در SuperClass متد doLogic در SubClass فراخوانی می شود.

راه حل:

یا باید متد doLogic را غیرقابل override کرد یا اینکه بدنه متد doLogic را در محل مشخص در Constructor کپی کرد و از متد doLogic صرف نظر کرد.


@this_java
آیا می توان متد که private یا static است را در جاوا override کرد؟
متد های private اصلا در مکانیزم وراثت در جاوا به کلاس فرزند ارث نمی رسند چه برسد به اینکه بخواهیم آنها را override کنیم.
متد های استاتیک یک کلاس را نمی توان override کرد بلکه می توانیم متد های استاتیک یک کلاس را مخفی (hide) کنیم.
@this_java
چرا نمی توان در جاوا متد های استاتیک را override کرد اما در زبان هایی مانند Scala یا Objective-C این کار امکانپذیر است؟

بدلیل اینکه متد های استاتیک در جاوا به اشیاء ساخته شده از یک کلاس تعلق ندارند و اصطلاحا متد های در سطح کلاس هستند و نمی توان آنها را در کلاس فرزند override کرد و اگر یک متد استاتیک در کلاس فرزند دقیقا با همان امضای متد کلاس پدر وجود داشته باشد خطایی رخ نمی دهد و برنامه بدرستی کامپایل می شود.
در این موارد گفته می شود کد متد فرزند متد پدر را hide کرده است و به این کار override گفته نمی شود چون هنوز متد کلاس پدر در سطح همان کلاس قابل دسترسی است.
@this_java
اگر هنوز با Jlink کار نکرده اید، ببینید چه چیزی از ابزار خط فرمان Java 9 می تواند برای کمک به یک JRE سبک وزن، سفارشی ایجاد کند.
معمولا برنامه ما با استفاده از JRE پیش فرض اجرا می شود، اما در صورتی که می خواهید JRE خودتان را ایجاد کنید، می توانید با مفهوم jlink اشنا شوید.

چرا JRE خود را بسازید؟
فرض کنید ما یک برنامه ساده " Hello World !" داریم:
class Test  {

public static void main(String[]args) {

System.out.prinltn("Hello World");

}

}

برای اجرای این برنامه "hello world" کوچک، ما نیاز به کلاس فایل های زیر داریم :


String.class
Test.class
System.class
Object.class
در اینجا، این 4 کلاس برای اجرای برنامه من کافی خواهد بود.

پیش فرض JRE توسط اوراکل شامل 4300 + فایل جاوا کلاس از پیش تعریف شده است .
اگر من درخواست hello world را با JRE پیش فرض اجرا کنم، سپس تمام فایل های کلاس class از پیش تعریف شده اجرا خواهند شد. اما اگر من فقط به فایل های 3-4 .class نیاز داشته باشم که برنامه Hello World را اجرا کنم، پس چرا باید فایل های بیرونی کلاس را حفظ کنم؟

بنابراین مشکل با JRE پیش فرض این است که تمام فایل های .class از پیش تعریف شده را اجرا می کند، آیا می خواهید یا نه.
و اگر شما همچنین به اندازه پیش فرض JRE نگاه کنید، خواهید دید که آن 203 مگابایت است. برای اجرای 1 کیلوبایت ساده من، باید 203 مگابایت JRE را در دستگاه خود نگهداری کنم. این یک اتلاف کامل از حافظه است.

بنابراین استفاده از JRE به طور پیش فرض به این معنی است:

بنابراین جاوا بهترین انتخاب برای سرویس های microservices و IoT نیست، اما این فقط یک مشکل با جاوا 1.8 بود. ولی حالا، جاوا 1.9 با jlink همراه است. با jlink ما می توانیم JRE کوچک خود را که شامل تنها کلاس های مرتبط است که می خواهیم ایجاد کنیم. و از هدر رفتن حافظه جلوگیری و عملکرد نیز افزایش خواهد یافت.

@this_java
همونطور که میدونید java fx از jdk 11 حذف شده ... اگه میخواید ازش استفاده کنید به صورت زیر عمل کنید:

https://dzone.com/articles/javafx-on-jdk-11
و اگر از maven همونطور که میدونید java fx از jdk 11 حذف شده ... اگه میخواید ازش استفاده کنید به صورت زیر عمل کنید:

https://dzone.com/articles/javafx-on-jdk-11
و اگر از maven استفاده میکنید :
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>

@this_java
var چیست؟

نوعی متغیر جدید که در java 10 معرفی شد و میتونه هر نوع مقداری رو توی خودش نگه داره... map عدد رشته لیست url و...
var list = List.of("A", "B", "C");
var copy = List.copyOf(list);
System.out.println(list == copy); // true
در سایت زیر میتونید اطلاعات بیشتری کسب کنید:
https://winterbe.com/posts/2018/09/24/java-11-tutorial/
@this_java