JavaRush /จาวาบล็อก /Random-TH /การหล่อ (การแปลง) ประเภทดั้งเดิมใน Java

การหล่อ (การแปลง) ประเภทดั้งเดิมใน Java

เผยแพร่ในกลุ่ม
สวัสดี! ในขณะที่ใช้งาน JavaRush คุณเจอประเภทดั้งเดิมมากกว่าหนึ่งครั้ง ต่อไปนี้เป็นรายการสั้นๆ เกี่ยวกับสิ่งที่เรารู้เกี่ยวกับพวกเขา:
  1. ไม่ใช่วัตถุและแสดงถึงค่าที่จัดเก็บไว้ในหน่วยความจำ
  2. ประเภทดั้งเดิมมีหลายประเภท:
    • จำนวนทั้งหมด - byte, short, int,long
    • จำนวนจุดลอยตัว (เศษส่วน) - floatและdouble
    • บูลีน -boolean
    • สัญลักษณ์ (เพื่อระบุตัวอักษรและตัวเลข) -char
  3. แต่ละคนมีช่วงค่าของตัวเอง:
ประเภทดั้งเดิม ขนาดในหน่วยความจำ ช่วงของค่า
ไบต์ 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. จำนวนหน่วยความจำที่ครอบครองโดยสิ่งมีชีวิตดึกดำบรรพ์สามารถเปรียบเทียบได้กับตุ๊กตาทำรัง: การขยายและการหดตัวของประเภทดั้งเดิม - 2 มีพื้นที่ว่างภายในตุ๊กตาทำรัง ยิ่งตุ๊กตาทำรังมีขนาดใหญ่ก็ยิ่งมีพื้นที่มากขึ้น 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) เป็นอีกเรื่องหนึ่งเมื่อคุณพยายามทำสิ่งที่ตรงกันข้าม - ใส่ค่าจำนวนมากลงในตัวแปรที่ไม่ได้ออกแบบมาสำหรับขนาดดังกล่าว โดยหลักการแล้ว เคล็ดลับนี้ใช้ไม่ได้กับตุ๊กตาทำรังจริง แต่ใน Java มันจะได้ผล แต่มีความแตกต่างเล็กน้อย ลองใส่ค่าลงintในตัวแปรshort:
public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = bigNumber;//error!
   System.out.println(bigNumber);
}
ข้อผิดพลาด! คอมไพเลอร์เข้าใจว่าคุณกำลังพยายามทำสิ่งที่ไม่ได้มาตรฐาน และใส่ตุ๊กตา matryoshka ขนาดใหญ่ ( 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 บิตและในรูปแบบไบนารี่จะมีลักษณะดังนี้: การขยายและการหดตัวของประเภทดั้งเดิม - 3 เราเขียนค่านี้ลงในตัวแปรshortแต่สามารถเก็บได้เพียง 16 บิตเท่านั้น! ดังนั้นเฉพาะ 16 บิตแรกของหมายเลขของเราเท่านั้นที่จะถูกย้ายไปที่นั่น ส่วนที่เหลือจะถูกละทิ้ง เป็นผลให้ตัวแปรshortจะมีค่า การขยายและการหดตัวของประเภทดั้งเดิม - 4ซึ่งในรูปแบบทศนิยมเท่ากับ -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

ถ่านชนิดข้อมูล

คุณรู้อยู่แล้วว่าประเภทถ่านใช้เพื่อแสดงอักขระแต่ละตัว
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 ทั่วไปมีขนาดใหญ่มากและแน่นอนว่าไม่จำเป็นต้องเรียนรู้ด้วยใจจริง ตัวอย่างเช่นนี่คือชิ้นส่วนของมัน: การขยายและการหดตัวของประเภทดั้งเดิม - 5 สิ่งสำคัญคือการเข้าใจหลักการของการจัดเก็บค่าcharและจำไว้ว่าการรู้รหัสของสัญลักษณ์เฉพาะคุณสามารถรับมันในโปรแกรมได้ตลอดเวลา ลองทำสิ่งนี้ด้วยตัวเลขสุ่ม:
public static void main(String[] args) {

   int x = 32816;

   char c = (char) x ;
   System.out.println(c);
}
เอาต์พุตคอนโซล: 耰 นี่คือรูปแบบที่อักขระถูกจัดเก็บในcharJava อักขระแต่ละตัวสอดคล้องกับตัวเลข - รหัสตัวเลข 16 บิตหรือสองไบต์ Unicode 32816 สอดคล้องกับอักขระ 耰 ให้ความสนใจกับช่วงเวลานี้ intในตัวอย่าง นี้เราใช้ตัวแปร ใช้หน่วย ความจำ 32 บิตในขณะที่char16 บิต เราเลือกที่นี่เนื่องจากหมายเลขที่เราต้องการ 32816 อยู่นอกช่วง แม้ว่าขนาดเช่น short จะเป็น 16 บิต แต่ไม่มีตัวเลขติดลบในช่วง ดังนั้นช่วง "บวก" จึงมีขนาดใหญ่เป็นสองเท่า (65536 แทนที่จะเป็น 32767 ) เราสามารถใช้ตราบใดที่โค้ดของเราอยู่ในช่วง 65536 แต่ถ้าเราสร้างตัวเลขมันจะกินพื้นที่มากกว่า 16 บิต และเมื่อจำกัดประเภทให้แคบลง: intshortcharcharcharshortintint >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 ของตัวละครของเรา การขยายและการหดตัวของประเภทดั้งเดิม - 6 ดังนั้นนี่คือ เมื่อเราทำการบวก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 :) กลไกการทำงานอย่างที่คุณเห็นนั้นค่อนข้างง่าย
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION