Importazione di due classi con lo stesso nome. Come gestire?


107

Dì che ho un codice come:

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 essere nomi di classe completi qualificati? Posso sbarazzarmi delle dichiarazioni di importazione? Un tale scenario è comune nella programmazione del mondo reale?


Non è proprio una risposta alla tua domanda, ma in C # puoi usare un alias per qualsiasi spazio dei nomi. Può essere che è lo zucchero sintattico, ma è davvero disponibile: msdn.microsoft.com/en-us/library/7f38zh8x.aspx
borjab

Risposte:


154

È possibile omettere le istruzioni di importazione e fare riferimento a esse utilizzando l'intero percorso. Per esempio:

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

Ma direi che usare due classi con lo stesso nome e una funzione simile di solito non è l'idea migliore a meno che tu non riesca a chiarire veramente quale è quale.


2
Se stai usando Eclipse, puoi cambiare il nome your.own.Dateusando ctrl + maiusc + R. Questo lo cambierà automaticamente ovunque ci si riferisca ad esso nel codice, così come nel file (e nel nome del file) your / own / Date.java. Qualsiasi altro IDE probabilmente ha una caratteristica simile.
MatrixFrog

16
Non sono d'accordo con l'ultima affermazione. Se vuoi progettare la tua classe Date, Dateè il nome perfetto. Lo userai nella maggior parte del tuo codice. Tuttavia, a volte sarà necessario chiamare in java.util.Dateparticolare per effettuare conversioni tra entrambi.
paradigmatico

2
@MatrixFrog La funzionalità in Eclipse che hai specificato è fornita anche da Netbeans IDE. Questa funzionalità è nota come "Refactoring". Le tue informazioni non erano sbagliate ma non è la risposta alla domanda posta. Se lui (Roger) sta sviluppando quel codice, allora sicuramente sa che può cambiare o refactoring il nome della sua Classe. Quello che sta chiedendo è diverso dalla risposta che hai dato.
Yatendra Goel

11
@Yatendra Ecco perché l'ho aggiunto come commento piuttosto che come risposta. Stavo espandendo il punto sollevato da Ellie P. alla fine della sua risposta. Roger probabilmente lo sa, ma lo scopo di SO è aiutare altri sviluppatori, non solo la persona che ha posto la domanda. Se le persone non conoscono la funzionalità IDE, potrebbero pensare che non sia possibile cambiare i nomi manualmente, quindi ho pensato che sarebbe stato utile inserire queste informazioni.
MatrixFrog

5
Il mio conflitto di nomi più frequente si verifica con org.apache.log4j.Loggere java.util.logging.Logger. Di solito, non ho il controllo su una parte o sull'altra; Sto eseguendo l'integrazione del codice legacy.
kevinarpe

21

utilizzare il nome completo invece di importare la classe.

per esempio

//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
La migliore pratica è importare quello più utilizzato, utilizzando quello meno utilizzato con il classpath completo
Alpaslan

10

Sì, quando importi classi con gli stessi nomi semplici, devi fare riferimento ad esse tramite i loro nomi di classe completi. Lascerei le istruzioni di importazione in, poiché danno agli altri sviluppatori un'idea di cosa c'è nel file quando ci stanno lavorando.

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

7

Un altro modo per farlo è sottoclassarlo:

package my.own;

public class FQNDate extends Date {

}

Quindi importa my.own.FQNDate nei pacchetti che hanno java.util.Date.


Mi piace tranne (è semplice) tuttavia non risolve il problema per esempio l'accesso ai metodi statici.
Justin Ohms

Lo faccio sempre quando voglio usare Hamcrest Matcherse Mockito Matchersnella stessa classe. Sembra funzionare con metodi statici.
Adam Burley

@Kidburla puoi anche usare importazioni statiche purché non ti interessi quale matcher proviene da dove. Lo faccio spesso nei test unitari per matchers .whenes, .thenReturns ecc. - rimuove il Mockito.gonfiore.
CptBartender

Questa è una cattiva pratica. Le classi non dovrebbero essere estese a meno che alcune funzionalità non vengano estese dalla classe originale.
Partha

3

Se hai la tua classe data, dovresti distinguerla dalla classe data incorporata. ovvero perché ne hai creato uno tuo. Qualcosa come ImmutableDate o BetterDate o NanoDate, anche MyDate indicherebbe perché hai la tua classe di appuntamenti. In questo caso, avranno un nome univoco.


3

Puoi importarne uno utilizzando import. Per tutte le altre classi simili, è necessario specificare nomi di classi completi. Altrimenti otterrai un errore di compilazione.

Per esempio:

import java.util.Date;

class Test{

  public static void main(String [] args){

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

    // util.Date
    Date utilDate;
  }
}

2

Questo scenario non è così comune nella programmazione del mondo reale, ma nemmeno così strano. A volte capita che due classi in pacchetti diversi abbiano lo stesso nome e abbiamo bisogno di entrambe.

Non è obbligatorio che se due classi hanno lo stesso nome, entrambe conterranno le stesse funzionalità e dovremmo sceglierne solo una.

Se abbiamo bisogno di entrambi, non c'è nulla di male nell'usarlo. E non è nemmeno una cattiva idea di programmazione.

Ma dovremmo usare nomi completi delle classi (che hanno lo stesso nome) per rendere chiaro anche a quale classe ci riferiamo.

:)


2

Ho riscontrato questo problema quando, ad esempio, mappando una classe a un'altra (come quando si passa a un nuovo set di classi per rappresentare i dati della persona). A quel punto, hai bisogno di entrambe le classi perché questo è il punto centrale del codice: mappare l'una all'altra. E non puoi rinominare le classi in nessuno dei due posti (di nuovo, il lavoro è mappare, non cambiare quello che ha fatto qualcun altro).

Pienamente qualificato è un modo. Sembra che tu non possa effettivamente includere entrambe le istruzioni di importazione, perché Java si preoccupa, ad esempio, di quale "Persona" si intende.


2

Se vuoi davvero o devi usare lo stesso nome di classe da due diversi pacchetti, hai due opzioni:

1-scegli uno da usare nell'importazione e usa il nome di classe completo dell'altro:

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-usa sempre il nome completo della classe:

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

Ho appena avuto lo stesso problema, quello che ho fatto, ho organizzato l'ordine della libreria in sequenza, ad esempio c'erano java.lang.NullPointerException e javacard.lang.NullPointerException. Ho creato la prima come libreria predefinita e se hai bisogno di usare l'altra puoi specificare esplicitamente il nome completo della classe.


0

Quando chiamate classi con gli stessi nomi, dovete specificare esplicitamente il pacchetto da cui viene chiamata la classe.

Puoi fare in questo modo:

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

Produzione:

Foo{first class}
Foo{second class}

Si prega di includere il codice dallo screenshot nella risposta.
Thomas Landauer
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.