جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی

 

 

پیش فرض اعداد اعشاری در جاوا بصورت double است و نمیتوانید float num=12.5 را ارسال کنید و حتما باید بصورت 12.5f ارسال شود

 

 

 

تقسیم بر صفر : در تمامی حالت تولید Exception میکند تنها دو دیتا تایپ Float و Double هستند که در صورت تقسیم عدد بر صفر بی نهایت را نشان میدهند 

Float.NEGATIVE_INFINITY

Float.POSITIVE_INFINITY

Double.POSITIVE_INFINITY

Double.NEGATIVE_INFINITY

 

حالت مبهم اعداد : دو دیتا تایپ Float و Double حالت NaN یا مبهم میتوانند برای مقادیر تقسیم صفر بر صفر بگیرند

 

String Pool : زمانی که چندمتغیر String مقدار یکسانی داشته باشند جاوا یک مقدار را در نظر میگیرد و بقیه متغییر ها فقط به آن اشاره میکنند این برای صرفه جویی در حافظه است و فقط هم خاص String است

 

 String ها Immutable هستند و با دادن مقدار جدید ، مقدار قبلی روی حافظه رم قابل استفاده نیست و مقدار جدیدی در رم ایجاد میشود


قبل از اینکه GC ابجکت garbage شده را بردارد متد .finilize را صدا خواهد زد


وقتی از داده های Generic استفاده میکنیم مجاز نیستیم داده هایی از جنس پدر به فرزند assign کنیم Down Casting مجاز نیست ولی میتوانیم Up Casting داشته باشیم

        List<Integer> list = new ArrayList<>();

        Number num = 21;

        list.add(num);

کد بالا خطای compile time خواهد داشت



در یک کلاس میتوانیم کلاس های دیگری هم داشته باشیم ولی فقط یک کلاس میتواند public باشد و اسم فایل هم به نام آن تولید خواهد شد


Fast Fail : هرگاه یک ابجکت از نوع Collection داشته باشیم و مقادیر آن در حال دریافت باشد و توسط عامل دیگری تغییر کند یک شکست سریع اتفاق افتاده است

Collection c = new ArrayList(); 

Iterator itr = c.iterator(); 

c.add("An object"); 

String s = itr.next();

در این حالت Iterator نا معتبر میشود و خطای  ConcurrentModificationException پرتاب میشود

Auto Boxing : امکان تخصیص اتوماتیک مقادیر primitive به نوع متناظر Reference آن بدون new کردن از آن Object

َAuto Unboxing : امکان تخصیص اتوماتیک مقادیر Reference به نوع متناظر primitive بدون تبدیل کردن 


Up Cast : یا Widening به عمل ارجاع کردن یک کلاس فرزند به کلاس پدر (در درخت توارث از سمت فرزند به سمت پدر بالا میرویم ) که ایمن است چون تمای متد های فرزند در پدر موجود است و موقع call کردن مشکلی وجود ندارد

Down Cast : یا Narrowing به عمل ارجاع کردن یک کلاس پدر به کلاس فرزند (در درخت توارث از سمت پدر به سمت فرزند پایین میرویم ) که همیشه این کار به علت داشتن method  و field های احتمالی بیشتر در کلاس فرزند ، ایمن نیست چون همه متد های فرزند در پدرش ممکن وجود نداشته باشد و موقع call کردن آن متد پیاده سازی ندارد و آن متد و فیلد های فرزند از دسترس خارج خواهند شد چون در Object پدر وجود ندارند که Bind شوند ولی آن فیلد و متد ها در حافظه رم وجود خواهند داشت و اگر زمانی دوباره به Object فرزند cast شوند دوباره قابل استفاده خواهد شد


Mutable : کلاس هایی که field هایشان قابل تغییر هستند Mutable میگویند

Immutable : کلاس هایی که field هایشان تا زمانی که از بین بروند قابل تغییر نیست  Immutable میگویند به عبارتی متدی برای تغییر field ها وجود ندارد


