การนำเข้าสองคลาสที่มีชื่อเดียวกัน รับมือยังไง?


107

บอกว่าฉันชอบรหัส:

import java.util.Date;
import my.own.Date;

class Test{

  public static void main(String [] args){

    // I want to choose my.own.Date here. How?
    ..
    // I want to choose util.Date here. How ?

  }
}

ฉันควรเป็นชื่อชั้นแบบเต็มหรือไม่? ฉันสามารถกำจัดใบแจ้งยอดการนำเข้าได้หรือไม่? สถานการณ์ดังกล่าวเป็นเรื่องปกติในการเขียนโปรแกรมในโลกแห่งความเป็นจริงหรือไม่?


ไม่ใช่คำตอบสำหรับคำถามของคุณ แต่ใน C # คุณสามารถใช้นามแฝงสำหรับเนมสเปซใดก็ได้ อาจจะเป็นแค่น้ำตาลวากยสัมพันธ์ แต่มันช่วยได้มาก: msdn.microsoft.com/en-us/library/7f38zh8x.aspx
borjab

คำตอบ:


154

คุณสามารถละเว้นคำสั่งนำเข้าและอ้างถึงโดยใช้เส้นทางทั้งหมด เช่น:

java.util.Date javaDate = new java.util.Date()
my.own.Date myDate = new my.own.Date();

แต่ฉันจะบอกว่าการใช้สองคลาสที่มีชื่อเดียวกันและฟังก์ชั่นที่คล้ายกันมักไม่ใช่ความคิดที่ดีที่สุดเว้นแต่คุณจะระบุให้ชัดเจนว่าเป็นแบบไหน


2
หากคุณใช้ Eclipse คุณสามารถเปลี่ยนชื่อการyour.own.Dateใช้ ctrl + shift + R สิ่งนี้จะเปลี่ยนโดยอัตโนมัติทุกที่ที่คุณอ้างถึงในรหัสของคุณตลอดจนในไฟล์ (และชื่อไฟล์) ของคุณ / ของคุณ / Date.java IDE อื่น ๆ อาจมีคุณสมบัติที่คล้ายกัน
MatrixFrog

16
ฉันไม่เห็นด้วยกับคำพูดสุดท้าย หากคุณต้องการออกแบบคลาส Date ของคุณเองDateชื่อนี้เป็นชื่อที่สมบูรณ์แบบ คุณจะใช้มันในโค้ดส่วนใหญ่ของคุณ อย่างไรก็ตามบางครั้งคุณจะต้องเรียกสิ่งที่java.util.Dateสะดุดตาเพื่อทำการแปลงระหว่างทั้งสองอย่าง
paradigmatic

2
@MatrixFrog คุณลักษณะใน Eclipse ที่คุณระบุยังมีให้โดย Netbeans IDE คุณลักษณะนี้เรียกว่า "Refactor" ข้อมูลของคุณไม่ผิด แต่ไม่ใช่คำตอบของคำถามที่ถาม ถ้าเขา (โรเจอร์) กำลังพัฒนาโค้ดนั้นแน่นอนว่าเขาจะรู้ว่าเขาสามารถเปลี่ยนหรือเปลี่ยนชื่อคลาสของเขาได้ สิ่งที่เขาถามแตกต่างจากคำตอบที่คุณให้
Yatendra Goel

11
@Yatendra นั่นคือเหตุผลที่ฉันเพิ่มมันเป็นความคิดเห็นมากกว่าคำตอบ ฉันขยายประเด็นที่เอลลีพีทำในตอนท้ายของคำตอบของเธอ Roger คงรู้ดี แต่ประเด็นของ SO คือการช่วยเหลือนักพัฒนาคนอื่น ๆ ไม่ใช่แค่คนที่ถามคำถาม หากผู้คนไม่ทราบเกี่ยวกับคุณสมบัติ IDE พวกเขาอาจคิดว่าการเปลี่ยนชื่อด้วยมือเป็นไปไม่ได้ดังนั้นฉันคิดว่าการใส่ข้อมูลนั้นจะเป็นประโยชน์
MatrixFrog

5
มากที่สุดชื่อบ่อยการปะทะกันเกิดขึ้นกับฉันและorg.apache.log4j.Logger java.util.logging.Loggerโดยปกติแล้วฉันไม่สามารถควบคุมด้านใดด้านหนึ่งได้ ฉันกำลังรวมรหัสเดิม
kevinarpe

21

ใช้ชื่อแบบเต็มแทนการนำเข้าคลาส

เช่น

//import java.util.Date; //delete this
//import my.own.Date;

class Test{

   public static void main(String [] args){

      // I want to choose my.own.Date here. How?
      my.own.Date myDate = new my.own.Date();

      // I want to choose util.Date here. How ?
      java.util.Date javaDate = new java.util.Date();
   }
}

6
แนวทางปฏิบัติที่ดีที่สุดคือการนำเข้าอันที่ใช้มากที่สุดโดยใช้อันที่ใช้น้อยที่สุดกับ classpath แบบเต็ม
Alpaslan

10

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

java.util.Data date1 = new java.util.Date();
my.own.Date date2 = new my.own.Date();

7

อีกวิธีในการทำมันคือคลาสย่อย:

