Импорт двух классов с одинаковым именем. Как справиться?

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 # вы можете использовать псевдоним для любого пространства имен. Может быть, это просто синтаксический сахар, но он действительно полезен
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. Это автоматически изменит его везде, где вы на него ссылаетесь в своем коде, а также в файле (и имени файла) your / own / Date.java. Любая другая IDE, вероятно, имеет похожую функцию.
MatrixFrog
16
Я не согласен с последним утверждением. Если вы хотите создать свой собственный класс Date, Dateэто идеальное имя. Вы будете использовать его в большей части своего кода. Тем не менее, иногда вам нужно будет вызвать java.util.Dateфункцию, чтобы выполнить преобразование между ними.
paradigmatic
2
@MatrixFrog Указанная вами функция Eclipse также предоставляется IDE Netbeans. Эта функция известна как «Рефакторинг». Ваша информация не была ошибочной, но это не ответ на заданный вопрос. Если он (Роджер) разрабатывает этот код, то он определенно знает, что может изменить или реорганизовать имя своего класса. То, что он спрашивает, отличается от вашего ответа.
Yatendra Goel
11
@Yatendra Вот почему я добавил это как комментарий, а не как ответ. Я подробно остановился на том, что Элли П. сделала в конце своего ответа. Роджер, вероятно, знает это, но цель SO - помочь другим разработчикам, а не только тому, кто задал вопрос. Если люди не знают о функции IDE, они могут подумать, что невозможно переключать имена вручную, поэтому я подумал, что было бы полезно добавить эту информацию.
MatrixFrog
5
Мое самое частое столкновение имен происходит с org.apache.log4j.Loggerи java.util.logging.Logger. Обычно я не контролирую ту или иную сторону; Я занимаюсь интеграцией устаревшего кода.
kevinarpe 01
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
Лучшая практика - импортировать наиболее часто используемый, используя наименее используемый с полным
путем
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 01
Это плохая практика. Классы не следует расширять, если некоторые функции не расширяются от исходного класса.
Partha
3

Если у вас есть собственный класс даты, вы должны отличать его от встроенного класса Date. т.е. зачем вы создали свой. Что-то вроде ImmutableDate, BetterDate или NanoDate, даже MyDate укажет, почему у вас есть собственный класс даты. В этом случае у них будет уникальное имя.

Питер Лоури
источник
3

Вы можете импортировать один из них, используя import. Для всех других подобных классов необходимо указать полные имена классов. В противном случае вы получите ошибку компиляции.

Например:

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-выбрать один для использования при импорте и использовать полное имя класса другого:

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();

  }
}
человекопад19
источник
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}
Кирило Лозицкий
источник
Включите в ответ код со скриншота.
Томас Ландауэр