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


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

  }
}

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.