package my.own;

public class FQNDate extends Date {

}

จากนั้นนำเข้า my.own.FQNDate ในแพ็คเกจที่มี java.util.Date


ฉันชอบสิ่งนี้ยกเว้น (มันง่าย) แต่มันไม่ได้แก้ไขปัญหาสำหรับการพูดว่าเข้าถึงวิธีการแบบคงที่
Justin Ohms

ฉันทำสิ่งนี้ตลอดเวลาเมื่อฉันต้องการใช้ Hamcrest Matchersและ Mockito Matchersในคลาสเดียวกัน ดูเหมือนว่าจะใช้ได้กับวิธีการคงที่
Adam Burley

@Kidburla คุณสามารถใช้การนำเข้าแบบคงที่ได้ตราบใดที่คุณไม่สนใจว่าตัวจับคู่มาจากไหน ฉันมักจะทำเช่นนี้ในการทดสอบหน่วยสำหรับ matchers และ.whens, .thenReturns ฯลฯ - เอาMockito.บวม
CptBartender

นี่เป็นการปฏิบัติที่ไม่ดี ไม่ควรขยายชั้นเรียนเว้นแต่จะมีการขยายฟังก์ชันการทำงานบางอย่างจากคลาสเดิม
Partha

3

หากคุณมีคลาสวันที่ของคุณเองคุณควรแยกความแตกต่างจากคลาส Date ที่สร้างขึ้น เช่นทำไมคุณถึงสร้างของคุณเอง บางอย่างเช่น ImmutableDate หรือ BetterDate หรือ NanoDate แม้แต่ MyDate ก็ระบุว่าทำไมคุณถึงมีคลาสวันที่ของคุณเอง ในกรณีนี้พวกเขาจะมีชื่อเฉพาะ


3

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

เช่น:

import java.util.Date;

class Test{

  public static void main(String [] args){

    // your own date
    my.own.Date myOwndate ;

    // util.Date
    Date utilDate;
  }
}

2

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

ไม่บังคับว่าถ้าสองคลาสมีชื่อเดียวกันทั้งสองคลาสจะมีฟังก์ชันที่เหมือนกันและเราควรเลือกเพียงคลาสเดียว

หากเราต้องการทั้งสองอย่างก็ไม่มีอันตรายใด ๆ ในการใช้สิ่งนั้น และก็ไม่ใช่แนวคิดในการเขียนโปรแกรมที่ไม่ดีด้วย

แต่เราควรใช้ชื่อคลาสที่มีคุณสมบัติครบถ้วน (ที่มีชื่อเดียวกัน) เพื่อให้ชัดเจนว่าเราหมายถึงคลาสใดด้วย

:)


2

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

มีคุณสมบัติครบถ้วนเป็นวิธีหนึ่ง ดูเหมือนว่าคุณไม่สามารถรวมทั้งคำสั่งนำเข้าได้เนื่องจาก Java กังวลว่า "บุคคล" หมายถึงอะไรตัวอย่างเช่น


2

หากคุณต้องการหรือจำเป็นต้องใช้ชื่อคลาสเดียวกันจากแพ็กเกจที่แตกต่างกันสองแพ็กเกจคุณมีสองตัวเลือก:

1 เลือก1 ตัวเลือกเพื่อใช้ในการนำเข้าและใช้ชื่อคลาสแบบเต็มอื่น ๆ :

import my.own.Date;

class Test{

     public static void main(String[] args){

        // I want to choose my.own.Date here. How?
        //Answer:
        Date ownDate = new Date();

        // I want to choose util.Date here. How ?
        //Answer:
        java.util.Date utilDate = new java.util.Date();

     }
}


2- ใช้ชื่อคลาสแบบเต็มเสมอ:

//no Date import
class Test{

  public static void main(String[] args){

    // I want to choose my.own.Date here. How?
    //Answer:
     my.own.Date ownDate = new my.own.Date();
    // I want to choose util.Date here. How ?
    //Answer:
     java.util.Date utilDate = new java.util.Date();

  }
}

0

ฉันเพิ่งมีปัญหาเดียวกันสิ่งที่ฉันทำฉันจัดเรียงลำดับไลบรารีตามลำดับเช่นมี java.lang.NullPointerException และ javacard.lang.NullPointerException ฉันสร้างอันแรกเป็นไลบรารีเริ่มต้นและถ้าคุณต้องการใช้อันอื่นคุณสามารถระบุชื่อคลาสแบบเต็มได้อย่างชัดเจน


0

เมื่อคุณเรียกคลาสด้วยชื่อเดียวกันคุณต้องระบุแพ็กเกจที่เรียกคลาสนั้นอย่างชัดเจน

คุณสามารถทำได้ดังนี้:

import first.Foo;

public class Main {
    public static void main(String[] args) {
        System.out.println(new Foo());
        System.out.println(new second.Foo());
    }
}



package first;

public class Foo {
    public Foo() {
    }

    @Override
    public String toString() {
        return "Foo{first class}";
    }
}



package second;

public class Foo {
    public Foo() {
    }

    @Override
    public String toString() {
        return "Foo{second class}";
    }
}

เอาท์พุต:

Foo{first class}
Foo{second class}

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