سلام! در حین مرور JavaRush، بیش از یک بار با انواع اولیه برخورد کردید. در اینجا لیست کوتاهی از آنچه در مورد آنها می دانیم آورده شده است:
اما، علاوه بر مقادیر، انواع در اندازه حافظه نیز متفاوت است.
نوع
- آنها اشیاء نیستند و مقدار ذخیره شده در حافظه را نشان می دهند
- انواع مختلفی از انواع اولیه وجود دارد:
- تمام اعداد -
byte
،short
،int
،long
- اعداد ممیز شناور (کسری) -
float
وdouble
- بولی -
boolean
- نمادین (برای نشان دادن حروف و اعداد) -
char
- تمام اعداد -
- هر یک از آنها محدوده مقادیر خاص خود را دارد:
نوع اولیه | اندازه در حافظه | محدوده ارزش ها |
---|---|---|
بایت | 8 بیت | -128 تا 127 |
کوتاه | 16 بیت | به -32768 تا 32767 |
کاراکتر | 16 بیت | از 0 تا 65536 |
بین المللی | 32 بیت | از -2147483648 تا 2147483647 |
طولانی | 64 بیت | از -9223372036854775808 تا 9223372036854775807 |
شناور | 32 بیت | از (2 به توان -149) تا ((2-2 به توان -23)*2 به توان 127) |
دو برابر | 64 بیت | از (2- به توان 63) تا ((2 به توان 63) - 1) |
بولی | 8 (هنگامی که در آرایه ها استفاده می شود)، 32 (در صورت استفاده در غیر آرایه ها) | درست یا غلط |
int
بیش از byte
. الف long
- بیش از short
. میزان حافظه اشغال شده توسط افراد اولیه را می توان با عروسک های تودرتو مقایسه کرد: فضای خالی در داخل عروسک تودرتو وجود دارد. هر چه عروسک تودرتو بزرگتر باشد، فضای بیشتری دارد. long
ما به راحتی می توانیم یک کوچکتر را داخل یک عروسک بزرگ تودرتو قرار دهیم int
. به راحتی جا می شود و نیازی به انجام کار اضافی ندارید. در جاوا هنگام کار با primitive ها به این حالت تبدیل خودکار می گویند. به نوعی دیگر به آن پسوند می گویند. در اینجا یک مثال پسوند ساده آورده شده است:
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
byte littleNumber = 16;
bigNumber = littleNumber;
System.out.println(bigNumber);
}
}
در اینجا یک مقدار byte
به یک متغیر اختصاص می دهیم int
. تخصیص موفقیت آمیز و بدون هیچ مشکلی انجام شد: مقدار ذخیره شده در byte
فضای حافظه کمتری را اشغال می کند int
. "عروسک لانه سازی کوچک" (ارزش byte
) به راحتی در "ماتریوشکای بزرگ" (متغیر int
) قرار می گیرد. زمانی که سعی می کنید برعکس این کار را انجام دهید موضوع دیگری است - یک مقدار بزرگ را در متغیری قرار دهید که برای چنین اندازه هایی طراحی نشده است. در اصل، این ترفند با عروسک های تودرتو واقعی کار نمی کند، اما در جاوا کار می کند، اما با تفاوت های ظریف. بیایید سعی کنیم مقداری را int
در یک متغیر قرار دهیم short
:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = bigNumber;//error!
System.out.println(bigNumber);
}
خطا! کامپایلر متوجه می شود که شما سعی می کنید کاری غیر استاندارد انجام دهید و یک عروسک بزرگ ماتریوشکا ( int
) را داخل یک عروسک کوچک ( short
) قرار دهید. یک خطای کامپایل در این مورد یک هشدار از طرف کامپایلر است: " هی، مطمئنی که میخواهی این کار را انجام دهی؟ "اگر مطمئن هستید، به کامپایلر در مورد آن بگویید: " همه چیز خوب است، من می دانم که دارم چه کار می کنم!" این فرآیند را تبدیل نوع صریح یا باریک کردن می نامند . برای باریک کردن، باید صریحاً نوع مورد نظر خود را مشخص کنید. به عبارت دیگر، به سوال کامپایلر پاسخ دهید: " خب، میخواهید این عروسک بزرگ را در کدام یک از این عروسکهای کوچک قرار دهید؟" در مورد ما به این صورت خواهد بود:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = (short) bigNumber;
System.out.println(littleNumber);
}
ما به صراحت نشان دادیم که میخواهیم مقدار را int
در یک متغیر قرار دهیم short
و مسئولیت آن را بر عهده بگیریم. کامپایلر با دیدن نشانه ای صریح از نوع باریک تر، تبدیل را انجام می دهد. نتیجه چه خواهد شد؟ خروجی کنسول: -27008 کمی غیرمنتظره. چرا دقیقا اینطوری؟ در واقع ساده است. ما مقدار اصلی را داشتیم - 10000000 در متغیری ذخیره شده بود int
که 32 بیت را اشغال می کرد و به شکل باینری به این صورت بود: ما این مقدار را روی متغیر می نویسیم short
، اما فقط می تواند 16 بیت را ذخیره کند! بر این اساس، تنها 16 بیت اول شماره ما به آنجا منتقل می شود، بقیه حذف می شوند. در نتیجه، متغیر short
حاوی مقدار خواهد بود که به صورت اعشاری دقیقاً برابر با -27008 است، به همین دلیل است که کامپایلر در قالب یک ارسال صریح به یک نوع خاص، "تایید درخواست کرد". اولاً نشان میدهد که شما مسئولیت نتیجه را به عهده میگیرید و ثانیاً به کامپایلر میگوید که چه مقدار فضایی را هنگام ریختهگری انواع اختصاص دهد. int
به هر حال، اگر در مثال آخر، به تایپ byte
، و نه به cast داده بودیم short
، فقط 8 بیت در اختیار داشتیم، نه 16، و نتیجه متفاوت بود. برای انواع کسری ( float
و double
)، باریک شدن به طور متفاوتی اتفاق می افتد. اگر بخواهید چنین عددی را به یک نوع صحیح تبدیل کنید، قسمت کسری آن حذف می شود.
public static void main(String[] args) {
double d = 2.7;
long x = (int) d;
System.out.println(x);
}
خروجی کنسول: 2
نوع داده char
قبلاً می دانید که نوع char برای نمایش کاراکترهای جداگانه استفاده می شود.public static void main(String[] args) {
char c = '!';
char z = 'z';
char i = '8';
}
اما تعدادی ویژگی دارد که درک آنها مهم است. بیایید دوباره به جدول با محدوده مقادیر نگاه کنیم:
نوع اولیه | اندازه در حافظه | محدوده ارزش ها |
---|---|---|
بایت | 8 بیت | -128 تا 127 |
کوتاه | 16 بیت | -32768 تا 32767 |
کاراکتر | 16 بیت | از 0 تا 65536 |
بین المللی | 32 بیت | از -2147483648 تا 2147483647 |
طولانی | 64 بیت | از -9223372036854775808 تا 9223372036854775807 |
شناور | 32 بیت | از (2 به توان -149) تا ((2-2 به توان -23)*2 به توان 127) |
دو برابر | 64 بیت | از (2- به توان 63) تا ((2 به توان 63)-1) |
بولی | 8 (هنگامی که در آرایه ها استفاده می شود)، 32 (در صورت استفاده در غیر آرایه ها) | درست یا غلط |
char
دارای محدوده عددی از 0 تا 65536 است. اما این به چه معناست؟ از این گذشته ، char
اینها فقط اعداد نیستند ، بلکه حروف ، علائم نقطه گذاری نیز هستند ... واقعیت این است که مقادیر char
در جاوا در قالب یونیکد ذخیره می شوند. قبلا در یکی از سخنرانی های قبلی با یونیکد مواجه شده بودیم. احتمالاً به یاد دارید که یونیکد یک استاندارد رمزگذاری کاراکتر است که شامل کاراکترهایی از تقریباً تمام زبان های نوشتاری جهان است. به عبارت دیگر، این لیستی از کدهای ویژه است که در آن کدی برای تقریباً هر کاراکتر از هر زبانی وجود دارد. جدول کلی یونیکد بسیار بزرگ است و البته نیازی به یادگیری از روی قلب ندارد. به عنوان مثال، بخشی از آن در اینجا آمده است: نکته اصلی درک اصل ذخیره مقادیر است char
و به یاد داشته باشید که با دانستن کد یک نماد خاص، همیشه می توانید آن را در برنامه دریافت کنید. بیایید این را با تعدادی عدد تصادفی امتحان کنیم:
public static void main(String[] args) {
int x = 32816;
char c = (char) x ;
System.out.println(c);
}
خروجی کنسول: 耰 این فرمتی است که کاراکترها در جاوا ذخیره می شوند char
. هر کاراکتر مربوط به یک عدد است - یک کد عددی 16 بیتی یا دو بایتی. یونیکد 32816 با کاراکتر 耰 مطابقت دارد. به این لحظه توجه کنید. در این مثال از متغیر استفاده کردیم int
. 32 بیت حافظه را اشغال می کند در حالی که char
16 بیت . در اینجا ما انتخاب کردیم زیرا شماره مورد نیاز ما، 32816، خارج از محدوده است . اگرچه اندازه ، مانند کوتاه، 16 بیت است، اما هیچ عدد منفی در محدوده وجود ندارد، بنابراین محدوده "مثبت" دو برابر بزرگتر است (65536 به جای 32767 ). تا زمانی که کد ما در محدوده 65536 قرار می گیرد، می توانیم استفاده کنیم . اما اگر یک عدد ایجاد کنیم ، بیش از 16 بیت را اشغال می کند. و هنگام محدود کردن انواع: int
short
char
char
char
short
int
int >65536
char c = (char) x;
بیت های اضافی دور ریخته می شوند و نتیجه کاملا غیرمنتظره خواهد بود.
ویژگی های جمع کردن کاراکتر و اعداد صحیح
بیایید به این مثال غیر معمول نگاه کنیم:public class Main {
public static void main(String[] args) {
char c = '1';
int i = 1;
System.out.println(i+c);
}
}
خروجی کنسول: 50 O_O منطق کجاست؟ 1+1 50 از کجا اومده؟! قبلاً می دانید که مقادیر char
به عنوان اعداد در محدوده 0 تا 65536 در حافظه ذخیره می شوند که نشان دهنده یونیکد کاراکتر ما است. پس اینجاست. وقتی جمع را انجام می دهیم char
و مقداری عدد صحیح char
به عددی که در یونیکد به آن مربوط می شود تبدیل می شود. وقتی در کد ما 1 و '1' را اضافه کردیم، نماد '1' به کد آن تبدیل شد که 49 است (شما می توانید آن را در جدول بالا بررسی کنید). بنابراین، نتیجه برابر با 50 شد. اجازه دهید یک بار دیگر دوست قدیمی خود -耰 را به عنوان مثال در نظر بگیریم و سعی کنیم آن را با یک عدد جمع کنیم.
public static void main(String[] args) {
char c = '耰';
int x = 200;
System.out.println(c + x);
}
خروجی کنسول: 33016 قبلاً متوجه شده ایم که耰مربوط به کد 32816 است. و وقتی این عدد و 200 را اضافه می کنیم، دقیقاً نتیجه خود را می گیریم - 33016 :) مکانیسم عملکرد، همانطور که می بینید، بسیار ساده است.
GO TO FULL VERSION