programing

메서드를 스태틱으로 선언함으로써 얻을 수 있는 이점은 무엇입니까?

minecode 2022. 10. 1. 14:09
반응형

메서드를 스태틱으로 선언함으로써 얻을 수 있는 이점은 무엇입니까?

최근에 이클립스의 경고를 훑어봤더니 이런 걸 발견했어요

정적 경고

메서드를 스태틱으로 선언할 수 있는 경우 컴파일러에 경고가 표시됩니다.

[edit] Eclipse 도움말에 포함된 정확한 인용문, 비공개 및 최종 인용문:

활성화 시 컴파일러는 개인 메서드 또는 최종 메서드 중 정적 멤버만을 참조하는 메서드에 대해 오류 또는 경고를 발행합니다.

네, 끌 수 있는 건 아는데 왜 켜는지 이유를 알고 싶어요.

가능한 모든 방법을 정적이라고 선언하는 것이 좋은 이유는 무엇입니까?

퍼포먼스상의 메리트가 있습니까?(모바일 도메인 내)

메서드를 스태틱으로 지적하면 인스턴스 변수를 사용하지 않으므로 utils 스타일 클래스로 이동할 수 있습니다.

결국 이 '무시'를 꺼야 할까요?아니면 100개 이상의 경고를 수정해야 할까요?

컴파일러가 이러한 메서드를 삽입할 뿐이므로, 이것이 코드를 더럽히는 추가 키워드라고 생각하십니까?(마지막으로 할 수 있는 모든 변수를 선언하는 것은 아니지만 할 수 있는 과 같습니다.

메서드를 작성할 때마다 주어진 범위 내에서 계약을 이행합니다.범위가 좁을수록 버그를 쓸 가능성은 적어집니다.

방식이 정적인 경우 비 정적인 멤버에 액세스할 수 없기 때문에 범위가 좁아집니다.계약을 이행하기 위해 (서브클래스에서도) 비정적 멤버가 필요없고 앞으로도 필요 없을 경우 이러한 필드에 대한 접근권을 메서드에 부여해야 합니다.메서드 선언static이 경우 컴파일러는 사용자가 사용하지 않는 멤버를 사용하지 않는지 확인합니다.

게다가, 그것은 당신의 코드를 읽는 사람들이 계약의 성격을 이해하는 데 도움이 될 것입니다.

에 어떤 생각됩니다.static실제로 정적 계약을 이행할 때 사용합니다.

경우에 따라서는 메서드가 클래스의 인스턴스와 관련된 의미만 가질 수 있으며 실제로 구현에서 비정적 필드 또는 인스턴스가 사용되지 않을 수 있습니다.그 하지 않습니다.static.

를 사용하지 않는 장소의 예static키워드:

  • 아무것도 하지 않는 확장 후크(단, 서브클래스의 인스턴스 데이터로 작업을 수행할 수 있음)
  • 서브클래스에서 커스터마이즈 가능한 매우 단순한 디폴트 동작입니다.
  • 이벤트 핸들러 구현: 구현은 이벤트핸들러 클래스에 따라 다르지만 이벤트핸들러 인스턴스의 속성은 사용하지 않습니다.

여기에는 최적화에 대한 개념이 없습니다.

A static방법은static왜냐하면 이 메서드는 필요하지 않다고 해서 폐쇄 클래스의 어떤 인스턴스에도 의존하지 않는다고 명시적으로 선언하기 때문입니다.따라서 문서에 명시된 이클립스 경고:

활성화 시 컴파일러는 개인 메서드 또는 최종 메서드 중 정적 멤버만을 참조하는 메서드에 대해 오류 또는 경고를 발행합니다.

인스턴스 변수가 필요 없고 메서드가 개인(외부에서 호출할 수 없음) 또는 최종(덮어쓸 수 없음)인 경우 정적 메서드가 아닌 일반 메서드로 둘 필요가 없습니다.스태틱 메서드는 기본적으로 더 적은 작업을 수행할 수 있기 때문에 더 안전합니다(인스턴스도 필요 없고 암묵적인 것도 없습니다).this오브젝트)

퍼포먼스에 대한 정보는 없습니다만, 타입에 따라서는 코드가 동적 디스패치를 실행할 필요가 없기 때문에, 기껏해야 조금 낫다고 생각합니다.

그러나 스태틱 방식으로 리팩터링하는 것을 반대하는 더 강력한 주장은 현재 스태틱을 사용하는 것이 잘못된 관행으로 간주된다는 것입니다.정적 메서드/변수는 객체 지향 언어에 잘 통합되지 않으며 적절하게 테스트하기도 어렵습니다.이것이 일부 새로운 언어들이 정적 메서드/변수의 개념을 완전히 배제하거나 OO와 더 잘 어울리는 방식으로 언어에 내장하려고 하는 이유입니다(예: Scala의 객체).

