Importowanie dwóch klas o tej samej nazwie. Jak radzić sobie?


107

Powiedz, że mam kod taki jak:

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 ?

  }
}

Czy powinienem mieć pełne kwalifikowane nazwy klas? Czy mogę pozbyć się instrukcji importu? Czy taki scenariusz jest powszechny w programowaniu w świecie rzeczywistym?


Właściwie nie jest to odpowiedź na twoje pytanie, ale w C # możesz użyć aliasu dla dowolnej przestrzeni nazw. Może to tylko cukier syntaktyczny, ale jest naprawdę pomocny: msdn.microsoft.com/en-us/library/7f38zh8x.aspx
borjab

Odpowiedzi:


154

Możesz pominąć instrukcje importu i odwołać się do nich, używając całej ścieżki. Na przykład:

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

Powiedziałbym jednak, że używanie dwóch klas o tej samej nazwie i podobnej funkcji zwykle nie jest najlepszym pomysłem, chyba że można jasno określić, która jest która.


2
Jeśli używasz Eclipse, możesz zmienić nazwę, your.own.Dateużywając ctrl + shift + R. Spowoduje to automatyczną zmianę wszędzie tam, gdzie odwołujesz się do niego w swoim kodzie, a także w pliku (i nazwie pliku) your / own / Date.java. Każde inne IDE prawdopodobnie ma podobną funkcję.
MatrixFrog,

16
Nie zgadzam się z ostatnim stwierdzeniem. Jeśli chcesz zaprojektować własną klasę Date, Datenazwa jest idealna. Będziesz go używać w większości swojego kodu. Czasami jednak będziesz musiał zadzwonić w java.util.Dateszczególności, aby dokonać konwersji między oboma.
paradygmatyczny

2
@MatrixFrog Funkcja Eclipse, którą określiłeś, jest również udostępniana przez Netbeans IDE. Ta funkcja jest znana jako „Refaktoryzacja”. Twoje informacje nie były błędne, ale nie jest to odpowiedź na zadane pytanie. Jeśli on (Roger) rozwija ten kod, to na pewno wie, że może zmienić lub przeformatować nazwę swojej klasy. To, o co pyta, różni się od odpowiedzi, której udzieliłeś.
Yatendra Goel

11
@Yatendra Dlatego dodałem to raczej jako komentarz niż odpowiedź. Rozwijałem kwestię, którą Ellie P. poczyniła na końcu swojej odpowiedzi. Roger prawdopodobnie to wie, ale celem SO jest pomoc innym programistom, a nie tylko osobie, która zadała pytanie. Jeśli ludzie nie wiedzą o funkcji IDE, mogą pomyśleć, że ręczne zmienianie nazw jest niewykonalne, więc pomyślałem, że warto byłoby wrzucić te informacje.
MatrixFrog

5
Moje najczęstsze zderzenie nazw występuje z org.apache.log4j.Loggeri java.util.logging.Logger. Zwykle nie mam kontroli nad jedną lub drugą stroną; Robię integrację ze starszym kodem.
kevinarpe

21

użyj w pełni kwalifikowanej nazwy zamiast importować klasę.

na przykład

//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
Najlepszą praktyką jest importowanie najczęściej używanego, używając najmniej używanego z pełną ścieżką klas
Alpaslan

10

Tak, kiedy importujesz klasy o tych samych prostych nazwach, musisz odwoływać się do nich, używając ich w pełni kwalifikowanych nazw. Pozostawiłbym instrukcje importu w, ponieważ daje to innym programistom poczucie tego, co jest w pliku, gdy z nim pracują.

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

7

Innym sposobem na to jest podklasa:

package my.own;

public class FQNDate extends Date {

}

A następnie zaimportuj my.own.FQNDate w pakietach, które mają java.util.Date.


Podoba mi się to, z wyjątkiem tego (jest to proste), ale nie rozwiązuje problemu, powiedzmy, dostępu do metod statycznych.
Justin Ohms,

