1. ตัวแปรอ้างอิง
ในภาษา Java มีตัวแปรอยู่ 2 ชนิด ได้แก่ ตัวแปรดั้งเดิมและอื่นๆ เมื่อมันเกิดขึ้น เราจะพูดถึง "อย่างอื่นทั้งหมด" ในตอนนี้
ในความเป็นจริง มันจะถูกต้องกว่าหากกล่าวว่ามีตัวแปรดั้งเดิมและตัวแปรอ้างอิง แล้วตัวแปรอ้างอิงเหล่านี้คืออะไร?
ซึ่งแตกต่างจากประเภทดั้งเดิมซึ่งตัวแปรเก็บค่าโดยตรง ตัวแปรอ้างอิงจะจัดเก็บการอ้างอิงไปยังวัตถุ นั่นคือมีวัตถุอยู่ในหน่วยความจำ และตัวแปรอ้างอิงก็เก็บที่อยู่ของวัตถุนี้ไว้ในหน่วยความจำ (การอ้างอิงถึงวัตถุ)
เฉพาะประเภทดั้งเดิมเท่านั้นที่เก็บค่าภายในตัวแปรโดยตรง ประเภท อื่นๆ ทั้งหมดจัดเก็บเฉพาะการอ้างอิงวัตถุ อย่างไรก็ตาม คุณได้พบตัวแปรสองประเภทดังกล่าวแล้ว — String
ตัวแปรและตัวแปรอาร์เรย์
ทั้งอาร์เรย์และสตริงเป็นวัตถุที่เก็บอยู่ในหน่วยความจำ String
ตัวแปรและตัวแปรอาร์เรย์เก็บเฉพาะการอ้างอิงถึงวัตถุ
int a, int b and double d
เป็นตัวแปรดั้งเดิมที่เก็บค่าของมันไว้ในตัวมันเอง
ตัวแปรString str
คือการอ้างอิงและจัดเก็บที่อยู่ (อ้างอิง) ไปยังString
วัตถุในหน่วยความจำ
เมื่อกำหนดค่าดั้งเดิมให้กับตัวแปรประเภทดั้งเดิม ค่านั้นจะถูกคัดลอก (ทำซ้ำ) เมื่อกำหนดตัวแปรอ้างอิงเฉพาะที่อยู่ของวัตถุเท่านั้นที่จะถูกคัดลอก — ตัววัตถุเอง จะไม่ถูกคัดลอก
2. การอ้างอิงทั้งหมดเกี่ยวกับอะไร
อะไรคือความแตกต่างพื้นฐานระหว่างตัวแปรอ้างอิงและตัวแปรดั้งเดิม
ตัวแปรดั้งเดิมเป็นเหมือนกล่อง: คุณสามารถเก็บค่าบางอย่างไว้ในนั้นได้ ตัวแปรอ้างอิงเป็นเหมือนกระดาษที่มีหมายเลขโทรศัพท์อยู่
รถ vs กุญแจรถ
จินตนาการว่าคุณตัดสินใจมอบรถให้เพื่อนของคุณในวันเกิดของเขา คุณจะไม่ห่อมันไว้ในกล่องแล้วพกติดตัวไปด้วย: รถมันใหญ่เกินไปสำหรับสิ่งนั้น
สะดวกกว่ามากที่จะนำเสนอกุญแจรถในกล่องที่ใหญ่พอที่จะบรรจุได้ เพื่อนของคุณจะเข้าใจทุกอย่างเมื่อเขาได้กุญแจออกมาจากกล่อง คุณไม่จำเป็นต้องพกรถทั้งคันไปกับคุณ เพียงแค่คุณมอบกุญแจเท่านั้น
บุคคล vs หมายเลขโทรศัพท์ของเธอ
หรือนี่คือการเปรียบเทียบอื่น: บุคคลและหมายเลขโทรศัพท์ของเธอ หมายเลขโทรศัพท์ไม่ใช่บุคคล แต่สามารถใช้หมายเลขโทรศัพท์เพื่อโทรหาเธอ ขอข้อมูลบางอย่างจากเธอ หรือให้คำแนะนำได้
ในทำนองเดียวกัน การอ้างอิงจะใช้เพื่อโต้ตอบกับวัตถุ วัตถุทั้งหมดโต้ตอบกันโดยใช้การอ้างอิง แทนที่จะ "แลกคน" เราก็แค่แลกเบอร์โทรกัน
เมื่อกำหนดค่าให้กับตัวแปรดั้งเดิม ค่าจะถูกคัดลอก (ทำซ้ำ) เมื่อกำหนดค่าให้กับตัวแปรอ้างอิง เฉพาะที่อยู่ (หมายเลขโทรศัพท์) ของวัตถุเท่านั้นที่จะถูกคัดลอก — ตัววัตถุเองจะไม่ถูกคัดลอก
การอ้างอิงมีข้อดีอีกประการหนึ่ง: คุณสามารถส่งการอ้างอิงวัตถุไปยังเมธอดบางเมธอดได้ และเมธอดจะสามารถแก้ไข (เปลี่ยนแปลง) อ็อบเจกต์ได้โดยใช้การอ้างอิงถึงเมธอด เรียกใช้เมธอดและเข้าถึงข้อมูลภายในออบเจกต์
3. การกำหนดการอ้างอิง
เมื่อกำหนดตัวแปรอ้างอิง จะมีการกำหนดเฉพาะที่อยู่ของวัตถุในหน่วยความจำเท่านั้น วัตถุจะไม่ปรากฏหรือหายไป
วิธีการนี้หลีกเลี่ยงการคัดลอกหน่วยความจำจำนวนมาก หากคุณต้องการส่งวัตถุขนาดใหญ่มากไปยังเมธอด เราก็แค่ส่งการอ้างอิงวัตถุ แค่นั้น การอ้างอิงใช้พื้นที่น้อยกว่ามาก
ขนาดของตัวแปรอ้างอิงทั้งหมด (โดยไม่คำนึงถึงประเภท) จะเท่ากัน — 4 ไบต์ (เช่น int) แต่! หากแอปพลิเคชันของคุณทำงานบนเครื่อง Java 64 บิต การอ้างอิงทั้งหมดจะมีขนาด 8 ไบต์ (64 บิต)
ยิ่งไปกว่านั้น สามารถกำหนดการอ้างอิงให้กันและกันเท่านั้น คุณไม่สามารถเปลี่ยนการอ้างอิงหรือกำหนดค่าตามอำเภอใจให้กับตัวแปรอ้างอิง:
รหัส | คำอธิบาย |
---|---|
|
สิ่งนี้ได้รับอนุญาต |
|
แต่สิ่งนี้ไม่ได้รับอนุญาต |
|
และสิ่งนี้ไม่ได้รับอนุญาต |
4. null
การอ้างอิง
และตัวแปรอ้างอิงจะเก็บอะไรถ้ายังไม่ได้กำหนดอะไรเลย?
มันเก็บข้อมูลอ้างอิงที่เป็นโมฆะ null
เป็นคีย์เวิร์ดพิเศษของ Java ซึ่งหมายถึงการไม่มีการอ้างอิง (การอ้างอิงที่ว่างเปล่า) null
สามารถกำหนดค่าให้กับตัวแปรอ้างอิงใดๆ
ตัวแปรอ้างอิงทั้งหมดnull
เว้นแต่จะมีการอ้างอิงบางชนิดกำหนดไว้
ตัวอย่าง:
รหัส | คำอธิบาย |
---|---|
|
ตัวแปร String name มีค่าเริ่มต้น: null . ตัวแปร int age มีค่าเริ่มต้น: 0 . |
ตัวแปรเฉพาะที่ไม่ได้รับการกำหนดค่าจะถือว่าไม่ได้กำหนดค่าเริ่มต้นสำหรับทั้งประเภทดั้งเดิมและประเภทอ้างอิง
หากตัวแปรเก็บการอ้างอิงถึงวัตถุบางอย่าง และคุณต้องการล้างค่าของตัวแปร ให้กำหนดค่าการอ้างอิงเป็นค่าว่าง
รหัส | คำอธิบาย |
---|---|
|
s ร้านnull ค้า s เก็บการอ้างอิงไปยังs ที่เก็บnull วัตถุ สตริง |
5. ผ่านการอ้างอิงถึงวิธีการ
หากเมธอดมีพารามิเตอร์ที่เป็นประเภทการอ้างอิงค่าจะถูกส่งผ่านไปยังเมธอดในลักษณะเดียวกับเมื่อทำงานกับตัวแปรที่ไม่ใช่การอ้างอิง พารามิเตอร์เป็นเพียงการกำหนดค่าของตัวแปรอื่น
ตัวอย่าง:
รหัส | คำอธิบาย |
---|---|
|
เติม fill อาร์เรย์ที่ผ่าน ( array ) ด้วยค่าที่ผ่าน ( value ) |
เมื่อมีfill
การเรียกใช้เมธอดarray
พารามิเตอร์จะถูกกำหนดการอ้างอิงไปยังdata
อาร์เรย์ ตัวแปรvalue
ถูกกำหนดให้อ้างอิงถึงวัตถุสตริง ("สวัสดี")
นี่คือลักษณะของหน่วยความจำก่อนที่จะเรียกใช้ fill
เมธอด:
นี่คือลักษณะของหน่วยความจำเมื่อ fill
เมธอดทำงาน :