대부분의 경우 파라미터만을 입력으로 사용하여 출력을 생성하는 함수(유틸리티/헬퍼 함수 등)를 구현하기 위해 정적 메서드가 필요합니다.현대 언어에는 이를 가능하게 하는 퍼스트 클래스 함수 개념이 있기 때문에 정적 기능은 필요하지 않습니다.Java 8은 람다 식을 통합하기 때문에 이미 이 방향으로 진행 중입니다.

(1) 신고방법static는 약간의 퍼포먼스상의 이점을 얻을 수 있지만, 보다 편리한 것은 오브젝트인스턴스를 수중에 두지 않고 사용할 수 있다는 점입니다(공장에서의 방법이나 싱글톤 취득 등).또한 방법의 특성을 설명하는 문서 목적도 제공합니다.이 문서적인 목적은 무시되어서는 안 됩니다.이것은, 코드의 독자와 API의 유저에게 메서드의 성질에 관한 힌트를 주는 동시에, 오리지날 프로그래머의 사고 툴로서도 기능합니다.- 의도한 의미를 명확하게 하는 것은, 올바른 사고와 보다 좋은 품질의 코드를 만드는 데 도움이 됩니다(m에 근거하고 있다고 생각합니다).y개인경험은다르지만사람은다릅니다).예를 들어, 어떤 타입으로 동작하는 메서드와 그 타입의 인스턴스에서 동작하는 메서드를 구별하는 것이 논리적이고 바람직합니다(Jon Sket이 C# 질문에 대한 코멘트에서 지적한 와 같습니다).

사용 과 같습니다.static메서드는 절차 프로그래밍 인터페이스를 모방하는 것입니다.클래스와 그 방법 및 속성을 생각해 보십시오.학급.java.lang.System는 인스턴스화 가능한 객체가 아니라 그룹 이름 공간처럼 사용됩니다.

2. Eclipse(또는 다른 프로그래밍된 또는 다른 종류의 생물 적합성 또는 비생물 적합성) 엔티티)는 어떤 방법이 정적이라고 선언될 수 있는지 어떻게 확실히 알 수 있습니까?기본 클래스가 인스턴스 변수에 액세스하지 않거나 비정적 메서드를 호출하지 않더라도 상속 메커니즘에 의해 상황이 변경될 수 있습니다.서브클래스를 상속하여 메서드를 재정의할 수 없는 경우에만 메서드를 실제로 선언할 수 있음을 100% 확실하게 주장할 수 있습니다.static. 이 두 수

  1. private할 수 알 수 (서브클래스는 그것을 있지 않습니다)
  2. final(서브 클래스에서 액세스할 수 있는 경우에도 인스턴스 데이터 또는 함수를 참조하도록 메서드를 변경할 수 없습니다).

따라서 이클립스 옵션의 논리입니다.

3. 원본 포스터에도 "메서드를 스태틱으로 지정하는 것은 인스턴스 변수를 사용하지 않기 때문에 utils 스타일 클래스로 이동할 수 있음을 보여주는같습니다."라고 적혀 있습니다.아주 좋은 지적입니다.이러한 설계 변경이 경고로 나타날 수 있습니다.

이클립스를 사용하거나 자바에서 프로그래밍을 할 경우, 개인적으로 활성화하고 싶은 매우 편리한 옵션입니다.

메서드의 범위가 어떻게 변경되는지에 대한 Samuel의 답변을 참조하십시오.이것이 방법을 정적으로 만드는 주요 측면이라고 생각합니다.

퍼포먼스에 대해서도 질문했습니다.

스태틱 메서드에 대한 호출에는 암묵적인 "this" 참조가 파라미터로 필요하지 않기 때문에 약간의 퍼포먼스가 향상될 수 있습니다.

그러나 이 퍼포먼스에 미치는 영향은 매우 작습니다.따라서 모든 것은 범위와 관련이 있습니다.

Android 성능 가이드라인:

가상보다 정적 선호 객체의 필드에 액세스할 필요가 없는 경우 메서드를 정적으로 설정하십시오.호출이 약 15%~20% 빨라집니다.메서드 시그니처를 통해 메서드를 호출해도 오브젝트의 상태를 변경할 수 없기 때문에 이 방법도 좋은 방법입니다.

http://developer.android.com/training/articles/perf-tips.html#PreferStatic

Eclipse 문서에는 문제의 경고에 대해 나와 있습니다.

메서드는 정적일 수 있습니다.

