Что является хорошим прецедентом для статического импорта методов?

Просто получил комментарий к обзору, что мой статический импорт метода не был хорошей идеей. Статический импорт был методом из класса DA, который имеет в основном статические методы. Итак, в середине бизнес-логики у меня была активность da, которая, по-видимому, принадлежала к текущему классу:

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

Рецензент не интересовался тем, что я меняю код, и я не сделал этого, но я согласен с ним. Одна из причин, почему не статический импорт, заключалась в том, что запутанный метод был определен, он не был в текущем классе, а не в каком-либо суперклассе, поэтому слишком некоторое время для определения его определения (веб-обзорная система не имеет интерактивных такие как IDE:-) Я действительно не думаю, что это имеет значение, статические-импорт все еще совершенно новый, и вскоре мы все привыкём к их поиску.

Но другая причина, с которой я согласен, заключается в том, что вызов неквалифицированного метода кажется принадлежащим текущему объекту и не должен пересказывать контексты. Но если это действительно так, было бы целесообразно расширить этот суперкласс.

Итак, когда это имеет смысл для статических методов импорта? Когда вы это сделали? Вам понравилось, как выглядят безусловные звонки?

EDIT: популярное мнение похоже на то, что статические методы импорта, если никто не собирается путать их как методы текущего класса. Например, методы из java.lang.Math и java.awt.Color. Но если abs и getAlpha не являются двусмысленными, я не понимаю, почему readEmployee. Как и во многих вариантах программирования, я думаю, что это тоже личное предпочтение.

Спасибо за ответ, ребята, я закрываю вопрос.

Ответ 1

Это от руководства Sun, когда они отпустили функцию (выделение в оригинале):

Итак, когда вы должны использовать статический импорт? Очень экономно! Используйте его только тогда, когда в противном случае у вас возникнет соблазн объявить локальные копии констант или злоупотреблять наследованием (Constant Interface Antipattern).... Если вы злоупотребляете функцией статического импорта, это может сделать вашу программу нечитаемой и недостижимой, загрязняя ее пространство имен всеми статическими членами, которые вы импортируете. Читатели вашего кода (включая вас, через несколько месяцев после того, как вы его написали) не будут знать, из какого класса приходит статический член. Импорт всех статических элементов из класса может быть особенно вреден для удобочитаемости; если вам нужен только один или два члена, импортируйте их отдельно.

(http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html)

Есть две части, которые я хочу вызвать специально:

  • Использовать статический импорт только, когда у вас возникает соблазн "злоупотреблять наследованием". В этом случае у вас возникнет соблазн иметь BusinessObject extend some.package.DA? Если это так, статический импорт может быть более чистым способом обработки этого. Если вы никогда не мечтали о расширении some.package.DA, то это, вероятно, плохое использование статического импорта. Не используйте его только для сохранения нескольких символов при вводе.
  • Импортировать отдельные элементы. Произнести import static some.package.DA.save вместо DA.*. Это значительно облегчит поиск источника импортируемого метода.

Лично я использовал эту функцию языка очень редко и почти всегда только с константами или перечислениями, никогда с методами. Компромисс для меня почти никогда не стоит.

Ответ 2

Еще одно разумное использование для статического импорта - с JUnit 4. В более ранних версиях методы JUnit, такие как assertEquals и fail, были наследованы с расширенного тестового класса junit.framework.TestCase.

// old way
import junit.framework.TestCase;

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

В JUnit 4 тестовым классам больше не нужно расширять TestCase и вместо этого использовать аннотации. Затем вы можете статически импортировать методы assert из 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 документы, используя его таким образом.

Ответ 3

Эффективная Java, второе издание, в конце пункта 19 отмечается, что вы можете использовать статический импорт, если сильно , используя константы из служебного класса. Я думаю, что этот принцип применим к статическому импорту как констант, так и методов.

import static com.example.UtilityClassWithFrequentlyUsedMethods.myMethod;

public class MyClass {
    public void doSomething() {
        int foo= UtilityClassWithFrequentlyUsedMethods.myMethod();
        // can be written less verbosely as
        int bar = myMethod();
    }
}

