تیکه پاره های جاوا
528 subscribers
93 photos
24 videos
7 files
58 links
سلام خوش اومدید. اینجا یادداشت ها و تکه های جاوا رو کنار هم قرار میدیم :) مطالب کاملا اختصاصی و دستنویس هستند. کپی فقط با ذکر منبع و آیدی کانال❤️

📝برای تدریس پیام دهید
محمدرضا عظیمی‌فرد
🆔 @mrvj475
Download Telegram
💎معنی Mutable و Immutable بودن کلاس ها (قابل تغییر و غیر قابل تغییر بودن)

🔅به آبجکت هایی که بعد از ایجاد شدن قابل تغییر هستند، Mutable گفته میشود. برای مثال کلاس Date یا StringBuilder
🔅در مقابل به ابجکت هایی که پس از ایجاد شدن قابل تغییر نیستند، Immutable گفته میشود. برای مثال کلاس String, Integer, Long,...

🔰 نمونه کلاس String:

String str = "Test";
str.replaceAll("T","s);
System.out.println(str)
;//prints Test

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

🔆تفاوت های کلاس های Mutable و Immutable
⭕️در کلاس های Mutable فیلد ها بعد از ایجاد ابجکت قابل تغییر هستند در صورتی که در کلاس های Immutable چنین چیزی ممکن نیست.

⭕️کلاس های Mutable دارای متد هایی برای تغییر مقادیر فیلد ها مانند setter & getter هستند. در صورتی که کلاس های Immutable فقط دارای متد های getter میباشند.

⁉️چرا بعضی از کلاس ها Immutable هستند و یا چرا باید باشند؟
- همانطور که گفتیم مقادیر این کلاس ها غیر قابل تغییر است و از لحاظ مدیریت حافظه بصرفه است.
- کلاس های Immutable اصطلاحا Thread Safe هستند (در محیط های چند نخی (multithreading)) در واقع Thread safety به فرایند امن سازی برنامه در محیط های چند نخی گفته میشود.
🔗 نحوه ایجاد کلاس Immutable

#immutable #mutable #threadsafe #thread_safe #StringBuilder #Date #String

@pieceJava
👍3
💎 کلیدواژه final

🔆کلیدواژه فاینال برای محدود کردن کاربرد یک متغیر، متود یا یک کلاس به کار میرود که البته در هر کدام از این موارد، کاربرد متفاوت است.

⭕️ اگر یک متغیر را فاینال تعریف کنیم، به این معناست که پس از مقدار دهی اولیه، مقدار متغیر دچار تغییرات نخواهد شد و مقدار دهی دوباره آن، خطای کمپایلر را به همراه خواهد داشت:
final int length = 5;


⭕️ اگر یک کلاس را فاینال تعریف کنیم، توسط هیچ کلاسی قابل ارث بری نخواهد بود (فاینال تعریف کردن یک کلاس به معنی Immutable کردن این کلاس نیست. زیرا فقط از ارث بری شدن جلوگیری میکند.)
final class Test{ }


⭕️ اگر یک متد را فاینال تعریف کنیم، توسط هیچ زیرکلاسی قابل اورراید کردن نخواهد بود. یا به عبارتی بدنه متد تحت هیچ شرایطی در زیرکلاس ها تغییر نخواهد کرد.
final void method(){ }

⭕️ اگر یک آرگومان را فاینال تعریف کنیم، این به این معناست که مقدار آن در بدنه متد قابل تغییر نمیباشد.
public void methodWithFinalArguments(final int x) {
x=1;
}
برای مثال، تکه کد بالا خطای کمپایلر را خواهد داشت.

#final #keywords

@pieceJava
👍3
💎نحوه ایجاد کلاس Immutable

🔗(در مورد ویژگی کلاس های Immutable از اینجا بخوانید )
🔅برای ایجاد کلاس های Immutable باید یک سری شرایط برقرار باشد:
⭕️کلاس نباید قابل ارث بری باشد. به همین منظور کلاس را فاینال تعریف میکنیم.
⭕️فیلد ها و داده های کلاس باید پرایوت باشند. در این صورت دسترسی فقط از طریق متد ها امکان پذیر خواهد بود.
⭕️فیلد ها و داده های کلاس باید فاینال باشند. در اینصورت فقط یکبار قابل مقدار دهی خواهند بود.
⭕️مقدار دهی فیلد ها فقط از طریق سازنده (constructor) باید صورت گیرد.
⭕️کلاس باید فقط دارای متد گتر باشد. برای بازگرداندن مقدار ترجیحا یک مقدار کپی از فیلد برگردانده شود.

🔰مثال:
final class Immutable{
private final int instanceNumber;
public Immutable(int instanceNumber) {
this.instanceNumber = instanceNumber;
}
public int getInstanceNumber() {
return instanceNumber;
}
}

@pieceJava
👍3
💎ساختار for-each در جاوا

🔆 در جاوا ساختار کلاسیک حلقه فور از سه بخش تشکیل شده است. بخش مقدار دهی شمارنده، شرط حلقه و تعداد گام های شمارنده برای رسیدن به پایان حلقه:
for (initialization; boolean-condition; step) {
statement;
}

🔅 یک حالت دیگه از فور وجود دارد که اصطلاحا به آن for each (Enhanced for / فور بهبود یافته) گفته میشود که البته برای پیمایش آرایه یا کالکشن ها مانند آری لیست، لینک لیست و ... کاربرد دارد. ضمنا برای مقدار دهی آرایه یا کالکشن ها ، این ساختار مناسب نمیباشد زیرا به ایندکس دسترسی نداریم.

ساختار for each:
for (data_type var_name : array | collection) {
// code
}

در این نوع ساختار از حلقه فور، در هر بار پیمایش بترتیب ابجکت هارا در یک خانه از حافظه (توی مثال بالا یعنی بجای data_type ) ذخیره و در ساختار استفاده میشود:
public class pieceJava {
public static void main(String[] args)
{
int[] array = {1,2,5,4,7,5};
for(int i: array)
{
System.out.print(i+"\t");
}
}
}
/////Output: 1 2 5 4 7 5

در رابطه با کالکشن ها نیز به همین صورت میتوان پیمایش را انجام داد:
import java.util.ArrayList;

public class pieceJava {
//Telegram: @pieceJava
public static void main(String[] args)
{
ArrayList<Data> datas = new ArrayList<>();
datas.add(new Data(5));
datas.add(new Data(6));
datas.add(new Data(7));
datas.add(new Data(8));
datas.add(new Data(9));

for(Data data: datas)
{
System.out.print(data.getData()+"\t");
}

}
}
class Data{
private int data;
public Data(int data)
{
this.data = data;
}
public int getData() {
return data;
}
}
//output: 5 6 7 8 9
————
#for #for_each #enhanced #enhanced_for

@pieceJava
👍2
تیکه پاره های جاوا pinned «💎 مقایسه اشیا (ابجکت ها) در جاوا 🔆 توی جاوا هر کلاس بصورت پیشفرض از کلاس Object ارث بری میکند. کلاس Object شامل متد هایی مثل hashCode, equals, toString و... میشود که کاربرد گسترده ای در رابطه با کار با ابجکت ها دارند. به همین منظور برای مقایسه ابجکت ها از…»
💎چطور سازنده ها را بهم متصل کنیم؟ (Chaining Constructors)

⚙️ برای ایجاد ارتباط میان سازنده ها (کنستراکتور) دو حالت وجود دارد:
👈 اتصال سازنده ها در یک کلاس
👈 اتصال سازنده های سوپر کلاس در زیر کلاس


🔅 اتصال سازنده ها در یک کلاس
در این حالت از کلیدواژه this() استفاده میکنیم. در واقع this در این مورد اشاره به سازنده های کلاس دارد.(برای خوانایی بهتر کد صفحه را در حالت افقی نگه دارید):

class Chaining{
private String firstname;
private int age;
private String lastname;
//first constructor
public Chaining(String firstname,String lastname)
{
this.firstname = firstname;
this.lastname = lastname;
}
//chaining constructors
public Chaining(int age,String firstname,String lastname){
this(firstname,lastname);
this.age = age;
}
}
در این مثال در بدنه سازنده دوم بوسیله کلیدواژه this به سازنده اول اشاره کرده ایم و مقادیر ورودی را به سازنده اول بوسیله کلیدواژه this نسبت داده ایم.

💡ضمنا با توجه به ورودی هر سازنده، میتوان مشخص کرد که this دقیقا به کدام سازنده اشاره دارد
🔰برای مثال:
class Temp {
public Temp() {
// calls constructor 2
this(5);
System.out.println("The Default constructor");
}

// parameterized constructor 2
public Temp(int x) {
// calls constructor 3
this(5, 15);
System.out.println(x);
}

// parameterized constructor 3
public Temp(int x, int y) {
System.out.println(x * y);
}
}

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


🔅 اتصال سازنده های سوپر کلاس در زیر کلاس
برای اینکار از کلیدواژه super استفاده میشود. ضمنا تمامی قوانین در رابطه با this ، برای super نیز برقرار است:
class SuperClass{
private String firstName;
private String lastName;
public SuperClass(String firstName,String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
}

class Chaining extends SuperClass{
private int age;
public Chaining(String firstName, String lastName,int age) {
super(firstName, lastName);
this.age = age;
}
}

———
#chaining #constructor #this #super
@pieceJava
👍2
💎بررسی مقدار و کلیدواژه null در جاوا


🔆 یکی از کلمات رزرو شده در جاوا کلمه null میباشد. مقدار null فقط مختص داده های مرجع میباشد. زمانی که یک شی از یک داده مرجع (Reference type) مقدار دهی نشده باشد (به هیچ خانه ای از حافظه اشاره نکند) بصورت پیشفرض مقدار اولیه آن برابر null خواهد بود.
🔰برای مثال:
public class ITHOOLOO {
private static Object object;
public static void main(String[] args) {
System.out.println(object);
}
}
خروجی نال را خواهد داشت. زیرا شی مقدار دهی نشده است.

🔅ویژگی های نال:
⭕️ کلیدواژه null حتما باید با حروف کوچک نوشته شود زیرا در غیر این صورت کمپایلر در شناسایی آن به مشکل خواهد خورد.

⭕️ همانطور که پیش تر نیز اشاره کردیم، مقدار null مختص داده های مرجع میباشد و در صورت اختصاص به داده های نوع پیشین (primitive data types) خطای کمپایلر را به همراه خواهد داشت:
int a = null; //error

⭕️مقدار پیشفرض هر داده مرجع (رفرنس، reference) پیش از مقدار دهی نال میباشد.

⭕️ از آنجا که نال یک مقدار خاص میباشد، میتواند به انواع داده های مرجع نیز تبدیل شود:
// Typecasting null to String type
String myStr = (String) null;
// Typecasting to an Integer class
Integer myItr = (Integer) null;
// Typecasting to a Double class
Double myDbl = (Double) null;
⭕️تلاش برای دسترسی به یک آبجکت نال استثنای NullPointerException را به همراه خواهد داشت. برای مثال پیمایش آرایه ای از ابجکت ها (اشیا) که شامل یک یا چند ابجکت نال باشد. در حین پیمایش، زمانی که حلقه به آبجکت نال برخورد کرد، اسثتنای NullPointerException رخ میدهد

⭕️ یکی از اپراتور های جاوا instanceof میباشد که بررسی میکند آیا یک ابجکت نمونه ای از یک کلاس هست یا خیر. برای مثال:
public class ITHOOLOO {
public static void main(String[] args) {
Object a = new Object();
System.out.println(a instanceof Object);
}
}
مقدار ترو را برمیگرداند زیرا a یک شی (ابجکت) از کلاس Object میباشد. حال اگر مقدار یک ابجکت null باشد، در بررسی با اپراتور instanceof مقدار فالس بازگشت میدهد. این نشان میدهد که null به معنای هیچ است. یعنی هیچ خانه ای در حافظه به ابجکت ساخته شده اختصاص داده نشده است:
public class ITHOOLOO {
public static void main(String[] args) {
Integer b = null;
System.out.println(b instanceof Integer);//return false
}
}

#null #nullpointerException #instanceof

@pieceJava
👍4
💎 کلاس Scanner و متد هایuserDelimeter و delimeter

🔆 همانطور که میدانید، کلاس اسکنر برای خواندن داده های ورودی کاربرد دارد. برای مثال برای هر کدام از ورودی های از نوع اینتجر، دابل، استرینگ و... کلاس اسکنر متد هایی را فراهم کرده است.

🔅یکی از متد های پر کاربرد کلاس Scanner، متد useDelimeter میباشد. بوسیله ی این متد میتوان یک جداکننده برای داده ورودی در نظر گرفت. برای مثال "," را جدا کننده رشته "Hello,From,ITHOOLOO" قرار میدیم و ورودی هارو چاپ میکنیم:
import java.util.Scanner;

public class ITHOOLOO {
public static void main(String[] args) {
String text = "HELLO,FROM,ITHOOLOO";
Scanner input = new Scanner(text);
input.useDelimiter(",");
while(input.hasNext())
{
System.out.println(input.next());
}
}
}
در این صورت خروجی به صورت زیر خواهد بود:
HELLO
FROM
ITHOOLOO
💡متد delimeter جدا کننده را برگشت میدهد:
input.delimiter(); // return ,

⭕️ یکی از کاربرد های useDelimeter در هنگام خواندن فایل و جدا کردن داده ها میباشد.
🔰برای مثال:
فرض کنید یک فایل در زیرشاخه src به نام test.txt داریم که شامل رشته زیر میباشد:
Mohammad,23,Iran

حال برای خواندن و ذخیره اطلاعات داریم:
public class ITHOOLOO {
public static void main(String[] args) {
File file = new File("src\\Test.txt");
String name = "";
int age = 0;
String country = "";
Scanner input = null;
try {
input = new Scanner(file);
input.useDelimiter(",");
while(input.hasNext())
{
name = input.next();
age = Integer.parseInt(input.next());
country = input.next();
}

} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(input!=null)
input.close();
}
System.out.println(name);
System.out.println(age);
System.out.println(country);
}
}
در این مثال خروجی بصورت زیر خواهد بود:
Mohammad
23
Iran
#scanner #delimeter #useDelimeter

@pieceJava
👍3
💎 داده های نوع پیشین و داده های مرجع
📝 #سوالات_مصاحبه

🔆داده های نوع پیشین (Primitive data types)
⭕️داده های نوع پیشین عبارتند از :
byte, boolean, char, short, int ,float, long , double

⭕️داده های نوع پیشین همیشه یک مقدار ذخیره دارند. اگر مقدار دهی نشده باشند، یک مقدار پیشفرض خواهند داشت. البته این مقدار پیش فرض مختص متغیر های نمونه ای هست که در سطح کلاس تعریف میشوند و متغیر های محلی که در یک بلاک کد تعریف میشوند، بطور خودکار هیچ مقدار پیشفرضی ندارند و شما پیش از استفاده باید آن را مقدار دهی کنید.
⭕️وجه تمایز بین داده long و int ، حرف L (یا l اِل کوچک)میباشد که آخر عدد اضافه میشود. حرف L نشاندهنده نوع داده long میباشد.
⭕️وجه تمایز بین داده float و double، حرف F(یا f کوچک) میباشد که بعد از عدد اعشاری برای داده فلوت به کار برده میشود. به همین صورت برای متغیر double میتوان بعد از عدد حرف D (یا d) قرار داد.
⭕️اختصاص یک داده نوع پیشین به یک متغیر، باعث ذخیره یک کپی از داده در متغیر خواهد شد:
int x = 4;
int y = x;


🔆داده های مرجع (reference data types / non-primitive data types)
⭕️داده های مرجع شامل تمامی داده ها غیر از داده های نوع پیشین میباشد.
⭕️داده های نوع مرجع بعنوان اشیا (objects) شناخته میشوند.
⭕️داده های مرجع در واقع به یک خانه از حافظه اشاره میکنند.
⭕️برای یک داده مرجع در صورتی که تعریف نشده باشد، مقدار null تعلق میگیرد.
⭕️داده های مرجع (اشیا) شامل متغیر ها و متد ها میشوند که وضعیت و رفتار شی ساخته شده را تعریف میکنند.
⭕️زمانی که یک داده مرجع به یک داده دیگر نسبت داده میشود، در این صورت هر دو به یک خانه از حافظه اشاره میکنند و کپی ایجاد نمیشود. این به این معناست که هر تغییر در ابجکت دوم، ابجکت اول را هم دچار تغییر میکند:
class myClass{
String name;
}

class Main{
public static void main(String[] args){
Class o1 = new Class();
Class o2 = o1;
o2.name = "Object Name";
System.out.println(o1.name);//prints Object Name
}
}
در مثال بالا هر چند که مقدار ابجکت o2 را تغییر داده ایم ولی از آنجا که هر دو ابجکت به یک خانه از حافظه اشاره میکنند، این تغییر باعث میشود که o1 نیز دچار تغییر شود.

(⁉️) سوالات:
داده نوع پیشین چیست؟
اگر به داده نوع پیشین مقداری نسبت داده نشود، چه مقداری در متغیر ذخیره خواهد شد؟
پیشوند های D و F و L به ترتیب برای کدام داده ها و چرا به کار میروند؟
اگر که یک داده پیشین به داده پیشین دیگر نسبت دهیم چه اتفاقی خواهد افتاد؟
داده مرجع چیست؟
اگر که یک داده مرجع را به داده مرجع دیگر نسبت دهیم چه اتفاقی خواهد افتاد؟
تفاوت داده مرجع و داده نوع پیشین را توضیح دهید؟
هدف از نوشتن متدها و متغیر در داده های مرجع چیست؟
اگر داده مرجع مقدار دهی نشود، بصورت پیشفرض چه مقداری در بر میگیرد؟

#primitive #reference #dataTypes #data_types #primitive_data
@pieceJava
👍3
💎تفاوت پیش افزاینده و پس افزاینده در جاوا

🔅 پس افزاینده (Post-Increment ) زمانی مناسب است که قرار باشد از مقدار فعلی داده استفاده و سپس مقدار داده افزایش پیدا کند.
🔰برای مثال:
int i = 1;
System.out.println(i++); // prints 1
System.out.println(i); // prints 2


🔅 پیش افزاینده (Pre-Increment) بر خلاف پس افزاینده زمانی مناسب است که قرار باشد مقدار فعلی را افزایش و سپس استفاده کنیم.
🔰برای مثال:
int i = 1;
System.out.println(++i);// prints 2
System.out.println(i); // prints 2

#increment
@pieceJava
👍2
💎 مفهوم استخر رشته (String pool) و کارایی آن در جاوا

🔆 همانطور که میدانید رشته ها از نوع داده مرجع میباشند و هر داده مرجع برای ایجاد شدن هم از لحاظ زمان و هم حافظه هزینه بر است. یکی از راه هایی که در جهت بهینه سازی این موضوع بکار برده شده است، بوجود آوردن استخر رشته (String pool) است. پیش از آنکه این مفهوم را بررسی کنیم، اجازه دهید به نحوه ایجاد رشته ها در جاوا بپردازیم. در جاوا به دو صورت میتوان رشته ایجاد کرد:

⭕️ ذخیره مستقیم رشته بصورت یک ثابت :
String str = "ITHOOLOO";
💡
به این نوع رشته ها، لیترال گفته میشود (String literal)


⭕️ تعریف رشته بوسیله ی کلیدواژه new:
String str2 = new String("ITHOOLOO");


حال اگر رشته سومی با مقدار تکراری داشته باشیم:
String str3 = "ITHOOLOO";

در این صورت خواهیم داشت:
System.out.println(str==str2); //false
System.out.println(str==str3); // true
System.out.println(str2==str3); // false

دلیل برابری رشته اول و سوم به مفهوم استخر رشته برمیگردد.

🔆 استخر رشته:
همان
طور که گفتیم در جهت بهینه سازی در هزینه، هر بار که یک رشته لیترال ایجاد میکنیم، JVM بررسی میکند که آیا در استخر رشته، رشته مشابه وجود دارد یا خیر. در صورت وجود آدرس رشته تکراری را برگشت میدهد و در غیر اینصورت آن را در استخر رشته ایجاد میکند. در نتیجه دلیل برابری رشته اول و سوم به این خاطر میباشد که در حافظه هر دو به یک آدرس مراجعه میکنند. اما کلیدواژه new یک ابجکت جدا ایجاد میکند و از آنجا که هر دو رشته دو آدرس متفاوت دارند، نتیجه مقایسه == برابر فالس میشود.

💡 برای مقایسه رشته ها بهتر است از متد equals و یا compareTo استفاده شود.
🔗 نحوه صحیح مقایسه رشته ها
🔗 کلاس های Immutable و Mutable
🔗 چرا رشته ها غیر قابل تغییر یا Immutable هستند
👍4
#چرا
💎چرا رشته ها غیر قابل تغییر یا Immutable هستند؟
در مورد Immutable و Mutable بودن کلاس ها از اینجا بخوانید.
فرض کنید رشته ای بصورت زیر داریم:
String str = "Hello";

حال بوسیله متد concat یک رشته را به رشته فعلی اضافه میکنیم:
str.concat(" World");
و در نهایت از رشته تولید شده خروجی میگیریم:
System.out.println(str);
خروجی مثال بالا همان رشته Hello خواهد بود. این موضوع به غیر قابل تغییر بودن رشته ها برمیگردد. در واقع در سطح حافظه رشته Hello World ایجاد شده است. اما رشته فعلی همچنان به خانه قبلی در حافظه اشاره میکند. برای ارجاع به ادرس جدید، الحاق رشته باید بصورت زیر انجام شود:
str = str.concat(" World");

در این صورت خروجی زیر برابر با Hello World خواهد بود:
System.out.println(str);


چرا رشته ها غیر قابل تغییر هستند؟

⭕️ فرض کنید چند رشته لیترال داشتیم که هر کدام فقط به یک خانه از حافظه اشاره میکردند. حال اگر مقدار یکی از رشته ها را به اینصورت تغییر دهیم، این تغییر باقی رشته ها را تحت تاثیر قرار میداد.

⭕️ غیر قابل تغییر بودن رشته ها در مدیریت حافظه نیز تاثیر دارد. (از اینجا بخوانید)
👍7