[java] 자바의 #ifdef #ifndef

C ++의 #ifdef #ifndef와 같이 Java에서 컴파일 시간 조건을 만드는 방법이 있는지 의심됩니다.

내 문제는 Java로 작성된 알고리즘이 있고 해당 알고리즘에 대해 다른 실행 시간이 향상된다는 것입니다. 따라서 각 개선 사항을 사용할 때 절약되는 시간을 측정하고 싶습니다.

지금은 실행 시간 동안 개선해야 할 것과 그렇지 않은 것을 결정하는 데 사용되는 부울 변수 세트가 있습니다. 그러나 이러한 변수를 테스트하는 것조차 총 실행 시간에 영향을줍니다.

그래서 컴파일 시간 동안 프로그램의 어떤 부분을 컴파일하고 사용해야하는지 결정하는 방법을 찾고 싶습니다.

누군가 Java로 수행하는 방법을 알고 있습니까? 또는 누군가가 그러한 방법이 없다는 것을 알고있을 수도 있습니다 (유용 할 수도 있습니다).



답변

private static final boolean enableFast = false;

// ...
if (enableFast) {
  // This is removed at compile time
}

위에 표시된 것과 같은 조건은 컴파일 타임에 평가됩니다. 대신 이것을 사용한다면

private static final boolean enableFast = "true".equals(System.getProperty("fast"));

그러면 enableFast에 종속 된 모든 조건이 JIT 컴파일러에 의해 평가됩니다. 이에 대한 오버 헤드는 무시할 수 있습니다.


답변

javac는 연결할 수없는 컴파일 된 코드를 출력하지 않습니다. 당신을위한 상수 값에 최종 변수 세트를 사용 #define하고 일반 if에 대한 문 #ifdef.

javap를 사용하여 연결할 수없는 코드가 출력 클래스 파일에 포함되어 있지 않음을 증명할 수 있습니다. 예를 들어, 다음 코드를 고려하십시오.

public class Test
{
   private static final boolean debug = false;

   public static void main(String[] args)
   {
       if (debug)
       {
           System.out.println("debug was enabled");
       }
       else
       {
           System.out.println("debug was not enabled");
       }
   }
}

javap -c Test 두 경로 중 하나만 컴파일되었음을 나타내는 다음 출력을 제공합니다 (그리고 if 문은 컴파일되지 않음).

public static void main(java.lang.String[]);
  Code:
   0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #3; //String debug was not enabled
   5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return


답변

해결책을 찾았다 고 생각합니다. 훨씬 간단합니다.
“최종”수정 자로 부울 변수를 정의하면 Java 컴파일러 자체가 문제를 해결합니다. 이 조건을 테스트 한 결과가 무엇인지 미리 알고 있기 때문입니다. 예를 들어이 코드 :

    boolean flag1 = true;
    boolean flag2 = false;
    int j=0;
    for(int i=0;i<1000000000;i++){
        if(flag1)
            if(flag2)
                j++;
            else
                j++;
        else
            if(flag2)
                j++;
            else
                j++;
    }

내 컴퓨터에서 약 3 초 실행됩니다.
그리고 이것

    final boolean flag1 = true;
    final boolean flag2 = false;
    int j=0;
    for(int i=0;i<1000000000;i++){
        if(flag1)
            if(flag2)
                j++;
            else
                j++;
        else
            if(flag2)
                j++;
            else
                j++;
    }

약 1 초 실행됩니다. 이 코드에 걸리는 시간과 동시에

    int j=0;
    for(int i=0;i<1000000000;i++){
        j++;
    }


답변

사용한 적이 없지만 존재합니다.

JCPP는 C 전 처리기의 완전하고 호환되는 독립형 순수 Java 구현입니다. sablecc, antlr, JLex, CUP 등과 같은 도구를 사용하여 Java로 C 스타일 컴파일러를 작성하는 사람들에게 사용하기위한 것입니다. 이 프로젝트는 GNU C 라이브러리의 소스 코드 대부분을 성공적으로 전처리하는 데 사용되었습니다. 버전 1.2.5부터 Apple Objective C 라이브러리를 전처리 할 수도 있습니다.

http://www.anarres.org/projects/jcpp/


답변

정말 조건부 컴파일이 필요하고 Ant 를 사용하는 경우 코드를 필터링하고 검색 및 바꾸기를 수행 할 수 있습니다.

예 : http://weblogs.java.net/blog/schaefa/archive/2005/01/how_to_do_condi.html

같은 방법으로 당신은, 예를 들어, 교체 필터 쓸 수 LOG.debug(...);와를 /*LOG.debug(...);*/. 이것은 if (LOG.isDebugEnabled()) { ... }동시에 더 간결하다는 것은 말할 것도없고 물건 보다 더 빨리 실행될 것 입니다.

Maven 을 사용하는 경우 여기에 설명 된 유사한 기능이 있습니다 .


답변

Manifold 는 완전히 통합 된 Java 전처리기를 제공합니다 (빌드 단계 또는 생성 된 소스 없음). 조건부 컴파일만을 대상으로하며 C 스타일 지시문을 사용합니다.

매니 폴드의 자바 전 처리기


답변

팩토리 패턴을 사용하여 클래스 구현간에 전환 하시겠습니까?

객체 생성 시간은 이제 문제가 될 수 없습니까? 장기간에 걸쳐 평균을 낼 때 소비 된 시간의 가장 큰 구성 요소는 이제 주 알고리즘에 있어야합니다. 그렇지 않습니까?

엄밀히 말하면, 달성하고자하는 일을 수행하기 위해 전처리 기가 실제로 필요하지는 않습니다. 물론 내가 제안한 것보다 귀하의 요구 사항을 충족시키는 다른 방법이있을 것입니다.