ถ้า IDE ของฉันฉลาดเหลือเกินฉันจะต้องทำการ“ clone ()” ทำไม?


13

My IDE ( NetBeans ) ประเภทของฉันตรวจสอบCollectionsขณะที่ฉันพิมพ์รหัส แต่ทำไมฉันต้องโยนวัตถุคืนกลับมาObject.clone()? ซึ่งเป็นเรื่องปกติ ไม่เป็นอันตรายไม่มีเหม็น แต่ถึงกระนั้นฉันไม่เข้าใจ

การตรวจสอบประเภทObject.clone()เป็นไปได้หรือไม่โดยไม่ต้องทำการคัดลอกวัตถุที่ส่งคืนเป็นไปไม่ได้? genericsกรอบทำให้ฉันคิดว่า IDE สามารถตรวจสอบประเภทของการอ้างอิงวัตถุบนด้านขวาของ " =เครื่องหมาย" โดยไม่ต้องหล่อในขณะที่ฉันพิมพ์? ฉันไม่เข้าใจ

ภาคผนวก
กรณีการใช้งานของฉันเป็นเพียงแค่ว่าผมมีความส่วนตัวCalendarฟิลด์pubDate ฉันกำลังจะเขียน:

Calendar getPubdate() {
    return pubdate;
}

แต่มีความเสี่ยงที่ผู้บุกรุกสามารถแก้ไขpubdateของฉันได้ดังนั้นฉันจึงส่งสำเนา:

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

pubdate.clone()แล้วฉันสงสัยว่าทำไมผมต้องหล่อ ลายเซ็นวิธีมีประเภทที่นั่น NetBeansน่าจะสามารถเข้าใจได้ และNetBeansCollectionsดูเหมือนจะทำอะไรบางอย่างที่คล้ายกันในเรื่องเกี่ยวกับ


5
ตัวอย่างรหัสสั้น ๆ (!) จะเป็นประโยชน์
Doc Brown

78
IDE แยกออกจากภาษาดังนั้น Netbeans ที่ชาญฉลาดจะไม่มีผลกระทบต่อวิธีการใช้ภาษาจาวา
JacquesB

