Importando dos clases con el mismo nombre. ¿Cómo manejar?

107

Digamos que tengo un 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 ?

  }
}

¿Debería ser nombres completos de clases calificados? ¿Puedo deshacerme de las declaraciones de importación? ¿Es este escenario común en la programación del mundo real?

juego terminado
fuente
No es realmente una respuesta a su pregunta, pero en C # puede usar un alias para cualquier espacio de nombres. Puede ser solo azúcar sintáctico, pero es realmente útil: msdn.microsoft.com/en-us/library/7f38zh8x.aspx
borjab

Respuestas:

154

Puede omitir las declaraciones de importación y consultarlas utilizando la ruta completa. P.ej:

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

Pero yo diría que usar dos clases con el mismo nombre y una función similar no suele ser la mejor idea a menos que puedas dejar muy claro cuál es cuál.

Ellie P.
fuente
2
Si está usando Eclipse, puede cambiar el nombre de your.own.Dateusar ctrl + shift + R. Esto lo cambiará automáticamente en todos los lugares a los que se refiera en su código, así como en el archivo (y nombre de archivo) your / own / Date.java. Cualquier otro IDE probablemente tenga una característica similar.
MatrixFrog
16
No estoy de acuerdo con la última declaración. Si desea diseñar su propia clase Date, Datees el nombre perfecto. Lo usará en la mayor parte de su código. Sin embargo, a veces necesitará llamar al java.util.Datenotablemente para realizar conversiones entre ambos.
paradigmático
2
@MatrixFrog La función de Eclipse que ha especificado también la proporciona Netbeans IDE. Esta característica se conoce como "Refactorización". Tu información no es incorrecta, pero no es la respuesta a la pregunta. Si él (Roger) está desarrollando ese código, definitivamente sabe que puede cambiar o refactorizar el nombre de su Clase. Lo que pregunta es diferente a la respuesta que le diste.
Yatendra Goel
11
@Yatendra Es por eso que lo agregué como comentario en lugar de respuesta. Estaba ampliando el punto que hizo Ellie P. al final de su respuesta. Roger probablemente lo sepa, pero el objetivo de SO es ayudar a otros desarrolladores, no solo a la persona que hizo la pregunta. Si las personas no conocen la función IDE, podrían pensar que no es factible cambiar los nombres manualmente, así que pensé que sería útil incluir esa información.
MatrixFrog
5
Mi conflicto de nombres más frecuente ocurre con org.apache.log4j.Loggery java.util.logging.Logger. Por lo general, no tengo control sobre un lado o el otro; Estoy integrando código heredado.
kevinarpe
21

utilice el nombre completo en lugar de importar la clase.

p.ej

//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
fuente
6
La mejor práctica es importar el más utilizado, utilizando el menos utilizado con el classpath completo
Alpaslan
10

Sí, cuando importa clases con los mismos nombres simples, debe referirse a ellas por sus nombres de clase completamente calificados. Dejaría las declaraciones de importación, ya que les da a otros desarrolladores una idea de lo que hay en el archivo cuando están trabajando con él.

java.util.Data date1 = new java.util.Date();
my.own.Date date2 = new my.own.Date();
corriente continua
fuente
7

Otra forma de hacerlo es subclasificarlo:

package my.own;

public class FQNDate extends Date {

}

Y luego importe my.own.FQNDate en paquetes que tengan java.util.Date.

Cheruvim
fuente
Me gusta esto excepto (es simple) sin embargo, no aborda el problema de, por ejemplo, acceder a métodos estáticos.
Justin Ohms
Hago esto todo el tiempo cuando quiero usar Hamcrest Matchersy Mockito Matchersen la misma clase. Parece funcionar con métodos estáticos.
Adam Burley
@Kidburla también puede usar importaciones estáticas siempre que no le importe qué comparador viene de dónde. A menudo hago esto en pruebas unitarias para matchers y .whens, .thenReturns , etc. - elimina la Mockito.hinchazón.
CptBartender
Esta es una mala práctica. Las clases no deben extenderse a menos que se extienda alguna funcionalidad de la clase original.
Partha
3

Si tiene su propia clase de fecha, debe distinguirla de la clase de fecha incorporada. es decir, ¿por qué creaste el tuyo? Algo como ImmutableDate o BetterDate o NanoDate, incluso MyDate indicaría por qué tiene su propia clase de fecha. En este caso, tendrán un nombre único.

Peter Lawrey
fuente
3

Puede importar uno de ellos mediante la importación. Para todas las demás clases similares, debe especificar nombres de clase totalmente calificados. De lo contrario, obtendrá un error de compilación.

P.ej:

import java.util.Date;

class Test{

  public static void main(String [] args){

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

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

Este escenario no es tan común en la programación del mundo real, pero tampoco tan extraño. A veces sucede que dos clases en paquetes diferentes tienen el mismo nombre y las necesitamos a las dos.

No es obligatorio que si dos clases tienen el mismo nombre, ambas contendrán las mismas funcionalidades y debamos elegir solo una de ellas.

Si necesitamos ambos, entonces no hay nada de malo en usarlos. Y tampoco es una mala idea de programación.

Pero deberíamos usar nombres completos de las clases (que tienen el mismo nombre) para dejar claro a qué clase nos referimos también.

:)

Yatendra Goel
fuente
2

Me encuentro con este problema cuando, por ejemplo, mapeo una clase a otra (como cuando cambio a un nuevo conjunto de clases para representar datos personales). En ese punto, necesita ambas clases porque ese es el objetivo del código: asignar una a la otra. Y no puede cambiar el nombre de las clases en ningún lugar (nuevamente, el trabajo es mapear, no cambiar lo que hizo otra persona).

Completamente calificado es una forma. Parece que en realidad no puede incluir ambas declaraciones de importación, porque Java se preocupa por a qué "Persona" se refiere, por ejemplo.

Randy Wilson
fuente
2

Si realmente desea o necesita usar el mismo nombre de clase de dos paquetes diferentes, tiene dos opciones:

1-elija uno para usar en la importación y use el nombre de clase completo del otro:

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-utilice siempre el nombre de clase completo:

//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
fuente
0

Simplemente tuve el mismo problema, lo que hice, organicé el orden de la biblioteca en secuencia, por ejemplo, había java.lang.NullPointerException y javacard.lang.NullPointerException. Hice la primera como biblioteca predeterminada y si necesita usar la otra, puede especificar explícitamente el nombre completo de la clase calificada.

Bondhan Novandy
fuente
0

Cuando llama a clases con los mismos nombres, debe especificar explícitamente el paquete desde el que se llama a la clase.

Puedes hacer esto:

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

Salida:

Foo{first class}
Foo{second class}
Kirilo Lozitsky
fuente
Incluya el código de la captura de pantalla en su respuesta.
Thomas Landauer