เมื่อใดควรใช้คลาส wrapper และประเภทดั้งเดิม


101

เมื่อใดที่ฉันควรเลือกคลาส Wrapper มากกว่าประเภทดั้งเดิม หรือในกรณีใดฉันควรเลือกระหว่าง wrapper / Primitive types?


2
w3resource.com/java-tutorial/java-wrapper-classes.phpบทความนี้จะเป็นประโยชน์สำหรับการสนทนานี้
pankaj

คำตอบ:


70

คนอื่น ๆ ได้กล่าวว่าโครงสร้างบางอย่างเช่นCollectionsต้องใช้วัตถุและวัตถุนั้นมีค่าใช้จ่ายมากกว่าวัตถุดั้งเดิม (หน่วยความจำและการชกมวย)

ข้อควรพิจารณาอีกประการหนึ่งคือ:

การเตรียมใช้งานออบเจ็กต์nullหรือส่งnullพารามิเตอร์ไปยังเมธอด / คอนสตรัคเตอร์เพื่อระบุสถานะหรือฟังก์ชันได้อย่างสะดวก สิ่งนี้ไม่สามารถทำได้โดยใช้แบบดั้งเดิม

โปรแกรมเมอร์หลายคนเริ่มต้นตัวเลขเป็น 0 (ค่าเริ่มต้น) หรือ -1 เพื่อแสดงถึงสิ่งนี้ แต่ขึ้นอยู่กับสถานการณ์นี้อาจไม่ถูกต้องหรือทำให้เข้าใจผิด

นอกจากนี้ยังจะจัดฉากNullPointerExceptionเมื่อมีการใช้บางสิ่งอย่างไม่ถูกต้องซึ่งเป็นมิตรกับโปรแกรมเมอร์มากกว่าข้อผิดพลาดบางอย่างตามอำเภอใจ


15
"สามารถเริ่มต้น Objects เป็น null ได้อย่างสะดวก" ไม่สามารถใช้ประโยชน์ได้เนื่องจากไม่ถูกต้องหากช่องนี้เป็นทางเลือกคุณควรระบุสิ่งนี้อย่างชัดเจน
Eddie Jamsession

8
lol @EddieJamsession ขอบคุณฉันจะไม่เริ่มต้นเป็นโมฆะอีกต่อไป (pfffft)
pstanton

1
@EddieJamsession หากการกำหนดค่าเริ่มต้นออบเจ็กต์เป็นค่าว่างเพื่อระบุความล้มเหลวเมื่อการตั้งค่าจริงล้มเหลวคุณจะเสนอให้แก้ไขปัญหานี้อย่างไร โอ้ฉันเพิ่งรู้เมื่อฉันพิมพ์สิ่งนี้: ข้อยกเว้น NullPointerException ธรรมดาเกินไป จะเป็นการดีกว่าหากใช้ข้อยกเว้นที่กำหนดเองเฉพาะเจาะจงเพื่อระบุสิ่งที่ผิดพลาด ดีฉันจะทำสิ่งนั้นต่อจากนี้ ...
klaar

1
@EddieJamsession หลังจากอ่านเรื่องนี้แล้วฉันก็ได้พบกับแนวคิดของวัตถุเสริม ขวา.
klaar

@klaar วัตถุเสริมคืออะไร?
carloswm85

19

โดยทั่วไปคุณควรใช้ประเภทดั้งเดิมเว้นแต่ว่าคุณต้องการวัตถุด้วยเหตุผลบางประการ (เช่นเพื่อเก็บรวบรวม) ถึงอย่างนั้นให้พิจารณาแนวทางอื่นที่ไม่ต้องการวัตถุหากคุณต้องการเพิ่มประสิทธิภาพตัวเลขให้สูงสุด นี้จะให้คำแนะนำโดยเอกสารและบทความนี้แสดงให้เห็นถึงวิธีการอัตโนมัติมวยสามารถก่อให้เกิดความแตกต่างในการปฏิบัติงานที่มีขนาดใหญ่


3
การตีประสิทธิภาพไม่ดีมากจนความชัดเจนของรหัส / ความน่าเชื่อถือควรใช้เบาะหลัง
pstanton

3
ขั้นแรกการใช้แบบดั้งเดิมอย่างเหมาะสมจะไม่ทำให้โค้ดของคุณอ่านไม่ออก ประการที่สองการตีประสิทธิภาพมีความสำคัญในบางกรณี มันไร้สาระที่จะบอกว่ามันไม่เคยเป็น
Matthew Flaschen

1
@pstanton: โปรดอธิบายว่าIntegerมันชัดเจนกว่าintอย่างไร
Stephen C

