Імпорт двох класів з однаковою назвою. Як впоратися?


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. Це автоматично змінить його скрізь, де ви посилаєтесь на нього у своєму коді, а також у файлі (та імені файла) ваш / own / Date.java. Будь-який інший IDE, ймовірно, має подібну особливість.
MatrixFrog

16
Я не згоден з останнім твердженням. Якщо ви хочете створити свій власний клас дати, Dateце ідеальне ім'я. Ви будете використовувати його в більшості свого коду. Однак іноді вам потрібно буде зателефонувати java.util.Dateпомітно, щоб здійснити перетворення між обома.
парадигматичний

2
@MatrixFrog Функція Eclipse, яку ви вказали, також надається Netbeans IDE. Ця функція відома як "Рефактор". Ваша інформація не помилялася, але це не відповідь на поставлене запитання. Якщо він (Роджер) розробляє цей код, то він, безумовно, знає, що може змінити або змінити назву свого класу. Те, що він запитує, відрізняється від відповіді, яку ви дали.
Ятендра Гоел

11
@Yatendra Тому я додав це як коментар, а не відповідь. Я розширював питання, яке Еллі П. зробила наприкінці своєї відповіді. Роджер, напевно, це знає, але суть ТА полягає в тому, щоб допомогти іншим розробникам, а не лише людині, яка задала питання. Якщо люди не знають про функцію 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
Найкраща практика - імпортувати найбільш використаний, використовуючи найменш використаний з повним класовим шляхом
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.


Мені це подобається, за винятком (це просто), однак це не стосується проблеми, наприклад, для доступу до статичних методів.
Джастін Омс

Я роблю це весь час, коли хочу використовувати Hamcrest Matchersі Mockito Matchersв одному класі. Здається, працює зі статичними методами.
Адам Берлі

@Kidburla ви також можете використовувати статичний імпорт до тих пір, поки вам не байдуже, який збірник бере звідки. Я часто роблю це в одиничних тестах для матчів і .whens, .thenReturns тощо. - видаляє Mockito.набряк.
CptBartender

Це погана практика. Класи не слід розширювати, якщо певна функціональність не буде розширена з початкового класу.
Партха

3

Якщо у вас є власний клас дати, слід розрізнити його від вбудованого класу Дата. тобто чому ви створили свою власну. Щось на зразок 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 переживає, що, наприклад, означає "Person".


2

Якщо ви дійсно хочете або потребуєте використання одного і того ж імені класу з двох різних пакетів, у вас є два варіанти:

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}

Будь ласка, включіть код у скріншоті у свою відповідь.
Томас Ландауер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.