메서드를 정적으로 가져 오기위한 좋은 사용 사례는 무엇입니까?
방금 정적 메소드 가져 오기가 좋지 않다는 리뷰 의견이 있습니다. 정적 가져 오기는 주로 정적 메소드가있는 DA 클래스의 메소드입니다. 따라서 비즈니스 논리의 중간에 현재 클래스에 속하는 것처럼 보이는 da 활동이있었습니다.
import static some.package.DA.*;
class BusinessObject {
void someMethod() {
....
save(this);
}
}
리뷰어는 코드를 바꾸는 데 열중하지 않았지만 그렇게하지는 않았지만 나는 그에게 동의합니다. 정적 가져 오기가 아닌 이유 중 하나는 메소드가 정의 된 위치가 혼란스럽고 현재 클래스가 아니고 수퍼 클래스가 아니기 때문에 정의를 식별하기에는 너무 시간이 오래 걸리기 때문입니다 (웹 기반 검토 시스템에는 클릭 할 수 없음) IDE와 같은 링크 :-) 나는 이것이 중요하다고 생각하지 않습니다. 정적 가져 오기는 여전히 새롭고 곧 우리는 그것들을 찾는 데 익숙해 질 것입니다.
그러나 내가 동의하는 다른 이유는 규정되지 않은 메소드 호출이 현재 객체에 속하는 것으로 보이므로 컨텍스트를 뛰어 넘지 않아야하기 때문입니다. 그러나 그것이 실제로 속해 있다면, 그 슈퍼 클래스를 확장하는 것이 합리적입니다.
그래서, 때 않습니다 그것은 정적 수입 방법에 대한 이해가? 언제 했어요? 정규화되지 않은 전화 모양을 좋아했습니까?
편집 : 대중적인 의견은 아무도 정적 가져 오기 메소드를 현재 클래스의 메소드로 혼동하지 않을 것입니다. 예를 들어 java.lang.Math 및 java.awt.Color의 메소드입니다. 그러나 abs와 getAlpha가 모호하지 않으면 readEmployee가 왜 그런지 알 수 없습니다. 많은 프로그래밍 선택에서와 마찬가지로, 나는 이것 또한 개인적인 선호 사항이라고 생각합니다.
답변 해 주셔서 감사합니다. 질문을 닫습니다.
이 기능을 릴리스했을 때의 Sun 안내서에서 가져온 것입니다 (원본에서 강조 표시).
정적 가져 오기를 언제 사용해야합니까? 매우 드물게! 상수의 로컬 사본을 선언하거나 상속을 남용하려는 유혹이있는 경우에만 사용하십시오 (Constant Interface Antipattern). ... 정적 가져 오기 기능을 과도하게 사용하면 가져 오는 모든 정적 멤버로 네임 스페이스를 오염시켜 프로그램을 읽을 수없고 유지할 수 없게 만들 수 있습니다. 코드를 작성한 후 몇 개월이 지난 후에도 코드 멤버는 정적 멤버의 클래스를 알 수 없습니다. 클래스에서 모든 정적 멤버를 가져 오는 것은 특히 가독성에 해로울 수 있습니다. 하나 또는 두 개의 멤버 만 필요한 경우 개별적으로 가져 오십시오.
( https://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html )
구체적으로 설명하고 싶은 두 부분이 있습니다.
- "상속을 남용하려는"유혹이있을 때만 정적 가져 오기를 사용하십시오 . 이 경우 BusinessObject를 갖고 싶은 유혹을
extend some.package.DA
받았습니까? 그렇다면 정적 가져 오기가이를보다 깔끔하게 처리 할 수 있습니다. 확장을 꿈꿔 본 적이 없다면some.package.DA
정적 가져 오기를 제대로 사용 하지 않는 것일 수 있습니다. 입력 할 때 문자를 몇 개만 저장하는 데 사용하지 마십시오. - 개별 회원을 가져옵니다.
import static some.package.DA.save
대신 말하십시오DA.*
. 이렇게하면이 가져온 방법의 출처를 훨씬 쉽게 찾을 수 있습니다.
개인적으로, 나는이 언어 기능을 사용하지 않은 매우 결코 방법으로 만 상수 또는 열거 거의 항상 거의합니다. 절충은 거의 가치가 없습니다.
정적 가져 오기의 또 다른 합리적인 용도는 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은 이것을 사용하여 문서화 합니다.
Effective Java, Second Edition, at the end of Item 19 notes that you can use static imports if you find yourself heavily using constants from a utility class. I think this principle would apply to static imports of both constants and methods.
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();
}
}
This has advantages and disadvantages. It makes the code a bit more readable at the expense of losing some immediate information about where the method is defined. However, a good IDE will let you go to the definition, so this isn't much of an issue.
You should still use this sparingly, and only if you find yourself using things from the imported file many, many times.
Edit: Updated to be more specific to methods, as that's what this question is referring to. The principle applies regardless of what's being imported (constants or methods).
I agree that they can be problematic from a readability perspective and should be used sparingly. But when using a common static method they can actually increase readability. For example, in a JUnit test class, methods like assertEquals
are obvious where they come from. Similarly for methods from java.lang.Math
.
I use it for Color a lot.
static import java.awt.Color.*;
It is very unlikely that the colors will be confused with something else.
I think static import is really useful to remove redundant class names when using utils classes like Arrays
and Assertions
.
Not sure why but Ross skipped out the last sentence that mentions this in the documentation he is referencing.
Used appropriately, static import can make your program more readable, by removing the boilerplate of repetition of class names.
Basically copied from this blog: https://medium.com/alphadev-thoughts/static-imports-are-great-but-underused-e805ba9b279f
So for example:
Assertions in tests
This is the most obvious case which I think we all agree on
Assertions.assertThat(1).isEqualTo(2);
// Use static import instead
assertThat(1).isEqualTo(2);
Utils classes and enums
The class name can be removed in many cases when using utils classes making the code easier to read
List<Integer> numbers = Arrays.asList(1, 2, 3);
// asList method name is enough information
List<Integer> numbers = asList(1, 2, 3);
java.time package has a few cases where it should be used
// 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));
Example of when not to use
// Ok this is an Optional
Optional.of("hello world");
// I have no idea what this is
of("hello world");
Static imports are the only “new” feature of Java that I have never used and don’t intend to ever use, due to the problems you just mentioned.
I use 'import static java.lang.Math.*' when porting math heavy code from C/C++ to java. The math methods map 1 to 1 and makes diffing the ported code easier without the class name qualification.
I recommend the use of static import when using OpenGL with Java, which is a use-case falling into the "heavy use of constants from a utility class" category
Consider that
import static android.opengl.GLES20.*;
allows you to port original C code and write something readable such as :
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(samplerUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, vtxBuffer);
glVertexAttribPointer(vtxAttrib, 3, GL_FLOAT, false, 0, 0);
instead of that common widespread ugliness :
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);
Talking about unit tests: most people use static imports for the various static methods that mocking frameworks provide, such as when()
or verify()
.
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
And of course, when using the one and only assert you should be using `assertThat() it comes in handy to statically import the required hamcrest matchers, as in:
import static org.hamcrest.Matchers.*;
They're useful to reduce verbiage, particularly in cases where there are a lot of imported methods being called, and the distinction between local and imported methods is clear.
One example: code that involves multiple references to java.lang.Math
Another: An XML builder class where prepending the classname to every reference would hide the structure being built
I think static imports are neat for NLS in the gettext-style.
import static mypackage.TranslatorUtil._;
//...
System.out.println(_("Hello world."));
This both marks the string as a string that has to be extracted and provides an easy and clean way to replace the string with its translation.
IMO static import is quite a nice feature. It is absolutely true that heavy reliance on static import makes the code unreadable and difficult to understand which class a static method or attribute belongs to. However, in my experience it becomes a usable feature especially when designing Util
classes which provide some static methods and attributes. The ambiguity arising whenever providing static import can be circumvented by establishing code standards. In my experience within a company this approach is acceptable and makes the code cleaner and easy to understand. Preferably I insert the _
character in front static methods and static attributes (somehow adopted from C). Apparently this approach violates the naming standards of Java but it provides clarity to code. For example, if we have a AngleUtils class:
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){
}
}
In this case the static import provides clarity and code structure looks more elegant to me:
import static AngleUtils.*;
public class TestClass{
public void testAngles(){
float initialAngle = _ZERO;
float angle1, angle2;
_addAngle(angle1, angle2);
}
}
Right away someone can tell the which method or attribute comes from a static import and it hides the information of the class which it belongs to. I dont suggest using static import for classes that are integral part of a module and provide static and non-static methods as in these case it is important to know which class provides certain static functionality.
I found this to be very convenient when using Utility classes.
For example , instead of using : if(CollectionUtils.isNotEmpty(col))
I can instead :
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
if(isNotEmpty(col))
Which IMO increases code readability when I use this utility multiple times in my code.
You need to use them when:
- you wish to use a
switch
statement with enum values - you wish to make your code difficult to understand
I use them when ever I can. I have IntelliJ setup to remind me if I forget. I think it looks much cleaner than a fully qualified package name.
참고URL : https://stackoverflow.com/questions/420791/what-is-a-good-use-case-for-static-import-of-methods
'Programing' 카테고리의 다른 글
DateTime.ToString (“MM / dd / yyyy HH : mm : ss.fff”)은“09/14/2013 07.20.31.371”과 같은 결과를 가져 왔습니다 (0) | 2020.07.07 |
---|---|
비트 연산자 란 무엇입니까? (0) | 2020.07.07 |
클래스에서 생성자를 비공개로 사용하는 것은 무엇입니까? (0) | 2020.07.07 |
Postgres / SQL에서 두 정수의 최소 / 최대를 얻는 방법은 무엇입니까? (0) | 2020.07.07 |
경고 메시지 :`…`: 유효하지 않은 요인 수준, NA 생성 (0) | 2020.07.07 |