ในหลาย ๆ กรณี Integer ไม่สามารถอ่านได้ชัดเจนไปกว่า int และในกรณีเหล่านี้ฉันจะใช้ int เสมอหรือถ้าฉันรู้ว่าตัวแปรบางตัวจะไม่เป็นโมฆะฉันจะใช้ int เพราะ int นั้นมีประสิทธิภาพมากกว่าเล็กน้อย อย่างไรก็ตามในหลาย ๆ กรณีโปรแกรมเมอร์คนอื่นจะเข้าใจสถานะของตัวแปรได้ง่ายขึ้นเมื่อใช้ออบเจ็กต์เนื่องจากสามารถเริ่มต้นเป็น null เพื่อแสดงว่ายังไม่พร้อม ตัวอย่างเช่นหากคุณมีระเบียนฐานข้อมูลที่ไม่ได้บันทึกซึ่งมีรหัสตัวเลขที่เพิ่มขึ้นไม่ซ้ำกัน id นี้ควรเป็น 0, -1 หรือ null ก่อนที่จะกำหนด ID ที่ถูกต้องหรือไม่ ในกรณีนั้น Objects จะดีกว่า
pstanton

เกี่ยวกับประสิทธิภาพ - ในกรณีพิเศษการตีประสิทธิภาพอาจมีความสำคัญเช่นหากคุณกำลังสร้างวัตถุเหล่านี้จำนวนมากอย่างรวดเร็วหรือหากหลาย ๆ ชิ้นจำนวนมากสร้างขึ้นในช่วงเวลาหนึ่ง อย่างไรก็ตามฉันคาดหวังว่าโปรแกรมเมอร์ที่ดีจะสามารถระบุกรณีพิเศษเหล่านี้ได้ไม่ว่าจะหลีกเลี่ยงหรือแก้ไขตามนั้น ฉันไม่เคยบอกว่ามันไม่สำคัญ แต่โดยทั่วไปแล้วมันไม่ใช่
pstanton

12

ในความคิดของฉันถ้าสมาชิกชั้นเรียนของฉันเป็นตัวแปร Wrapper จะไม่ขึ้นอยู่กับค่าเริ่มต้นซึ่งเป็นพฤติกรรมที่เป็นมิตรกับนักพัฒนา

1.

class Person {
   int SSN ; // gets initialized to zero by default 
}

2.

class PersonBetter {
  Integer SSN; //gets initialized to null by default
}

ในกรณีแรกคุณไม่สามารถเก็บค่า SSN ไว้โดยไม่กำหนดค่าเริ่มต้นได้ อาจเจ็บหากคุณไม่ได้ตรวจสอบว่าได้ตั้งค่าก่อนที่จะพยายามใช้หรือไม่

ในกรณีที่สองคุณสามารถเริ่มต้น SSN ด้วย null ได้ ซึ่งสามารถนำไปสู่ ​​NullPointerException แต่จะดีกว่าการแทรกค่าเริ่มต้น (ศูนย์) เป็น SSN ลงในฐานข้อมูลโดยไม่รู้ตัวเมื่อใดก็ตามที่คุณพยายามใช้งานโดยไม่ต้องเริ่มต้นฟิลด์ SSN


3
รูปแบบตัวสร้างมีขึ้นเพื่อหลีกเลี่ยงสิ่งนี้ ในสถานการณ์นี้คุณสร้างPersonBuilderข้อยกเว้นหากไม่ได้ตั้งค่า SSN ไว้ก่อนที่จะเรียก "build" เพื่อรับPersonอินสแตนซ์ ฉันคิดว่าสิ่งนี้มากเกินไป แต่เป็นสิ่งที่ภาษา Java ส่งเสริมสำหรับรูปแบบที่เหมาะสม
Sandy Chapman

8

ฉันจะใช้ประเภทกระดาษห่อหุ้มเท่านั้นถ้าคุณต้อง

ในการใช้พวกเขาคุณจะไม่ได้รับมากนักนอกจากความจริงที่ว่าพวกเขา Objectsในการใช้พวกเขาที่คุณไม่ได้รับมากนอกเหนือจากความจริงที่ว่าพวกเขา

และคุณสูญเสียค่าใช้จ่ายในการใช้หน่วยความจำและเวลาที่ใช้ในการชกมวย / แกะกล่อง


4
คุณอาจไม่ได้รับมากนัก แต่คุณก็ไม่ได้สูญเสียมากเช่นกัน เว้นแต่คุณจะวิ่งบนฝ่ามือในปี 1990
pstanton

ความจริงที่ว่าพวกเขาเป็น Objects ยังให้บริบทและการห่อหุ้มพวกเขามากกว่าแบบดั้งเดิมธรรมดา ดังนั้นคุณอาจได้รับประโยชน์มากขึ้นอยู่กับความหมายของสิ่งดั้งเดิมเหล่านั้นและสถานที่ที่ใช้
aberrant80

