มันสะดวกกว่าและสะอาดกว่าหากใช้คำสั่งเดียวเช่น
import java.awt.*;
กว่าจะนำเข้ากลุ่มของแต่ละคลาส
import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...
เกิดอะไรขึ้นกับการใช้สัญลักษณ์แทนในimport
คำสั่ง
มันสะดวกกว่าและสะอาดกว่าหากใช้คำสั่งเดียวเช่น
import java.awt.*;
กว่าจะนำเข้ากลุ่มของแต่ละคลาส
import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...
เกิดอะไรขึ้นกับการใช้สัญลักษณ์แทนในimport
คำสั่ง
คำตอบ:
ปัญหาเดียวของมันคือมัน clutters namespace ท้องถิ่นของคุณ ตัวอย่างเช่นสมมุติว่าคุณกำลังเขียนแอปสวิงและเพื่อความต้องการjava.awt.Event
และยังมีการเชื่อมต่อกับระบบปฏิทินของ บริษัท ฯ com.mycompany.calendar.Event
ซึ่งมี หากคุณนำเข้าทั้งสองโดยใช้วิธีไวด์การ์ดวิธีหนึ่งในสามสิ่งนี้จะเกิดขึ้น:
java.awt.Event
และcom.mycompany.calendar.Event
และเพื่อให้คุณไม่สามารถแม้แต่จะรวบรวม.*
ที่ผิดและคุณพยายามหาสาเหตุที่รหัสของคุณอ้างว่าเป็นประเภทที่ไม่ถูกต้องcom.mycompany.calendar.Event
แต่เมื่อพวกเขาเพิ่มหนึ่งรหัสที่ถูกต้องก่อนหน้านี้ของคุณก็หยุดรวบรวมข้อได้เปรียบของการแสดงรายการการนำเข้าทั้งหมดอย่างชัดเจนคือฉันสามารถบอกได้ทันทีว่าคุณต้องการใช้คลาสใดซึ่งทำให้การอ่านโค้ดง่ายขึ้นมาก หากคุณเพิ่งทำสิ่งเดียวที่รวดเร็วไม่มีอะไรผิดปกติอย่างชัดเจนแต่ผู้ดูแลในอนาคตจะขอบคุณสำหรับความชัดเจนของคุณเป็นอย่างอื่น
นี่คือการลงคะแนนสำหรับการนำเข้าดาว คำสั่งการนำเข้ามีวัตถุประสงค์เพื่อนำเข้าแพคเกจไม่ใช่ชั้นเรียน มันสะอาดกว่าการนำเข้าแพ็คเกจทั้งหมด; ปัญหาที่ระบุที่นี่ (เช่นjava.sql.Date
vs java.util.Date
) นั้นสามารถแก้ไขได้อย่างง่ายดายด้วยวิธีการอื่นไม่ใช่เรื่องจริงการแก้ไขโดยการนำเข้าที่เฉพาะเจาะจงและแน่นอนไม่ได้ปรับการนำเข้าอวดความรู้เมามันในชั้นเรียนทั้งหมด ไม่มีอะไรที่ทำให้สับสนมากกว่าการเปิดไฟล์ต้นฉบับและต้องผ่านคำสั่งนำเข้า 100 รายการ
การทำการนำเข้าเฉพาะทำให้การปรับโครงสร้างทำได้ยากขึ้น ถ้าคุณลบ / เปลี่ยนชื่อคลาสคุณจะต้องลบทั้งหมดการนำเข้าเฉพาะหากคุณสลับการใช้งานเป็นคลาสอื่นในแพ็คเกจเดียวกันคุณต้องแก้ไขการนำเข้า ในขณะที่ขั้นตอนพิเศษเหล่านี้สามารถเป็นไปโดยอัตโนมัติ
แม้ว่า Eclipse จะไม่นำเข้าคลาสโดยค่าเริ่มต้นทุกคนจะยังคงนำเข้าดาว ฉันขอโทษ แต่ไม่มีเหตุผลที่สมเหตุสมผลสำหรับการทำการนำเข้าเฉพาะ
นี่คือวิธีจัดการกับความขัดแย้งในชั้นเรียน:
import java.sql.*;
import java.util.*;
import java.sql.Date;
Foo
และถ้าฉันอ่านรหัสของคุณโดยไม่ใช้ IDE (เนื่องจากข้อโต้แย้งของคุณคือฉันไม่ควรใช้อย่างใดอย่างหนึ่ง) ฉันจะรู้ได้อย่างไรว่าแพคเกจFoo
มาจากไหน? แน่นอนว่าการใช้ IDE นั้น IDE จะบอกฉัน แต่ข้อโต้แย้งทั้งหมดของคุณคือฉันควรจะสามารถอ่านรหัสได้โดยไม่มีใคร การทำการนำเข้าอย่างชัดเจนช่วยเอกสารรหัส (เหตุผลที่ดีในการหลีกเลี่ยงสัญลักษณ์เสริม)และมีแนวโน้มมากที่ฉันจะอ่านรหัสโดยไม่ใช้ IDE มากกว่าที่ฉันจะเขียนรหัสโดยไม่ใช้ IDE
โปรดดูบทความการนำเข้าตามความต้องการคือความชั่วร้าย
กล่าวโดยย่อปัญหาที่ใหญ่ที่สุดคือรหัสของคุณอาจแตกเมื่อมีการเพิ่มคลาสลงในแพ็คเกจที่คุณนำเข้า ตัวอย่างเช่น:
import java.awt.*;
import java.util.*;
// ...
List list;
ใน Java 1.1 นี่ใช้ได้ พบรายการใน java.awt และไม่มีข้อขัดแย้ง
ตอนนี้สมมติว่าคุณตรวจสอบรหัสการทำงานที่สมบูรณ์แบบของคุณและอีกหนึ่งปีต่อมามีคนนำมันออกมาเพื่อแก้ไขและใช้ Java 1.2
Java 1.2 เพิ่มอินเตอร์เฟสชื่อ List ไปยัง java.util BOOM! ขัดแย้ง. รหัสการทำงานที่สมบูรณ์แบบไม่ทำงานอีกต่อไป
นี่เป็นคุณสมบัติภาษาEVIL นอกจากนี้ไม่มีเหตุผลว่ารหัสควรจะหยุดการรวบรวมเพียงเพราะเป็นชนิดที่มีการเพิ่มการแพคเกจ ...
นอกจากนี้ยังทำให้ผู้อ่านระบุได้ยากว่า "Foo" ที่คุณใช้อยู่
java.util.List
vs java.awt.List
ไม่เลวเกินไปที่จะคิดออก แต่ลองใช้เมื่อชื่อคลาสเป็นConfiguration
และไลบรารีการพึ่งพาจำนวนมากได้เพิ่มเข้าไปในเวอร์ชัน repo maven ล่าสุดของพวกเขา
การใช้ไวด์การ์ดกับคำสั่งการนำเข้า Java นั้นไม่เลว
ในClean Code , Robert C. Martin แนะนำให้ใช้พวกเขาเพื่อหลีกเลี่ยงรายการนำเข้าที่มีความยาว
นี่คือคำแนะนำ:
J1: หลีกเลี่ยงรายการนำเข้าแบบยาวโดยใช้สัญลักษณ์แทน
หากคุณใช้สองคลาสขึ้นไปจากแพ็คเกจให้นำเข้าแพ็คเกจทั้งหมดด้วย
แพ็คเกจนำเข้า. *;
รายการการนำเข้าแบบยาวนั้นน่ากลัวสำหรับผู้อ่าน เราไม่ต้องการทำให้โมดูลของเรายุ่งเหยิงด้วยการนำเข้า 80 บรรทัด แต่เราต้องการให้การนำเข้าเป็นข้อความที่กระชับเกี่ยวกับแพคเกจที่เราทำงานร่วมกัน
การนำเข้าเฉพาะเป็นการพึ่งพายากในขณะที่การนำเข้าสัญลักษณ์แทนไม่ หากคุณนำเข้าคลาสโดยเฉพาะคลาสนั้นจะต้องมีอยู่ แต่ถ้าคุณนำเข้าแพคเกจที่มีไวด์การ์ดไม่จำเป็นต้องมีคลาสใดอยู่ คำสั่งการนำเข้าเพียงเพิ่มแพ็คเกจไปยังเส้นทางการค้นหาเมื่อค้นหาชื่อ ดังนั้นจึงไม่มีการพึ่งพาที่แท้จริงถูกสร้างขึ้นโดยการนำเข้าดังกล่าวและพวกเขาจึงให้บริการเพื่อให้โมดูลของเราคู่น้อยลง
มีหลายครั้งที่รายการนำเข้าที่เฉพาะเจาะจงจำนวนมากอาจมีประโยชน์ ตัวอย่างเช่นหากคุณกำลังจัดการกับรหัสดั้งเดิมและคุณต้องการค้นหาคลาสที่คุณต้องการสร้าง mocks และ stubs คุณสามารถเดินลงรายการนำเข้าเฉพาะเพื่อค้นหาชื่อที่ผ่านการรับรองจริงของชั้นเรียนเหล่านั้นทั้งหมดแล้วใส่ ต้นขั้วที่เหมาะสมในสถานที่ อย่างไรก็ตามการใช้งานสำหรับการนำเข้าเฉพาะนี้หายากมาก นอกจากนี้ IDEs ที่ทันสมัยส่วนใหญ่จะอนุญาตให้คุณแปลงการนำเข้า wildcard เป็นรายการของการอิมพอร์ตเฉพาะด้วยคำสั่งเดียว ดังนั้นแม้ในกรณีดั้งเดิมจะเป็นการดีกว่าที่จะนำเข้าสัญลักษณ์เสริม
การนำเข้าไวลด์การ์ดอาจทำให้เกิดข้อขัดแย้งของชื่อและความกำกวม สองคลาสที่มีชื่อเหมือนกัน แต่ในแพ็คเกจที่ต่างกันจะต้องมีการนำเข้าโดยเฉพาะหรืออย่างน้อยมีคุณสมบัติเฉพาะเมื่อใช้ นี่อาจเป็นสิ่งที่สร้างความรำคาญ แต่หายากพอที่การใช้การนำเข้าไวด์การ์ดโดยทั่วไปยังคงดีกว่าการนำเข้าเฉพาะ
ประสิทธิภาพการทำงาน : ไม่มีผลกระทบต่อประสิทธิภาพการทำงานเนื่องจากรหัสไบต์เหมือนกัน แม้ว่ามันจะนำไปสู่การรวบรวมค่าโสหุ้ย
การคอมไพล์: บนเครื่องส่วนตัวของฉันการคอมไพล์คลาสเปล่าโดยไม่ต้องอิมพอร์ตอะไรใช้เวลา 100 ms แต่คลาสเดียวกันเมื่ออิมพอร์ต java. * ใช้เวลา 170 ms
import java.*
นำเข้าอะไร ทำไมมันถึงสร้างความแตกต่าง?
มันตัดเนมสเปซของคุณโดยกำหนดให้คุณต้องระบุชื่อคลาสที่คลุมเครือ สิ่งที่พบได้บ่อยที่สุดคือ:
import java.util.*;
import java.awt.*;
...
List blah; // Ambiguous, needs to be qualified.
นอกจากนี้ยังช่วยทำให้การอ้างอิงของคุณเป็นรูปธรรมเนื่องจากการอ้างอิงทั้งหมดของคุณแสดงไว้ที่ด้านบนของไฟล์
สถานที่ส่วนใหญ่ที่ฉันเคยทำงานที่ใช้จาวาจำนวนมากทำให้การนำเข้าส่วนหนึ่งของมาตรฐานการเข้ารหัสชัดเจน บางครั้งฉันยังใช้ * สำหรับการสร้างต้นแบบอย่างรวดเร็วจากนั้นขยายรายการนำเข้า (IDE บางตัวจะทำสิ่งนี้เพื่อคุณเช่นกัน) เมื่อสร้างรหัส
ฉันชอบการนำเข้าที่เฉพาะเจาะจงเพราะมันทำให้ฉันเห็นการอ้างอิงภายนอกทั้งหมดที่ใช้ในไฟล์โดยไม่ต้องดูไฟล์ทั้งหมด (ใช่ฉันรู้ว่ามันไม่จำเป็นต้องแสดงข้อมูลอ้างอิงที่มีคุณสมบัติครบถ้วน แต่ฉันจะหลีกเลี่ยงเมื่อใดก็ตามที่เป็นไปได้)
ในโครงการก่อนหน้านี้ฉันพบว่าการเปลี่ยนจาก * - การนำเข้าเป็นการนำเข้าเฉพาะลดเวลารวบรวมโดยครึ่งหนึ่ง (จากประมาณ 10 นาทีเป็นประมาณ 5 นาที) * -import ทำให้คอมไพเลอร์ค้นหาแต่ละแพ็กเกจที่แสดงรายการสำหรับคลาสที่ตรงกับที่คุณใช้ ในขณะนี้อาจมีขนาดเล็ก แต่ก็เพิ่มขึ้นสำหรับโครงการขนาดใหญ่
ผลกระทบด้านข้างของ * -import คือผู้พัฒนาจะคัดลอกและวางบรรทัดการนำเข้าทั่วไปแทนที่จะคิดว่าพวกเขาต้องการอะไร
ในเทคโนโลยีการพัฒนาใด ๆ ก็ตามการดำเนินการจะขึ้นอยู่กับการค้นหาวิธีการลดการทำงานของโมดูล refactoring ใน Java ไม่มีการหลีกเลี่ยงการนำเข้าสู่แต่ละคลาส แต่อย่างน้อยคุณสามารถนำเข้าแพคเกจทั้งหมดในแต่ละครั้งซึ่งสะท้อนให้เห็นถึงความตั้งใจที่แพคเกจเป็นหน่วยที่มีความเหนียวแน่นสูงในขณะเดียวกันก็ลดความพยายามในการเปลี่ยนชื่อแพคเกจ
และถ้ามันตัดเนมสเปซในพื้นที่ไม่ใช่ความผิดของคุณ - ตำหนิขนาดของแพ็คเกจ
ไม่มีผลกระทบต่อรันไทม์เนื่องจากคอมไพเลอร์แทนที่ * ด้วยชื่อคลาสที่เป็นรูปธรรมโดยอัตโนมัติ ถ้าคุณแยกไฟล์ .class import ...*
คุณจะไม่เคยเห็น
C # มักจะใช้ * (โดยปริยาย) ในขณะที่คุณสามารถusing
จัดแพคเกจชื่อ คุณไม่สามารถระบุชื่อคลาสได้เลย Java แนะนำคุณสมบัติหลังจาก c # (Java นั้นค่อนข้างยุ่งยากในหลาย ๆ ด้าน แต่อยู่นอกเหนือจากหัวข้อนี้)
ใน Intellij Idea เมื่อคุณ "จัดระเบียบการนำเข้า" มันจะแทนที่การอิมพอร์ตแพ็กเกจเดียวกันด้วยหลายรายการโดยอัตโนมัติ นี่เป็นคุณสมบัติที่จำเป็นเนื่องจากคุณไม่สามารถปิดได้ (แม้ว่าคุณจะสามารถเพิ่มเกณฑ์ได้)
กรณีที่ระบุไว้โดยการตอบรับที่ยอมรับไม่ถูกต้อง หากไม่มี * คุณยังคงได้รับปัญหาเดียวกัน คุณต้องระบุชื่อ pakcage ในรหัสของคุณไม่ว่าคุณจะใช้ * หรือไม่ก็ตาม
สำหรับบันทึก: เมื่อคุณเพิ่มการนำเข้าคุณจะระบุการอ้างอิงของคุณด้วย
คุณสามารถดูได้อย่างรวดเร็วว่าการพึ่งพาของไฟล์คืออะไร (ไม่รวมคลาสของเนมสเปซเดียวกัน)
สิ่งที่สำคัญที่สุดคือการนำเข้าjava.awt.*
สามารถทำให้โปรแกรมของคุณเข้ากันไม่ได้กับรุ่น Java ในอนาคต:
สมมติว่าคุณมีระดับที่ชื่อ "เอบีซี" คุณกำลังใช้ JDK 8 java.util.*
และคุณนำเข้า ทีนี้สมมติว่า Java 9 ออกมาแล้วและมันมีคลาสใหม่ในแพคเกจjava.util
ที่เกิดขึ้นโดยบังเอิญเช่นกันที่เรียกว่า "ABC" โปรแกรมของคุณจะไม่คอมไพล์ใน Java 9 เนื่องจากคอมไพเลอร์ไม่ทราบว่าชื่อ ABC หรือไม่คุณหมายถึงคลาสของคุณเองหรือคลาสใหม่ในjava.awt
ที่คุณหมายถึงระดับของคุณเองหรือคนชั้นใหม่
คุณจะไม่มีปัญหานั้นเมื่อคุณนำเข้าเฉพาะคลาสเหล่านั้นอย่างชัดเจนจากjava.awt
ที่คุณใช้จริง
แหล่งข้อมูล:
Stream
เป็นตัวอย่างของคลาสใหม่ที่เพิ่มเข้ามาใน Java ใน java.util ใน Java 8 ...
ในจุดที่ถูกต้องทั้งสองด้านฉันไม่ได้พบเหตุผลหลักของฉันที่จะหลีกเลี่ยงสัญลักษณ์แทน: ฉันชอบที่จะสามารถอ่านรหัสและรู้โดยตรงว่าทุกชั้นเรียนคืออะไรหรือถ้าคำจำกัดความไม่ได้อยู่ในภาษาหรือ ไฟล์ที่จะหามัน หากมีการนำเข้าแพ็คเกจมากกว่าหนึ่งรายการด้วย * ฉันต้องไปค้นหาทุก ๆ แพ็คเกจเพื่อหาชั้นเรียนที่ฉันจำไม่ได้ ความสามารถในการอ่านสูงสุดและฉันยอมรับโค้ดไม่จำเป็นต้องมี IDE สำหรับการอ่าน