مرحبًا! أثناء تصفحك لـ 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
. تناسبها بسهولة ولا تحتاج إلى القيام بأي شيء إضافي. في Java، عند العمل مع العناصر الأولية، يُسمى هذا بالتحويل التلقائي. وبطريقة أخرى يطلق عليه امتدادا. فيما يلي مثال تمديد بسيط:
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
وليس إلى 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 يُستخدم لعرض الأحرف الفردية.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
يتم تخزينها في Java بتنسيق Unicode. لقد واجهنا Unicode بالفعل في إحدى المحاضرات السابقة. ربما تتذكر أن Unicode هو معيار لترميز الأحرف يتضمن أحرفًا من جميع اللغات المكتوبة في العالم تقريبًا. بمعنى آخر، هذه قائمة بالرموز الخاصة التي تحتوي على رمز لأي حرف تقريبًا من أي لغة. جدول Unicode العام كبير جدًا، وبالطبع لا يحتاج إلى حفظه عن ظهر قلب. هنا، على سبيل المثال، جزء منه: الشيء الرئيسي هو فهم مبدأ تخزين القيم char
، وتذكر أنه بمعرفة رمز رمز معين، يمكنك دائمًا الحصول عليه في البرنامج. دعونا نجرب هذا مع بعض الأرقام العشوائية:
public static void main(String[] args) {
int x = 32816;
char c = (char) x ;
System.out.println(c);
}
إخراج وحدة التحكم: هذا هو التنسيق الذي يتم تخزين الأحرف به في Java char
. يتوافق كل حرف مع رقم - رمز رقمي مكون من 16 بت، أو بايتين. Unicode 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، مما يمثل Unicode لشخصيتنا. حتى هنا هو عليه. عندما نقوم بإجراء عملية الجمع ويتم تحويل char
بعض أنواع الأعداد الصحيحة char
إلى الرقم الذي يتوافق معها في Unicode. عندما أضفنا 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