7
หมายเหตุเนื่องจากมีการส่งกลับชนิดแปรปรวนก็จะแนะนำให้กลับมาMyObjectจากclone()มากกว่าObject- นี้เอาปัญหานี้ทั้งหมด ไม่แนะนำให้ใช้ต่อไปclone()(รายการ Java ที่มีประสิทธิภาพ # 11)
Boris the Spider

คำถามของคุณเน้นที่ฉันหรือ'โยน "โคลน ()"'หรือไม่? เพราะคำถามจากอดีตอาจเป็นคำถามที่ดีกว่าคำถามหลัง
user541686

เมื่อฉันอ่านชื่อคำถามสิ่งเดียวที่ฉันคิดคือthis.clone()อยู่บนวัตถุโปรแกรมเมอร์โดยเฉพาะในคืนวันพุธหลังจากการปล่อยตัวของอ. ขออภัย แต่ฉันต้องเขียนความคิดเห็นนี้ .. ทำไมไม่สามารถสมาร์ท IDE เพียงแค่แก้ไขข้อผิดพลาดทั้งหมดสำหรับเรา LOL
Mai

คำตอบ:


53

ทำไมฉันต้องโยนวัตถุคืนกลับมาObject.clone()?

เพราะมันกลับObjectมา

genericsกรอบทำให้ฉันคิดว่า IDE สามารถตรวจสอบประเภทของการอ้างอิงวัตถุบนด้านขวาของ " =เครื่องหมาย" โดยไม่ต้องหล่อในขณะที่ฉันพิมพ์? ฉันไม่เข้าใจ

Object.clone ไม่ธรรมดา

หากมีข้อมูลทั่วไปเมื่อcloneถูกออกแบบมันอาจจะเป็นแบบนี้ (ใช้ F-Bounded Polymorphism):

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

หาก Java มีคุณสมบัติ MyType มันอาจจะเป็นดังนี้:

interface Cloneable {
  this clone();
}

แต่ Generics ไม่มีอยู่เมื่อObject.cloneถูกออกแบบมาและ Java ไม่มี MyTypes ดังนั้นเวอร์ชันที่ไม่ปลอดภัยของประเภทObject.cloneนี้คือสิ่งที่เราต้องทำงานด้วย


ฉันเพิ่งรู้ว่าคุณสมบัติ IDE ที่ทำให้ฉันสับสนคือการรวบรวมพื้นหลัง? ฉันหมายความว่านั่นคือสิ่งที่ช่วยให้การเติมโค้ดและการตรวจสอบชนิดอัตโนมัติด้วย generics? โดยส่วนตัวฉันชอบการตรวจสอบประเภทการหน่วงเวลาจนกว่าจะมีการคอมไพล์อย่างชัดเจน แต่ฉันทำโค้ดรักให้สมบูรณ์
konishiki

1
@konishiki กับ Java 8 (และ Java 7) การอนุมานชนิดเพื่อที่จะให้ความช่วยเหลือใด ๆ IDE จำเป็นต้องอนุมานประเภท ต้องมีการรวบรวมบางส่วน ก่อนการอนุมานชนิดไม่จำเป็นต้องมีการรวบรวมสำหรับการเติมข้อความอัตโนมัติ
Boris the Spider

@BoristheSpider ขอบคุณมากสำหรับข้อเสนอแนะ! แน่นอนฉันต้องทำการทดสอบเพิ่มเติม / คิดเพิ่มเติม ชื่นชมมาก
konishiki

ทำไมคุณจะต้องผ่านoriginal?
Clashsoft

@Clashsoft: Stupid Thinko ในขณะที่ปรับเวอร์ชั่นการทำงานของ Programming อย่างชัดเจน ขอบคุณ
Jörg W Mittag

26

นี่ไม่ใช่คุณสมบัติของ IDE ใด ๆ แต่เป็นข้อกำหนดของภาษา

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

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


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

1
IDE สามารถทำลายกฎทั้งหมดของสเป็คภาษาได้อย่างง่ายดายและเพียงแค่รวบรวมรหัสอย่างไรก็ตาม ฉันรู้ว่าทั้ง NetBeans และ Eclipse ใช้คอมไพเลอร์ของตัวเอง ดังนั้นในกรณีเหล่านั้น IDE และคอมไพเลอร์ก็มีประสิทธิภาพเหมือนกัน ไม่ได้บอกว่ามันเป็นความคิดที่ดี แต่คอมไพเลอร์ซีทำมันตลอดเวลา
MichaelS

@MichaelS ข้อมูลจำเพาะภาษา C ได้รับการออกแบบเพื่อให้เกิดความแตกต่างอย่างมีนัยสำคัญระหว่างการใช้งานเพื่อให้ผู้ขายที่แตกต่างกันสามารถเลือกระหว่างแนวทางที่เป็นไปได้ที่แตกต่างกันและเพิ่มคุณสมบัติพิเศษ สิ่งนี้สร้างความคลุมเครือในด้านต่าง ๆ ของข้อกำหนดซึ่งจำเป็นต่อการเปลี่ยนแปลงเหล่านั้น ชื่อ "C" ไม่ใช่เครื่องหมายการค้าดังนั้นจึงไม่มีใครควบคุมการใช้คำดังกล่าว ข้อมูลจำเพาะ Java ถูกออกแบบมาเพื่อกำจัดความคลุมเครือมากที่สุดเท่าที่จะเป็นไปได้และ Java เป็นเครื่องหมายการค้าและผู้ถือเครื่องหมายการค้าบังคับใช้ว่าสามารถใช้ได้เฉพาะในการปรับใช้ที่สอดคล้อง
จูลส์

Modern IDE ต้องการคอมไพเลอร์อยู่ดี คำแนะนำในการกรอกรหัสจำเป็นต้องใช้รหัสก่อนที่เคอร์เซอร์จะถูกวิเคราะห์คำ และแน่นอนว่าด้วย generics (หรือเทมเพลต C ++) ที่ต้องการคอมไพเลอร์แบบเต็มไม่ใช่แค่ตัวแยกวิเคราะห์
MSalters

3

มันเป็นเพราะลายเซ็นประเภทของวิธีการ Object.clone ประเภทลายเซ็นระบุว่าวิธีการจะส่งกลับวัตถุประเภทวัตถุ

protected Object clone() throws CloneNotSupportedException

คอลเลกชันจะใช้ประเภททั่วไปที่เรียกว่าเพื่อทดแทนประเภทการหล่อโดยอัตโนมัติ

ดังนั้นหากคุณมีรหัสนี้:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

คอมไพเลอร์จะเพิ่ม casts ให้คุณหลังฉากดังนั้นโค้ดจะเป็น:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);

0

เพื่อความสมบูรณ์ตั้งแต่ Java 5 ประเภทผลตอบแทน covariant ได้รับอนุญาต ดังนั้นคุณสามารถเขียนสิ่งต่อไปนี้:

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

ด้วยวิธีนี้รหัสต่อไปนี้ถูกกฎหมาย:

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