ตัวแปรdata
และarray
อ้างถึง (จัดเก็บการอ้างอิงถึง) คอนเทนเนอร์เดียวกันในหน่วยความจำ
ตัวแปรvalue
เก็บการอ้างอิงถึงวัตถุสตริง ( "Hello"
)
เซลล์ของอาร์เรย์ยังเก็บการอ้างอิงไปยัง"Hello"
วัตถุ เท่านั้น
อันที่จริงแล้ว ไม่มีออบเจ็กต์ใดซ้ำกัน — เฉพาะการอ้างอิงเท่านั้นที่จะถูกคัดลอก
6. การเปรียบเทียบกับภาษา C/C++
ในการสัมภาษณ์ บางครั้งโปรแกรมเมอร์ Java ถูกถามว่าข้อมูลถูกส่งไปยังเมธอดใน Java อย่างไร และบางครั้งคำถามคือว่าข้อมูลถูกส่งโดยการอ้างอิงหรือตามค่า?
คำถามนี้มาจาก C++ แต่ไม่มีความหมายมากนักใน Java ใน Java พารามิเตอร์จะได้รับการกำหนดค่าของอาร์กิวเมนต์เสมอ ดังนั้นคำตอบที่ถูกต้องคือ " ตามมูลค่า "
แต่จงเตรียมพร้อมที่จะอธิบายตำแหน่งของคุณเนื่องจากคุณอาจได้ยินคำโต้กลับในทันทีว่า "ประเภทดั้งเดิมจะถูกส่งผ่านตามค่า และประเภทการอ้างอิงจะถูกส่งผ่านโดยการอ้างอิง"
ที่มาของปัญหานี้เกิดจากการที่โปรแกรมเมอร์ Java จำนวนมากเคยเป็นโปรแกรมเมอร์ C++ มาก่อน ในภาษาโปรแกรมนั้น คำถามเกี่ยวกับวิธีส่งผ่านพารามิเตอร์ไปยังเมธอดมีความสำคัญมาก
ใน Java ทุกอย่างไม่คลุมเครือ: ประเภทดั้งเดิมจะเก็บค่าและประเภทการอ้างอิงก็เก็บค่าเช่นกัน — การอ้างอิง เป็นคำถามว่าตัวแปรถือเป็นค่าหรือไม่
ใน C++ ตัวแปรสามารถเก็บทั้งการอ้างอิงถึงวัตถุและตัววัตถุเอง เช่นเดียวกับประเภทดั้งเดิม: ตัวแปรดั้งเดิมสามารถเก็บค่าหรือประกาศตัวแปรเป็นการอ้างอิงไปยังไฟล์int
. ดังนั้น เพื่อหลีกเลี่ยงความสับสน โปรแกรมเมอร์ C++ มักจะอ้างถึงออบเจกต์ไปยังข้อมูลอ้างอิงเป็นข้อมูลอ้างอิงและตัววัตถุเองเป็นค่า
ใน C++ คุณสามารถมีสถานการณ์ที่ตัวแปรหนึ่งมีวัตถุได้อย่างง่ายดาย แต่อีกตัวแปรหนึ่งมีการอ้างอิงถึงวัตถุนั้น ดังนั้น คำถามเกี่ยวกับสิ่งที่ตัวแปรจัดเก็บ — ตัววัตถุเองหรือเพียงแค่การอ้างอิงถึงตัวแปร — จึงมีความสำคัญมาก เมื่อวัตถุถูกส่งไปยังเมธอด มันจะถูกคัดลอก (หากส่งผ่านค่า) และไม่ถูกคัดลอก (หากส่งผ่านโดยการอ้างอิง)
ใน Java ไม่มีความเป็นคู่นี้ ดังนั้นคำตอบที่ถูกต้องคือ: ค่าจะถูกส่งผ่านอาร์กิวเมนต์ไปยังเมธอด Java ตามค่า เมื่อเราพูดถึงตัวแปรอ้างอิง ค่านี้เป็นค่าอ้างอิง
GO TO FULL VERSION