สวัสดี! ในขณะที่ใช้งาน 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
) เป็นอีกเรื่องหนึ่งเมื่อคุณพยายามทำสิ่งที่ตรงกันข้าม - ใส่ค่าจำนวนมากลงในตัวแปรที่ไม่ได้ออกแบบมาสำหรับขนาดดังกล่าว โดยหลักการแล้ว เคล็ดลับนี้ใช้ไม่ได้กับตุ๊กตาทำรังจริง แต่ใน 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 บิตและในรูปแบบไบนารี่จะมีลักษณะดังนี้: เราเขียนค่านี้ลงในตัวแปร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
ถ่านชนิดข้อมูล
คุณรู้อยู่แล้วว่าประเภทถ่านใช้เพื่อแสดงอักขระแต่ละตัว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);
}
เอาต์พุตคอนโซล: 耰 นี่คือรูปแบบที่อักขระถูกจัดเก็บในchar
Java อักขระแต่ละตัวสอดคล้องกับตัวเลข - รหัสตัวเลข 16 บิตหรือสองไบต์ Unicode 32816 สอดคล้องกับอักขระ 耰 ให้ความสนใจกับช่วงเวลานี้ int
ในตัวอย่าง นี้เราใช้ตัวแปร ใช้หน่วย ความจำ 32 บิตในขณะที่char
16 บิต เราเลือกที่นี่เนื่องจากหมายเลขที่เราต้องการ 32816 อยู่นอกช่วง แม้ว่าขนาดเช่น short จะเป็น 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