Private Helper 메서드가 정적일 수 있는 경우 정적이어야 함
인스턴스화되도록 설계된 클래스가 있다고 가정해 보겠습니다.클래스 내에는 클래스 멤버 중 누구에게도 액세스 할 필요가 없는 프라이빗한 「헬퍼」메서드가 몇개 있어, 그 멤버의 인수만으로 조작해 결과를 반환합니다.
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
" " " " " " " 를 지정해야 하는 ?computeOne
★★★★★★★★★★★★★★★★★」computeMore
적인인방?방 법?? 니면 특특 ?유 유? ???
문제를 일으키지 않고 정적인 상태로 두는 것이 확실히 가장 간단합니다.
는 그런 합니다.private static
;는 오브젝트 상태를 변경하지 않는다는 것을 독자에게 명확히 합니다.IDE에서는 스태틱메서드에 대한 콜도 이탤릭체로 표시되므로 시그니처를 찾지 않아도 스태틱메서드를 알 수 있습니다.
는 ""에 할 수 수 .this
속도에는 차이가 없다고 생각합니다(만약 있다면 전체적으로는 차이가 나기에는 너무 작을 수 있습니다).
가능하면 정전기 상태로 만들 수 있습니다.하지만 그건 그저 저입니다.
편집: 이 답변은 바이트 코드 크기에 대한 확인되지 않은 어설션 때문에 계속 다운 투표됩니다.그래서 실제로 테스트를 해보겠습니다.
class TestBytecodeSize {
private void doSomething(int arg) { }
private static void doSomethingStatic(int arg) { }
public static void main(String[] args) {
// do it twice both ways
doSomethingStatic(0);
doSomethingStatic(0);
TestBytecodeSize t = new TestBytecodeSize();
t.doSomething(0);
t.doSomething(0);
}
}
코드(「」로 )javap -c -private TestBytecodeSize
Compiled from "TestBytecodeSize.java"
class TestBytecodeSize extends java.lang.Object{
TestBytecodeSize();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
private void doSomething(int);
Code:
0: return
private static void doSomethingStatic(int);
Code:
0: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: invokestatic #2; //Method doSomethingStatic:(I)V
4: iconst_0
5: invokestatic #2; //Method doSomethingStatic:(I)V
8: new #3; //class TestBytecodeSize
11: dup
12: invokespecial #4; //Method "<init>":()V
15: astore_1
16: aload_1
17: iconst_0
18: invokespecial #5; //Method doSomething:(I)V
21: aload_1
22: iconst_0
23: invokespecial #5; //Method doSomething:(I)V
26: return
}
tops)바바 2 바바바바바바바바 2 tops)bybybybybyby topstopstopstops :iconst_0
) 및 (인수의 경우)invokestatic
.
하려면 non-static method(비정적)의 3가지 방법이 합니다.aload_1
)TestBytecodeSize
내iconst_0
) 및 (인수의 경우)invokespecial
이 사적인은 (인 방법들이 아니었다면)이 되었을 invokevirtual
invokespecial
; 「JLS © 7 . 7 Booting Methods 」를 참조해 주세요).
invokestatic
1번으로 하다 invokestatic
★★★★★★★★★★★★★★★★★」invokespecial
다 보다 한다invokevirtual
둘 다 동적 바인딩 대신 정적 바인딩을 사용하기 때문에 어느 쪽도 다른 쪽보다 빠른지 알 수 없습니다.저도 좋은 참고 자료를 찾을 수가 없어요.가장 가까운 것은 1997년 Java World 기사입니다.이 기사는 기본적으로 제가 방금 말한 내용을 다시 기술한 것입니다.
는 " " " " 입니다.
invokespecial
★★★★★★★★★★★★★★★★★」invokestatic
이러한 명령에 의해 호출되는 메서드는 정적으로 바인드되기 때문입니다.JVM이 이러한 명령의 심볼 참조를 해결하고 직접 참조로 대체하면 해당 직접 참조에는 실제 바이트 코드에 대한 포인터가 포함될 수 있습니다.
하지만 1997년 이후로 많은 것들이 바뀌었다.
그래서 결론적으로...나는 내가 전에 말했던 것을 여전히 고수하고 있는 것 같아.속도는 기껏해야 미세 최적화일 것이기 때문에 둘 중 하나를 선택하는 이유가 되어서는 안 됩니다.
제 개인적인 선호는 그들이 상태 비저장임을 분명히 보여주는 것이기 때문에 정적인 것으로 선언하는 것입니다.
정답은...사정에 따라 다르겠지.
member가 취급하는 오브젝트에 고유한 인스턴스 변수인 경우, 왜 그것을 파라미터로 전달합니까?
예:
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne();
total += computeMore();
return total;
}
private double computeOne() { /* Process member here */ }
private double computeMore() { /* Process member here */ }
}
중 컨스트럭터 "before" 스태틱도우미 "before"에서가 있는 입니다.this
★★★★★★★★★★★★★★★★★」super
§:
public class MyClass extends SomeOtherClass {
public MyClass(String arg) {
super(recoverInt(arg));
}
private static int recoverInt(String arg) {
return Integer.parseInt(arg.substring(arg.length() - 1));
}
}
알 수 있다.recoverInt
이 경우 인스턴스 메서드가 될 수 없습니다.
프라이빗 스태틱 방식의 확실한 장점은 생각나지 않습니다.그렇다고 해서, 그것들을 비정전성으로 하는 것도 특별한 이점은 없습니다.이것은 주로 프레젠테이션의 문제입니다.물건을 변경하지 않는다는 사실을 명확하게 강조하기 위해 정적으로 만들 필요가 있습니다.
액세스 권한이 다른 메서드의 경우 다음 두 가지 주요 인수가 있다고 생각합니다.
- static 메서드는 오브젝트의 인스턴스를 생성하지 않고 호출할 수 있으며, 이는 유용할 수 있습니다.
- 정적 메서드는 상속할 수 없습니다.다형성이 필요한 경우 문제가 될 수 있습니다(단, 개인 메서드와는 무관합니다).
게다가 그 차이는 매우 작기 때문에, 이 포인터가 instance method에 건네진 여분의 포인터가 큰 차이를 가져오는 것은 아닌지 매우 의심스럽다.
정답은 다음과 같습니다.
필드에서 정보를 가져오지 않고 필드에 정보를 입력하지 않는 메서드는 인스턴스 메서드일 필요가 없습니다.클래스 또는 객체의 필드를 사용하지 않거나 변경하지 않는 메서드는 정적 메서드가 될 수 있습니다.
또는 [정적]으로 간주하지 않을 특별한 이유가 있습니까?
네.
인스턴스 방식으로 유지하면 나중에 다른 구현을 제공할 수 있습니다.
바보같이 들릴 수도 있지만(그리고 실제로 이러한 메서드가 50줄짜리 프로그램에서 사용자만 사용하는 경우), 더 큰 응용 프로그램이나 다른 사용자가 사용하는 라이브러리에서 더 나은 구현을 선택할 수도 있지만 기존 코드를 깨고 싶지 않습니다.
서브클래스를 생성하여 새 버전에서 반환하고 메서드가 인스턴스 메서드로 선언되었으므로 다형성이 기능하도록 합니다.
또한 동일한 이유로 컨스트럭터를 비공개로 하고 정적 공장 방법을 제공하는 것이 좋습니다.
따라서 인스턴스 방식으로 유지하고 가능하면 스태틱하지 않도록 하는 것이 좋습니다.
언어가 제공하는 역동성을 활용하십시오.
관련 비디오에 대해서는, 여기를 참조해 주세요. 좋은 API를 설계하는 방법과 그 중요성
스태틱 vs 인스턴스(static vs instance) 메서드 논의와는 직접 관련이 없지만 API 설계에서 몇 가지 흥미로운 점에 대해 설명합니다.
메서드가 기본적으로 상태 정보를 예측 불가능하게 사용하는 서브루틴일 경우 스태틱하다고 선언합니다.
이를 통해 다른 정적 메서드 또는 클래스 초기화에서 사용할 수 있습니다.
public class Example {
//...
//Only possible if computeOne is static
public final static double COMPUTED_ONE = computeOne(new Something("1"));
//...
}
스태틱 메서드를 사용하는 경우의 한 가지 문제는 유닛 테스트에서 오브젝트를 사용하기 어려워질 수 있다는 것입니다.Mockito는 정적 메서드에 대한 mock을 만들 수 없으며 메서드의 하위 클래스 구현을 만들 수 없습니다.
정적/비정적 질문은 "이 클래스의 개체를 정말로 사용해야 합니까?"로 귀결됩니다.
그럼, 당신은 다른 방법들 사이에 물체를 전달하고 있는 건가요?오브젝트에는 스태틱메서드 이외의 유용한 정보가 포함되어 있습니까?양쪽 방법을 모두 사용할 경우 양쪽 방법을 정의하지 않을 이유가 있습니까?
이 딜레마에 빠지면 메서드에 필요한 모든 데이터가 오브젝트 외부에 있는 코드에 있는 것 같습니다.이게 네가 원하는 거야?매번 그 데이터를 하나의 객체로 수집하는 것이 더 쉬울까요?당신은 단지 단일 모델에 전념하는 것에 대해 양면적일 수 있다.단방향으로 모든 작업을 수행할 수 있는 경우 정적 또는 비정적 중 하나를 선택하여 선택합니다.
이런 경우에 제가 선호하는 것은computeOne
★★★★★★★★★★★★★★★★★」computeMore
캡슐화.이유는 캡슐화입니다.클래스의 실장에 액세스 할 수 있는 코드가 적을수록 좋습니다.
에서는 '어느 정도', '어느 정도', '어느 정도'라고 있습니다.computeOne
★★★★★★★★★★★★★★★★★」computeMore
수업의 내부 정보에 접근할 필요가 없는데 왜 수업의 관리자들이 내부 정보에 개입할 기회를 주나요?
다른 포스터가 잘못된 정보를 제공한다고 말한 것을 몇 가지 명확히 하고 싶습니다.
우선, 이 메서드는 프라이빗하기 때문에, 스태틱하다고 선언해도, 이 클래스 이외에서는 액세스 할 수 없습니다.둘째, 이들은 비공개이기 때문에 서브클래스로 덮어쓸 수도 없기 때문에 스태틱 또는 비 스태틱은 아무런 차이가 없습니다.셋째, 비정적 개인 메서드는 클래스의 컨스트럭터로부터 호출할 수 있습니다.또, 정적일 필요는 없습니다.
Private Helper 메서드를 스태틱 또는 비 스태틱으로 정의할 것인지 질문합니다.Private Method static 마킹은 이 메서드가 상태 비저장임을 나타내므로 Steve의 답변으로 하겠습니다.코드할 때도 이 규칙을 따릅니다.
경험에 비추어 볼 때, 나는 그러한 사적인 방법들이 꽤 보편적이고 재사용 가능한 경향이 있다고 말하고 싶다.
저는 이 방법이 현재 수업의 문맥을 벗어나 유용하게 쓰일 수 있는지 질문하는 것이 가장 먼저라고 생각합니다.만약 그렇다면, 저는 Everyone이 제안하는 대로 이 메서드를 스태틱하게 추출하고, 새로운 메서드를 실장하기 전에 누군가가 체크할 수 있는 유틸리티 클래스로 이 메서드를 스태틱하게 추출합니다.
이러한 일반적인 개인 사용 방식은 각 개발자가 사용해야 하는 장소에서 독립적으로 재창조하기 때문에 프로젝트에서 코드 복제의 큰 부분을 차지합니다.따라서 이러한 방법을 중앙 집중화하는 것이 바람직한 방법입니다.
구체적으로 말하면, 이러한 메서드를 정의하는 목적은 기능성(프라이빗으로 정의됨)보다는 코드를 명확하게 하기 위한 것입니다.이 경우 static을 사용하는 것은 클래스 기능을 공개하는 것이 목적이므로 실제로는 static을 사용하는 것은 도움이 되지 않습니다.
1가지 이유는 다른 모든 것이 동일하기 때문에 스태틱메서드 콜이 고속화되기 때문입니다.정적 메서드는 가상일 수 없으며 암묵적으로 이 참조를 사용하지 마십시오.
많은 분들이 말씀하신 것처럼 정전기처럼 해주세요!내가 따르는 엄지의 법칙은 다음과 같다: 만약 당신이 그 메서드가 단지 수학 함수라고 생각한다면, 즉, 그것은 스테이트리스이며, 어떤 인스턴스 변수도 포함하지 않는다(=> 메서드에 파란색 색상 변수도 포함되지 않는다), 그리고 그 메서드의 결과는 n개의 콜 수(물론 같은 파라미터로)에 대해 동일하다)에 대해 그 메서드를 스태틱으로 표시한다.
이 메서드가 다른 클래스에 도움이 된다고 생각되면 Util 클래스로 이동합니다.그렇지 않으면 메서드를 같은 클래스에 private로 배치합니다.(접근성 향상)
오프토픽: 도우미 메서드는 정적 메서드만 포함된 스탠드아론 유틸리티/헬퍼 클래스로 유지합니다.
사용 시점에서 도우미 메서드('same class'로 읽음)를 사용하는 경우의 문제점은 관련성이 없는 자신의 도우미 메서드를 같은 장소에 게시하는 것을 선택할 수 있다는 것입니다.
class Whatever {
public static varType myVar = initializeClassVariable();
private static varType initializeClassVariable() {
//initialization code goes here
}
}
프라이빗 스태틱메서드의 장점은 클래스 변수를 재초기화할 필요가 있는 경우 나중에 재사용할 수 있다는 것입니다.
정적 수식자가 없으면 메서드를 (다시) 쓸 때 쉽게 수행할 수 있는 추가 분석 없이 메서드가 스테이트리스임을 알 수 없습니다.
그러면 "정적" 수식어는 다른 사람들이 유용하지 않다고 생각할 수 있는 것 외에 리팩터링에 대한 아이디어를 줄 수 있습니다.예를 들어 메서드를 유틸리티 클래스로 이동하거나 멤버 메서드로 변환합니다.
상태 비저장으로 표시하기 위해 정적임을 선언합니다.
Java는 내보내지 않는 사소한 작업에 대해 더 나은 메커니즘을 가지고 있지 않기 때문에 프라이빗 스태틱은 허용할 수 있다고 생각합니다.
언급URL : https://stackoverflow.com/questions/538870/should-private-helper-methods-be-static-if-they-can-be-static
'IT이야기' 카테고리의 다른 글
GCC 치명적 오류: stdio.h: 해당 파일 또는 디렉토리가 없습니다. (0) | 2022.05.31 |
---|---|
구성 요소가 렌더링하기 전에 vuex에 저장소를 채우는 방법 (0) | 2022.05.30 |
Larabel 5 VueJ가 작동하지 않음 (0) | 2022.05.30 |
VueJ에 JSON Imports (0) | 2022.05.30 |
Java에서 "transient"라는 키워드는 무엇을 의미합니까? (0) | 2022.05.30 |