Robię to cały czas, gdy chcę używać Hamcrest Matchersi Mockito Matchersw tej samej klasie. Wydaje się, że działa z metodami statycznymi.
Adam Burley

@Kidburla możesz również użyć importu statycznego, o ile nie obchodzi Cię, który element dopasowujący pochodzi skąd. Często robię to w testach jednostkowych dla dopasowań i .whens, .thenReturnitp. - usuwa Mockito.wzdęcia.
CptBartender

To zła praktyka. Klasy nie powinny być rozszerzane, chyba że niektóre funkcje są rozszerzane z oryginalnej klasy.
Partha

3

Jeśli masz własną klasę Date, powinieneś ją odróżnić od wbudowanej klasy Date. tj. dlaczego stworzyłeś swój własny. Coś w rodzaju ImmutableDate lub BetterDate lub NanoDate, nawet MyDate wskazywałoby, dlaczego masz własną klasę randkową. W takim przypadku będą miały unikalną nazwę.


3

Możesz zaimportować jeden z nich za pomocą importu. W przypadku wszystkich innych podobnych klas należy określić w pełni kwalifikowane nazwy klas. W przeciwnym razie pojawi się błąd kompilacji.

Na przykład:

import java.util.Date;

class Test{

  public static void main(String [] args){

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

    // util.Date
    Date utilDate;
  }
}

2

Ten scenariusz nie jest tak powszechny w programowaniu w świecie rzeczywistym, ale też nie jest tak dziwny. Czasami zdarza się, że dwie klasy w różnych pakietach mają tę samą nazwę i potrzebujemy obu.

Nie jest obowiązkowe, że jeśli dwie klasy mają taką samą nazwę, to obie będą zawierały te same funkcjonalności i powinniśmy wybrać tylko jedną z nich.

Jeśli potrzebujemy obu, nie ma nic złego w używaniu tego. Nie jest to też zły pomysł na programowanie.

Powinniśmy jednak używać w pełni kwalifikowanych nazw klas (o tej samej nazwie), aby było jasne, do której klasy również się odnosimy.

:)


2

Trafiłem na ten problem, gdy na przykład mapuję jedną klasę na inną (na przykład przy przełączaniu na nowy zestaw klas reprezentujących dane osoby). W tym momencie potrzebujesz obu klas, ponieważ to jest cały punkt kodu - aby zmapować jedną na drugą. I nie możesz zmienić nazw klas w żadnym miejscu (ponownie, zadaniem jest mapowanie, a nie zmienianie tego, co zrobił ktoś inny).

Pełne kwalifikacje to jedna droga. Wygląda na to, że nie można w rzeczywistości uwzględnić obu instrukcji importu, ponieważ Java martwi się, na przykład, o którą „osobę” chodzi.


2

Jeśli naprawdę chcesz lub potrzebujesz użyć tej samej nazwy klasy z dwóch różnych pakietów, masz dwie opcje:

1-wybierz jeden do importu i użyj w pełni kwalifikowanej nazwy klasy drugiej:

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 - zawsze używaj w pełni kwalifikowanej nazwy klasy:

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

Po prostu miałem ten sam problem, co zrobiłem, uporządkowałem kolejność bibliotek w kolejności, na przykład były java.lang.NullPointerException i javacard.lang.NullPointerException. Pierwszą z nich ustawiłem jako bibliotekę domyślną, a jeśli chcesz użyć drugiej, możesz jawnie określić pełną kwalifikowaną nazwę klasy.


0

W przypadku wywoływania klas o takich samych nazwach należy jawnie określić pakiet, z którego ta klasa jest wywoływana.

Możesz zrobić tak:

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

Wynik:

Foo{first class}
Foo{second class}

W odpowiedzi podaj kod ze zrzutu ekranu.
Thomas Landauer
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.