component : به کلاس های تشکیل دهنده برنامه گفته میشود

java bean : به کلاس (component) های جاوا که یکسری قواعد مشخص و استاندارد در طراحی آن بکار گرفته شده باشد java bean میگویند

prototype : به ظاهر تعریف متد prototype میگویند


override : مخصوص متد است و رفتار و پیاده سازی به ارث برده را میتوان عوض کرد همین عمل در مورد فیلد ها hide گفته میشود 

overload : متدهایی با یک نام و آرگومان های متفاوت برای شرایط مختلف قابل استفاده است


abstract : پیاده سازی ندارد

concrete :  پیاده سازی شده است 


super class : به کلاس پدر در جاوا super class میگویند

sub class : به کلاس فرزند در جاوا sub class میگویند


Reference Object :  به Object پدر هم گفته میشود

Actual Object : به Object فرزند هم گفته میشود


Instance یا Object : در فضای heap یک بخشی به ازای کلاس ساخته شده باشد یک Instance یا Object داریم

Instance Variable : فیلد های کلاس که به ازای هر بار new شدن از کلاس یکی ساخته می شود و static نیستند

Class Variable : فیلد های کلاس که به ازای هر بار new شدن کلاس متغییر آن وجود دارد و static است

Final Method : متدی که قابلیت Override ندارد

Final Class : کلاس که دیگر قابل ارث بری نیست و نوع خاص تری ندارد مثلا کلاس singleton باید final باشد چون ممکن است در کلاس فرزند متد getInstance توسط فرزند override شود

Final Variable :  متغییری که مقدار آن قابل تغییر نباشد

ِDynamic Binding : در polymorphism وقتی ما متدی و یک Actual Object به Reference Object نسبت داده باشیم و مشخص نباشد که کد اجرا کننده آن متد کدام یک از متد های سلسله مراتب وراثت است (یعنی متغییر ما Object از نوع reference باشد و برای new شدن از یکی از Actual Object ها استفاده کرده باشیم و حاوی متد هایی باشد با modifier های public ,default , protected که static نباشد ، با توجه به سلسله مراتب Override شدن در وراثت صورت گرفته جاوا بصورت داینامیک)، اتصال متد مناسب در runtime به متد reference را dynamic binding میگویند

Static Binding : وقتی ما متدی داریم با modifier های final , static , private (بخاطر اینکه این سه override نمیشوند )و costractor در compile time آن متد مشخص است که به ازای فراخوانی آن چه کدی باید اجرا شود

به علت static binding بودن متد های private , final , static و costractor میتوان این نتیجه را گرفت که سرعت اجرا بالاتری نسبت به بقیه متد ها دارند و فقط اینا میتوانند inline شوند

inlining : در جاوا اگر مشخص باشد که به ازای متد کدام کد قرار است اجرا شود optimizer جاوا آن کد را inline میکند به جای فراخوانی آن متد 


Overloading Resolution : به تشخیص زبان به استفاده از یکی از متد های Overload شده با توجه به آرگومان های ارسالی Overloading Resolution میگویند


Dynamic Loading : در جاوا با استفاده از Reflection میتوان یک Object جدید تنها با دانستن اسمش آنرا ایجاد کرد :

 String str = (String) Class.forName("java.lang.String").newInstance();