활성화 시 컴파일러는 개인 메서드 또는 최종 메서드 중 정적 멤버만을 참조하는 메서드에 대해 오류 또는 경고를 발행합니다.

거의 모든 걸 말해주는 것 같아이 메서드가 프라이빗하고 최종적인 것으로, 스태틱멤버만을 참조하는 경우, 문제의 메서드는 스태틱으로 선언되어 스태틱콘텐츠에만 액세스 할 생각임을 명확히 합니다.

나는 솔직히 그 이면에 다른 불가사의한 이유가 있다고 생각하지 않는다.

속도 차이에 대한 몇 가지 숫자를 놓쳤어요.그래서 벤치마크를 해봤지만 쉽지 않았다: 자바 루프는 몇 번의 실행 후에 느려진다/JIT의 장애?

최종적으로 Caliper를 사용했는데 결과는 손으로 테스트를 실행한 것과 같습니다.

스태틱 콜과 다이내믹콜은 측정 가능한 차이가 없습니다.적어도 Linux/AMD64/Java7에서는 제외됩니다.

캘리퍼 결과는 다음과 같습니다.https://microbenchmarks.appspot.com/runs/1426eac9-36ca-48f0-980f-0106af064e8f#r:scenario.benchmarkSpec.methodName,scenario.vmSpec.options.CMSLargeCoalSurplusPercent,scenario.vmSpec.options.CMSLargeSplitSurplusPercent,scenario.vmSpec.options.CMSSmallCoalSurplusPercent,scenario.vmSpec.options.CMSSmallSplitSurplusPercent,scenario.vmSpec.options.FLSLargestBlockCoalesceProximity,scenario.vmSpec.options.G1ConcMarkStepDurationMillis

제 결과는 다음과 같습니다.

Static: 352 ms
Dynamic: 353 ms
Static: 348 ms
Dynamic: 349 ms
Static: 349 ms
Dynamic: 348 ms
Static: 349 ms
Dynamic: 344 ms

캘리퍼 테스트 클래스는 다음과 같습니다.

public class TestPerfomanceOfStaticMethodsCaliper extends Benchmark {

    public static void main( String [] args ){

        CaliperMain.main( TestPerfomanceOfStaticMethodsCaliper.class, args );
    }

    public int timeAddDynamic( long reps ){
        int r=0;
        for( int i = 0; i < reps; i++ ) {
            r |= addDynamic( 1, i );
        }
        return r;
    }

    public int timeAddStatic( long reps ){
        int r=0;
        for( int i = 0; i < reps; i++ ) {
            r |= addStatic( 1, i );
        }
        return r;
    }

    public int addDynamic( int a, int b ){

        return a+b;
    }

    private static int addStatic( int a, int b ){

        return a+b;
    }

}

그리고 내 시험 수업은 다음과 같았다.

public class TestPerformanceOfStaticVsDynamicCalls {

    private static final int RUNS = 1_000_000_000;

    public static void main( String [] args ) throws Exception{

        new TestPerformanceOfStaticVsDynamicCalls().run();
    }

    private void run(){

        int r=0;
        long start, end;

        for( int loop = 0; loop<10; loop++ ){

            // Benchmark

            start = System.currentTimeMillis();
            for( int i = 0; i < RUNS; i++ ) {
                r += addStatic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Static: " + ( end - start ) + " ms" );

            start = System.currentTimeMillis();
            for( int i = 0; i < RUNS; i++ ) {
                r += addDynamic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Dynamic: " + ( end - start ) + " ms" );

            // Do something with r to keep compiler happy
            System.out.println( r );

        }

    }

    private int addDynamic( int a, int b ){

        return a+b;
    }

    private static int addStatic( int a, int b ){

        return a+b;
    }

}

스태틱으로 선언할 수 있는 메서드는 인스턴스화가 필요하지 않은 메서드입니다.

public class MyClass
{
    public static string InvertText(string text)
    {
        return text.Invert();
    }
}

그러면 해당 클래스를 설치하지 않고 다른 클래스로 호출할 수 있습니다.

public class MyClassTwo
{
    public void DoSomething()
    {
        var text = "hello world";
        Console.Write(MyClass.InvertText(text));
    }
}

하지만 그건 이미 알고 계실 겁니다이 방법에는 인스턴스 변수가 사용되지 않는다는 점을 명확히 하는 것 외에 그 자체로는 실질적인 이점을 얻을 수 없습니다.

즉, 가장 안전하게 전원을 완전히 끌 수 있습니다.다른 클래스에서 메서드를 사용하지 않는 경우(이 경우 비공개여야 함)에는 스태틱할 필요가 전혀 없습니다.

언급URL : https://stackoverflow.com/questions/11240178/what-is-the-gain-from-declaring-a-method-as-static

반응형