4

ในทางปฏิบัติฉันเคยเจอสถานการณ์ที่สามารถอธิบายการใช้คลาส wrapper ได้

ฉันสร้างคลาสบริการที่มีlongตัวแปรประเภท

  1. หากตัวแปรเป็นประเภทlong- เมื่อไม่ได้เริ่มต้นจะถูกตั้งค่าเป็น 0 - สิ่งนี้จะทำให้ผู้ใช้สับสนเมื่อแสดงใน GUI
  2. หากตัวแปรเป็นประเภทLong- เมื่อไม่ได้เริ่มต้นตัวแปรจะถูกตั้งค่าเป็นnull- ค่าว่างนี้จะไม่ปรากฏใน GUI

สิ่งนี้ใช้ได้กับBooleanค่าที่อาจทำให้สับสนได้มากขึ้นเมื่อเราใช้แบบดั้งเดิมboolean(เนื่องจากค่าเริ่มต้นเป็นเท็จ)


3

คอลเลกชันเป็นกรณีทั่วไปสำหรับออบเจ็กต์ Java wrapper แบบธรรมดา อย่างไรก็ตามคุณอาจพิจารณาให้ Wrapper มีความหมายที่เฉพาะเจาะจงมากขึ้นในรหัส (ออบเจ็กต์ค่า)

IMHO มักจะมีประโยชน์ในการใช้วัตถุที่มีค่าเมื่อมันลดความสามารถในการอ่านและการบำรุงรักษาโค้ด การห่อโครงสร้างข้อมูลง่ายๆภายในออบเจ็กต์เมื่อมีความรับผิดชอบบางอย่างมักจะทำให้โค้ดง่ายขึ้น นี่คือสิ่งที่สำคัญมากในการออกแบบที่ขับเคลื่อนด้วยโดเมนโดเมนที่ขับเคลื่อนด้วยการออกแบบ

แน่นอนว่ามีปัญหาด้านประสิทธิภาพ แต่ฉันมักจะเพิกเฉยจนกว่าฉันจะมีความเป็นไปได้ที่จะวัดประสิทธิภาพด้วยข้อมูลที่เหมาะสมและดำเนินการโดยตรงต่อพื้นที่ที่มีปัญหา นอกจากนี้ยังอาจทำความเข้าใจปัญหาด้านประสิทธิภาพได้ง่ายขึ้นหากโค้ดนั้นเข้าใจง่ายเช่นกัน


3

ประสิทธิภาพของแอปพลิเคชันที่ถูกควบคุมโดยการคำนวณตัวเลขจะได้รับประโยชน์อย่างมากจากการใช้งานแบบดั้งเดิม

ประเภทดั้งเดิมหนึ่งใช้ตัวดำเนินการ == แต่สำหรับ wrapper ตัวเลือกที่ต้องการคือการเรียกใช้เมธอด equals ()

"ประเภทดึกดำบรรพ์ถือว่าเป็นอันตราย"เนื่องจากผสม "ความหมายเชิงกระบวนการเข้ากับโมเดลเชิงวัตถุ

โปรแกรมเมอร์หลายคนเริ่มต้นตัวเลขเป็น 0 (ค่าเริ่มต้น) หรือ -1 เพื่อแสดงถึงสิ่งนี้ แต่ขึ้นอยู่กับสถานการณ์นี้อาจไม่ถูกต้องหรือทำให้เข้าใจผิด


1

หากคุณต้องการใช้ Collections คุณต้องใช้คลาส Wrapper

ประเภทดั้งเดิมใช้สำหรับอาร์เรย์ นอกจากนี้เพื่อแสดงถึงข้อมูลที่ไม่มีพฤติกรรมเช่นตัวนับหรือเงื่อนไขบูลีน

ตั้งแต่การทำ autoboxing พรมแดน "เมื่อใดควรใช้แบบดั้งเดิมหรือ Wrapper" ก็ค่อนข้างคลุมเครือ

แต่จำไว้ว่า Wrappers เป็นวัตถุดังนั้นคุณจะได้รับคุณสมบัติ Java ที่น่าสนใจทั้งหมด ตัวอย่างเช่นคุณสามารถใช้การสะท้อนกลับเพื่อสร้างอ็อบเจ็กต์จำนวนเต็ม แต่ไม่ใช่ค่า int คลาส Wrapper ยังมีเมธอดเช่น valueOf


นอกเหนือจากคอลเลกชันฉันไม่ควรใช้คลาส Wrapper วิธีการใช้สำหรับการประกาศธรรมดาเช่น Integer i = new Integer (10); ทำแบบนี้ดีมั้ย?
Gopi

autoboxing ให้คุณทำ Integer i = 10;
ทอม

