[java] Qual è un buon caso d'uso per l'importazione statica di metodi?


6 Answers

Un altro uso ragionevole per le importazioni statiche è con JUnit 4. Nelle versioni precedenti di JUnit sono stati ereditati metodi come assertEquals e fail poiché la classe di test ha esteso junit.framework.TestCase .

// old way
import junit.framework.TestCase;

public class MyTestClass extends TestCase {
    public void myMethodTest() {
        assertEquals("foo", "bar");
    }
}

In JUnit 4, le classi di test non devono più estendere il TestCase e possono invece utilizzare annotazioni. È quindi possibile importare staticamente i metodi di org.junit.Assert da org.junit.Assert :

// new way
import static org.junit.Assert.assertEquals;

public class MyTestClass {
    @Test public void myMethodTest() {
        assertEquals("foo", "bar");
        // instead of
        Assert.assertEquals("foo", "bar");
    }
}

JUnit documents utilizzano in questo modo.

Question

Ho appena ricevuto un commento di recensione che la mia importazione statica del metodo non era una buona idea. L'importazione statica era di un metodo di una classe DA, che ha principalmente metodi statici. Così, nel mezzo della logica del business, ho avuto un'attività che apparentemente sembrava appartenere alla classe attuale:

import static some.package.DA.*;
class BusinessObject {
  void someMethod() {
    ....
    save(this);
  }
} 

Il revisore non era entusiasta di aver cambiato il codice e non l'ho fatto, ma sono in qualche modo d'accordo con lui. Una ragione fornita per l'importazione non statica è stata la confusione in cui è stato definito il metodo, non era nella classe corrente e non in nessuna superclasse, quindi anche un po 'di tempo per identificare la sua definizione (il sistema di revisione basato sul web non ha cliccabile link come IDE :-) Non penso che questo sia importante, le importazioni statiche sono ancora piuttosto nuove e presto ci abitueremo a localizzarle.

Ma l'altro motivo, quello su cui sono d'accordo, è che una chiamata di metodo non qualificata sembra appartenere all'oggetto corrente e non dovrebbe saltare contesti. Ma se appartenesse davvero, avrebbe senso estendere quella super classe.

Quindi, quando ha senso adottare metodi di importazione statici? Quando l'hai fatto? Ti è piaciuto / mi piace il modo in cui appaiono le chiamate non qualificate?

EDIT: L'opinione popolare sembra essere quella dei metodi di importazione statica se nessuno li confonderà come metodi della classe corrente. Ad esempio i metodi da java.lang.Math e java.awt.Color. Ma se abs e getAlpha non sono ambigui, non vedo perché readEmployee sia. Come in molte scelte di programmazione, penso che anche questa sia una preferenza personale.

Grazie per la vostra risposta ragazzi, sto chiudendo la domanda.




Uso 'import static java.lang.Math. *' Durante il trasferimento di codice pesante matematico da C / C ++ a java. I metodi matematici mappano da 1 a 1 e rendono più facile diffondere il codice porticato senza la qualifica del nome della classe.




Raccomando l'uso dell'importazione statica quando si usa OpenGL con Java, che è un caso d'uso che rientra nella categoria "uso intensivo di costanti da una classe di utilità"

Considera che

import static android.opengl.GLES20.*;

ti permette di portare il codice C originale e scrivere qualcosa di leggibile come:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(samplerUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, vtxBuffer);
glVertexAttribPointer(vtxAttrib, 3, GL_FLOAT, false, 0, 0);

invece di quella comune bruttezza diffusa:

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
GLES20.glUniform1i(samplerUniform, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vtxBuffer);
GLES20.glVertexAttribPointer(vtxAttrib, 3, GLES20.GL_FLOAT, false, 0, 0);



Penso che l'importazione statica sia davvero utile per rimuovere nomi di classi ridondanti quando si utilizzano classi utils come Arrays e Assertions .

Non so perché, ma Ross ha saltato fuori l'ultima frase che menziona questo nella https://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html .

Utilizzato in modo appropriato, l'importazione statica può rendere più leggibile il programma rimuovendo il testo di ripetizione dei nomi delle classi.

Fondamentalmente copiato da questo blog: https://medium.com/alphadev-thoughts/static-imports-are-great-but-underused-e805ba9b279f

Quindi per esempio:

Asserzioni nei test

Questo è il caso più ovvio su cui penso siamo tutti d'accordo

Assertions.assertThat(1).isEqualTo(2);

// Use static import instead
assertThat(1).isEqualTo(2);

Classi ed enigmi di Utils

Il nome della classe può essere rimosso in molti casi quando si utilizzano le classi utils che rendono il codice più facile da leggere

List<Integer> numbers = Arrays.asList(1, 2, 3);

// asList method name is enough information
List<Integer> numbers = asList(1, 2, 3);

Il pacchetto java.time ha alcuni casi in cui dovrebbe essere usato

// Get next Friday from now, quite annoying to read
LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

// More concise and easier to read
LocalDate.now().with(next(FRIDAY));

Esempio di quando non usare

// Ok this is an Optional
Optional.of("hello world");

// I have no idea what this is 
of("hello world");



Penso che le importazioni statiche siano chiare per NLS in stile gettext.

import static mypackage.TranslatorUtil._;

//...
System.out.println(_("Hello world."));

Ciò indica sia la stringa che una stringa che deve essere estratta e fornisce un modo semplice e pulito per sostituire la stringa con la sua traduzione.




Lo uso molto per Color.

static import java.awt.Color.*;

È molto improbabile che i colori vengano confusi con qualcos'altro.




Parlando dei test unitari: la maggior parte delle persone usa le importazioni statiche per i vari metodi statici forniti dai framework di simulazione, come when() o verify() .

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

E naturalmente, quando si usa l'unica affermazione che si dovrebbe usare `assertThat (), è utile importare staticamente i necessari hamcrest matcher, come in:

import static org.hamcrest.Matchers.*;



Related