У этого есть преимущества и недостатки. Это делает код более читаемым за счет потери непосредственной информации о том, где этот метод определен. Тем не менее, хорошая среда IDE позволит вам перейти к определению, так что это не большая проблема.

Вы все равно должны использовать это экономно, и только в том случае, если вы часто используете вещи из импортированного файла много раз.

Изменить: Обновлено, чтобы быть более конкретным для методов, как это касается этого вопроса. Принцип применяется независимо от того, что импортируется (константы или методы).

Ответ 4

Я согласен, что они могут быть проблематичными с точки зрения читаемости и должны использоваться экономно. Но при использовании общего статического метода они могут повысить читаемость. Например, в тестовом классе JUnit такие методы, как assertEquals, очевидны там, где они происходят. Аналогично для методов из java.lang.Math.

Ответ 5

Я использую его для Color много.

static import java.awt.Color.*;

Очень маловероятно, что цвета будут смущены чем-то другим.

Ответ 6

Статический импорт - единственная "новая" функция Java, которую я никогда не использовал и не собираюсь использовать, из-за проблем, о которых вы только что упоминали.

Ответ 7

Вам нужно использовать их, когда:

  • вы хотите использовать оператор switch с значениями перечисления
  • вы хотите, чтобы ваш код был трудно понять.

Ответ 8

Я думаю, что статический импорт опрятен для NLS в стиле gettext.

import static mypackage.TranslatorUtil._;

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

Это означает, что строка является строкой, которая должна быть извлечена, и обеспечивает простой и чистый способ замены строки ее переводом.

Ответ 9

Статический импорт IMO - довольно приятная функция. Совершенно верно, что большая зависимость от статического импорта делает код нечитаемым и трудно понять, к какому классу принадлежит статический метод или атрибут. Однако, по моему опыту, он становится полезной особенностью, особенно при разработке классов Util, которые предоставляют некоторые статические методы и атрибуты. Неоднозначность, возникающая при обеспечении статического импорта, может быть обойдена путем установления стандартов кода. По моему опыту в компании этот подход является приемлемым и делает код более понятным и понятным. Я предпочитаю вставлять символ _ передними статическими методами и статическими атрибутами (как-то принятыми из C). По-видимому, этот подход нарушает стандарты именования Java, но он обеспечивает ясность для кода. Например, если у нас есть класс AngleUtils:

public class AngleUtils {

    public static final float _ZERO = 0.0f;
    public static final float _PI   = 3.14f;

    public static float _angleDiff(float angle1, float angle2){

    }

    public static float _addAngle(float target, float dest){

    }
}

В этом случае статический импорт обеспечивает ясность, а структура кода выглядит более элегантно для меня:

import static AngleUtils.*;

public class TestClass{

    public void testAngles(){

        float initialAngle = _ZERO;
        float angle1, angle2;
        _addAngle(angle1, angle2);
    }
}

Сразу же кто-то может сказать, какой метод или атрибут исходит от статического импорта, и он скрывает информацию о классе, к которому он принадлежит. Я не предлагаю использовать статический импорт для классов, которые являются неотъемлемой частью модуля и предоставляют статические и нестатические методы, так как в этом случае важно знать, какой класс предоставляет определенные статические функции.

Ответ 10

Я использую 'import static java.lang.Math. *' при переносе математического тяжелого кода с C/С++ на java. Математические методы отображают от 1 до 1 и упрощают сравнение переносимого кода без квалификации класса.

Ответ 11

Я рекомендую использовать статический импорт при использовании OpenGL с Java, который используется в случае использования "тяжелого использования констант из класса утилит"

Рассмотрим, что

import static android.opengl.GLES20.*;

позволяет вам перенести исходный код на C и записать что-нибудь читаемое, например:

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

вместо этого широко распространенного уродства:

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

Ответ 12

Они полезны для уменьшения формулировки, особенно в тех случаях, когда вызывается много импортируемых методов, а различие между локальными и импортными методами ясное.

Один пример: код, который включает несколько ссылок на java.lang.Math

Другое: класс строителя XML, где добавление класса к каждой ссылке будет скрывать построенную структуру

Ответ 13

Я использую их, когда только могу. У меня есть IntelliJ setup, чтобы напомнить мне, если я забуду. Я думаю, что он выглядит намного чище, чем полное имя пакета.