Importando duas classes com o mesmo nome. Como lidar?

107

Digamos que eu tenha um código como:

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 ?

  }
}

Devo ser nomes de classe totalmente qualificados? Posso me livrar das declarações de importação? Esse cenário é comum na programação do mundo real?

fim de jogo
fonte
Não é realmente uma resposta à sua pergunta, mas em C # você pode usar um alias para qualquer namespace. Pode ser apenas açúcar sintático, mas é realmente útil: msdn.microsoft.com/en-us/library/7f38zh8x.aspx
borjab

Respostas:

153

Você pode omitir as instruções de importação e se referir a elas usando o caminho inteiro. Por exemplo:

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

Mas eu diria que usar duas classes com o mesmo nome e uma função semelhante geralmente não é a melhor ideia, a menos que você possa deixar bem claro qual é qual.

Ellie P.
fonte
2
Se estiver usando o Eclipse, você pode alterar o nome your.own.Dateusando ctrl + shift + R. Isso irá alterá-lo automaticamente em todos os lugares em que você se referir a ele em seu código, bem como no arquivo (e nome de arquivo) seu / own / Date.java. Qualquer outro IDE provavelmente tem um recurso semelhante.
MatrixFrog
16
Não concordo com a última afirmação. Se você deseja criar sua própria classe Date, Dateé o nome perfeito. Você o usará na maior parte do seu código. No entanto, às vezes você precisará chamar o java.util.Datenotavelmente para fazer conversões entre os dois.
paradigmático de
2
@MatrixFrog O recurso no Eclipse que você especificou também é fornecido pelo Netbeans IDE. Este recurso é conhecido como "Refatorar". Sua informação não estava errada, mas não é a resposta para a pergunta feita. Se ele (Roger) está desenvolvendo esse código, então definitivamente ele sabe que pode alterar ou refatorar o nome de sua classe. O que ele está perguntando é diferente da resposta que você deu.
Yatendra Goel
11
@Yatendra É por isso que adicionei como um comentário ao invés de uma resposta. Eu estava expandindo o ponto que Ellie P. fez no final de sua resposta. Roger provavelmente sabe disso, mas o objetivo do SO é ajudar outros desenvolvedores, não apenas a pessoa que fez a pergunta. Se as pessoas não conhecerem o recurso IDE, elas podem pensar que é inviável trocar nomes manualmente, então achei que seria útil acrescentar essa informação.
MatrixFrog
5
Meu conflito de nomes mais frequente ocorre com org.apache.log4j.Loggere java.util.logging.Logger. Normalmente, não tenho controle sobre um lado ou outro; Estou fazendo integração de código legado.
kevinarpe 01 de
21

use o nome totalmente qualificado em vez de importar a classe.

por exemplo

//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();
   }
}
Chii
fonte
6
A melhor prática é importar o mais usado, usando o menos usado com o caminho de classe completo
Alpaslan
10

Sim, ao importar classes com os mesmos nomes simples, você deve se referir a eles por seus nomes de classe totalmente qualificados. Eu deixaria as instruções de importação, pois dá a outros desenvolvedores uma ideia do que está no arquivo quando eles estão trabalhando com ele.

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

Outra maneira de fazer isso é criar uma subclasse:

package my.own;

public class FQNDate extends Date {

}

Em seguida, importe my.own.FQNDate em pacotes que tenham java.util.Date.

Cheruvim
fonte
Eu gosto disso, exceto (é simples), no entanto, não aborda o problema de, digamos, acessar métodos estáticos.
Justin Ohms
Eu faço isso o tempo todo quando quero usar o Hamcrest Matcherse o Mockito Matchersna mesma classe. Parece funcionar com métodos estáticos.
Adam Burley
@Kidburla você também pode usar importações estáticas, desde que não se importe com qual matcher vem de onde. Costumo fazer isso em testes de unidade para matchers .whenes, .thenReturns etc. - remove o Mockito.inchaço.
CptBartender
Esta é uma prática ruim. As classes não devem ser estendidas a menos que alguma funcionalidade esteja sendo estendida da classe original.
Partha
3

Se você tiver sua própria classe de data, deverá distingui-la da classe de Data incorporada. ou seja, por que você criou o seu próprio. Algo como ImmutableDate ou BetterDate ou NanoDate, até mesmo MyDate indicaria por que você tem sua própria classe para encontros. Nesse caso, eles terão um nome exclusivo.

Peter Lawrey
fonte
3

Você pode importar um deles usando importar. Para todas as outras classes semelhantes, você precisa especificar nomes de classe totalmente qualificados. Caso contrário, você obterá um erro de compilação.

Por exemplo:

import java.util.Date;

class Test{

  public static void main(String [] args){

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

    // util.Date
    Date utilDate;
  }
}
Anuraj
fonte
2

Esse cenário não é tão comum na programação do mundo real, mas também não é tão estranho. Às vezes acontece que duas classes em pacotes diferentes têm o mesmo nome e precisamos de ambas.

Não é obrigatório que, se duas classes tiverem o mesmo nome, ambas conterão as mesmas funcionalidades e devemos escolher apenas uma delas.

Se precisarmos de ambos, não há mal nenhum em usar isso. E também não é uma má ideia de programação.

Mas devemos usar nomes totalmente qualificados das classes (que têm o mesmo nome) para deixar claro a qual classe estamos nos referindo também.

:)

Yatendra Goel
fonte
2

Eu me deparo com esse problema quando, por exemplo, mapeio uma classe para outra (como ao mudar para um novo conjunto de classes para representar dados pessoais). Nesse ponto, você precisa das duas classes porque esse é o ponto principal do código - mapear uma para a outra. E você não pode renomear as classes em nenhum dos lugares (novamente, o trabalho é mapear, não mudar o que outra pessoa fez).

Totalmente qualificado é uma maneira. Parece que você não pode realmente incluir ambas as instruções de importação, porque Java se preocupa com o significado de "Pessoa", por exemplo.

Randy Wilson
fonte
2

Se você realmente deseja ou precisa usar o mesmo nome de classe de dois pacotes diferentes, você tem duas opções:

1-escolha um para usar na importação e use o nome de classe totalmente qualificado do outro:

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-sempre use o nome de classe totalmente qualificado:

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

  }
}
manfall19
fonte
0

Acabei de ter o mesmo problema, o que fiz, organizei a ordem da biblioteca em sequência, por exemplo havia java.lang.NullPointerException e javacard.lang.NullPointerException. Fiz a primeira como biblioteca padrão e se você precisar usar a outra, pode especificar explicitamente o nome de classe totalmente qualificado.

Bondhan Novandy
fonte
0

Ao chamar classes com os mesmos nomes, você deve especificar explicitamente o pacote do qual a classe é chamada.

Você pode fazer assim:

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}";
    }
}

Resultado:

Foo{first class}
Foo{second class}
Kirilo Lozitsky
fonte
Inclua o código da captura de tela em sua resposta.
Thomas Landauer