Class Object : اطلاعات کلاس ما در حافظه در شی ای به نام Class Object ذخیره میشود تا قبل از جاوا 8 ، Class Object ها در بخشی از حافظه به نام (Permanent Generation (PermGen به معنای بخشی از حافظه که قرار است به صورت پایدار باقی بمانند ذخیره میشدند که این مشکل را بوجود می آوردند که اگر پروژه ما خیلی بزرگ بود ممکن بود این فضا پر شود و اجرای برنامه با خطا OutOfMemeoryError مواجه بشود این بیشتر برای پروژه هایی که مجبور بودند کتابخانه های زیادی از استفاده کنند دیده میشد البته راه کارهایی براش وجود داشت مثلا حجم حافظه PermGen را افزایش دهیم : java -XX:MaxPermSize=512m MyClass مشابه کاری که با سویچ های Xms- و Xmx- روی Heap انجام میشد

  ولی از جاوا 8 به بالاتر Class Object ها در بخشی از حافظه به نام MetaSpace نگهداری میشود و PermGen حذف شده و دیگر مشکلاتش را هم نداریم . MetaSpace تا جایی که حافظه جا داشته باشد اجازه استفاده را میدهد


Young : بخشی از حافظه Heap است که اشیاء جدید را نگهداری میکند

Tenured : بخشی از حافظه Heap است که اشیاء کهنه را نگهداری میکند


finalize : متدی است که در ابجکت Object موجود است و GC هنگامی که هیچ رفرنسی به آن ابجکت نباشد قبل از گاربیج کردن این متد را فراخوانی میکند و ما مثلا میتوانیم با override کردن این متد عملیاتی را انجام دهیم که به ندرت کاربرد دارد


atomic : عملیات اتمیک به عملیاتی گفته میشود که از ابتدا تا انتهای آن یکباره و بدون دخالت ترد دیگری یا انجام میشود و یا انجام نمیشود










JNI : وقتی بخواهیم یک کد native را فراخوانی کنیم از jni استفاده میکنیم با jni این امکان وجود دارد که یک متدی را با native modifier  تعریف کنیم و کد native مثلا c را از طریق آن اجرا کنیم ، سایر کلاس ها و متد ها آن کلاس را بصورت یک کد جاوا میبینند 


JNDI : یک API است که به برنامه های جاوا اجازه پیدا کردن یک Object از طریق آنها را میدهند .


HotSpot : این بخش به کمک JIT بصورت داینامیک کد های بایت کد جاوا را به کد ماشین تبدیل میکند و همواره کد های ماشین را برای performance برای اجرا های بعدی چک میکند و در صورت امکان از بهترین کد ماشین برای اجرا های بهتر بعدی استفاده میکن


JIT : قسمتی از HotSpot است که وقتی کد های جاوا به بایت کد ای کلاس تبدیل میشوند هنوز به زبان ماشین تبدیل نشده اند JIT در مقصد و جایی که قرار است کد ما اجرا شود بایت کد ها را به زبان ماشین ترجمه میکند



modifier ها در جاوا به دو دسته کلی تقسیم بندی میشوند :

آنهایی که سطح دسترسی را تعیین میکنند

آنهایی که تاثیر در عملیات میگذارند

 

public :

private :

protected :

default :

 

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


static : متد ها و فیلد های کلاس میتوانند این modifier را داشته باشند و هنگامی استفاده میشود که برای دسترسی به آن متد با فیلد نیازی به Object جدید نداریم و زمانی از این modifier روی متد استفاده میکنیم که این متد با هیچ فیلد و Object خاصی وابستگی نداشته باشد و برای کار نیازی نیست که data type ای در حافظه Allocate شود ، از داخل متد static به فیلد های non-static دسترسی نداریم و باید بصورت آرگومان دیتا ارسال شود متد ها و فیلد های این نوع دیگر بصورت dynamic لود نمیشوند و سرعت اجرای بالاتری را دارند


final : اگر روی کلاس تعریف شود آن کلاس قابل ارث بری نیست ، اگر روی متد تعریف شود آن متد قابل override شدن نیست و اگر روی متغیر های primitive استفاده شود مقدار متغییر قابل تغییر نیست و اگر روی متغیر های reference تعریف شوند instance جدید نمیتواند به آن متغیر منتسب شود 


synchronized : جهت استفاده در thread ها میتوان یک سری عملیات را بدون تداخل با thread دیگری در یک synchronized block اجرا کرد در حقیقت یک قفل اجرای موقتی که مجوز استفاده در لحظه تنها یک ترد را ایجاد میکند تا از ورود ترد ها دیگر و تداخل در عملیات جلوگیری شود


volatile :جهت استفاده در thread ها ، هر ترد هنگام انجام عملیات یک stack مختص به خود را دارد و وقتی با متغییر ها بخواهد کار کند یک cache از آنها ایجاد میکند و با آنها کار میکند حال یک ترد دیگر ممکن است اصلاعات متغیر را تغییر دهد و این میتواند خروجی عملیات ترد قبلی را نا معتبر کند برای جلوگیری از این حالت ، میتوان آن متغیر را از نوع volatile تعیین کرد و جاوا با این نوع متغیر ها بصورت atomic ( اتمیک بودن عملیات همانطور که در بحث دیتابیس های رابطه ای هم داریم یا کل عملیات یکباره انجام میشود و یا کل عملیات انجام نمیشود ) برخورد میکند یعنی هنگامی که متغیر در حال تغییر است بقیه ترد ها حق خواندن از آن متغییر را نخواهند داشت و وقتی که مقدار جدیدی به متغییر انتساب داده شد بقیه thread ها هم آنرا بصورت بروز شده میبینند در حقیقت جاوا اجازه نمیدهد که آن متغیر در stack/cache ترد ذخیره شود و آنرا در heap نگهداری میکند البته اینکار سرعت اجرا را به مراتب کند میکند اما در مالتی ترد بودن عملیات ، اطلاعات صحت خود را حفظ میکنند


- استفاده از کلمات کلیدی final  و volatile باهم تداخل خواهد داشت چون متغییری که از نوع volatile تعیین میشود به آن معناست که در آینده تغییراتی را میپذیرد


کاربرد volatile : هنگامی که یک shared resource داریم و میخواهیم آنرا بین ترد های مختلف به اشتراک بگذاریم عملی مشابه با بلاک های synchronized ولی تفاوت با آن چیست :

- در جاهایی که فقط تغییرات shared resoruce شامل خواندن و نوشتن روی یک متغییر است نوع متغییرهای atomic بسیار بهینه تر از synchronized عملی میکنند که عموما عملیات نوشتن (تغییر متغیر) توسط یک ترد و عملیات خواندن توسط تعداد زیادی صورت میگیرد

- در متغیرهای atomic قفل بر روی read/write یک متغییر گذاشته میشود ولی در بلاک های synchronized ما میتوانیم یک مجموعه عملیات را در یک بلاک بصورت اتمیک اجرا کنیم از این رو با بلاک synchronized میتوان مسایل بزرگتر و پیچیده تری را حل کرد


نکته : در سیستم های 32 بیتی متغییر های 64 بیتی مثل long و double  در دو آدرس حافظه 32 بیتی نگهداری میشوند و در هنگام تغییر مقادیر یک متغیر 64 بیتی عملیات آن atomic نیستند و هنگامی که 32 بیت اول در حال تغییر است میتواند 32 بیت دوم توسط ترد دیگری از قبل در حال تغییر باشد و باید حواسمان باشد که در برنامه های مالتی ترد در سیستم های 32 بیتی این نوع از متغییر ها را یا از نوع AtomicLong و ... استفاده کنیم و یا از نوع volatile


transient : هنگام عملیات Serializable فیلدهای transient ذخیره نمیشوند

native : برای متد هایی که از طریق JNI با native کد ها در ارتباط هستند

 


انتزاع یا abstraction یک مفهوم است و به دنبال معنی یک لغتی برای آن نباشید و باید آنرا درک کنید تا متوجه مفهوم آن شوید. همیشه این موضوع بین توسعه دهندگان محل اختلاف و بحث بوده اگر در ابتدای راه هستید به مرور متوجه کاربرد و درک مفهوم آن میشوید  .


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

هر ماشین با یک سرعت حداکثر توان حرکت کردن را دارد . سرعت صفتی است که همه ماشین ها آنرا دارند ماشینی که توان حرکت نداشته باشد یک ماشین کامل تلقی نمیشود


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


مفهوم abstraction از دو طریق در جاوا قابل اجراست کلاس های abstract و interface ها.



ادامه دارد ...

۰ نظر ۰۷ تیر ۹۸ ، ۱۸:۵۹
simple code