1
ไม่ใช่ศรี. ถ้าคุณไม่มีข้อกำหนดว่าฉันเป็นวัตถุก็อย่าสร้างมันขึ้นมา
Matthew Flaschen

Autoboxing จะยกเลิกการกล่องข้างบนที่ประกาศไว้ว่าเป็น int i = 10 หรือจำนวนเต็ม i = 10?
Gopi

3
int pi = จำนวนเต็มใหม่ (10); ได้ผล จำนวนเต็ม oi = 10; ได้ผล int ni = null; ไม่ทำงาน LHS ถูกแปลงเป็นสิ่งที่ RHS ต้องการ
pstanton

0

หากคุณต้องการสร้างประเภทค่า บางอย่างเช่น ProductSKU หรือ AirportCode

เมื่อประเภทดั้งเดิม (สตริงในตัวอย่างของฉัน) กำหนดความเท่าเทียมกันคุณจะต้องลบล้างความเท่าเทียมกัน


5
สตริงไม่ใช่แบบดั้งเดิม
pstanton

2
ยังคงมีเหตุผลที่ดีในการรวมประเภทค่าที่มีสตริงเป็นวัตถุฐาน
Chris Missal

คำตอบของคุณไม่สมเหตุสมผล ฉันไม่แน่ใจว่าคุณกำลังพูดอะไร ฉันเห็นด้วยกับความคิดเห็นของคุณคลาส Wrapper เป็นความคิดที่ดีหากพวกเขาปรับปรุงความชัดเจน
pstanton

ควรสร้างชนิดค่าหรือวัตถุมูลค่าและไม่เปลี่ยนรูป ตัวอย่างเช่นมันไม่สมเหตุสมผลที่จะสร้างวัตถุ "CountryCode" เช่น: CountryCode ใหม่ ("USA") จากนั้นสร้างวัตถุอื่นในลักษณะเดียวกันซึ่งในภายหลังจะแตกต่างกัน เป็นเพียงสตริงที่จะเริ่มต้น แต่มีความหมายอยู่เบื้องหลัง ด้วยการใช้สตริงคุณสามารถแก้ไขได้ (โดยการต่อท้ายข้อมูลเพิ่มเติม ฯลฯ ) แต่จะไม่เท่ากันอีกต่อไป ดูบทความนี้สำหรับคำอธิบายที่ดีขึ้นเกี่ยวกับสิ่งที่ฉันพยายามจะอธิบาย :) ฉันหวังว่านี่จะสมเหตุสมผล c2.com/cgi/wiki?ValueObject
Chris Missal

0

ค่าดั้งเดิมใน Java ไม่ใช่วัตถุ ในการจัดการค่าเหล่านี้เป็นอ็อบเจ็กต์แพ็กเกจ java.lang จะจัดเตรียมคลาส wrapper สำหรับแต่ละประเภทข้อมูลดั้งเดิม

คลาส Wrapper ทั้งหมดถือเป็นที่สิ้นสุด อ็อบเจ็กต์ของคลาส wrapper ทั้งหมดที่สามารถเริ่มต้นนั้นไม่เปลี่ยนรูปซึ่งหมายความว่าค่าในอ็อบเจ็กต์ wrapper ไม่สามารถเปลี่ยนแปลงได้

แม้ว่าคลาสโมฆะถือเป็นคลาสของ wrapper แต่ไม่ได้รวมค่าดั้งเดิมใด ๆ และไม่สามารถเริ่มต้นได้ ไม่มีตัวสร้างสาธารณะ แต่หมายถึงคลาสอ็อบเจ็กต์ที่แทนคีย์เวิร์ด void


0

เมื่อใดควรใช้ประเภทดั้งเดิม

  • เมื่อทำการคำนวณจำนวนมากประเภทดั้งเดิมจะเร็วกว่าเสมอ - มีค่าโสหุ้ยน้อยกว่ามาก
  • เมื่อคุณไม่ต้องการให้ตัวแปรเป็นโมฆะ
  • เมื่อคุณไม่ต้องการให้ค่าเริ่มต้นเป็นโมฆะ
  • ถ้าเมธอดต้องส่งคืนค่า

เมื่อใดควรใช้ Wrapper Class

  • เมื่อคุณใช้ Collections หรือ Generics - จำเป็น
  • หากคุณต้องการ MIN_SIZE หรือ MAX_SIZE ประเภท
  • เมื่อคุณต้องการให้ตัวแปรเป็นโมฆะ
  • เมื่อคุณต้องการให้ค่าเริ่มต้นเป็นค่าว่าง
  • หากบางครั้งเมธอดสามารถคืนค่าว่างได้

จากhttps://medium.com/@bpnorlander/java-understand-primitive-types-and-wrapper-objects-a6798fb2afe9

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.