जावा में #ifdef #ifndef


106

मुझे संदेह है कि अगर जावा में संकलित समय की स्थिति बनाने का एक तरीका है जैसे C ++ में #ifdef #ifndef।

मेरी समस्या यह है कि जावा में एक एल्गोरिथ्म लिखा है, और मेरे पास उस एल्गोरिथ्म में अलग-अलग चलने का समय है। इसलिए मैं मापना चाहता हूं कि प्रत्येक सुधार का उपयोग करने पर मैं कितना समय बचा सकता हूं।

अभी मेरे पास बूलियन वेरिएबल्स का एक सेट है जिसका उपयोग रनिंग टाइम के दौरान तय करने के लिए किया जाता है कि कौन सा सुधार किया जाना चाहिए और कौन सा नहीं। लेकिन यहां तक ​​कि उन चर का परीक्षण करने से कुल चलने का समय प्रभावित होता है।

इसलिए मैं संकलन समय के दौरान निर्णय लेने का एक तरीका खोजना चाहता हूं कि कार्यक्रम के किन हिस्सों को संकलित किया जाए और उनका उपयोग किया जाए।

क्या कोई इसे जावा में करने का तरीका जानता है। या शायद कोई जानता है कि ऐसा कोई तरीका नहीं है (यह भी उपयोगी होगा)।

जवाबों:


126
private static final boolean enableFast = false;

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

उपर्युक्त की तरह सशर्त संकलन समय पर मूल्यांकन किया जाता है। अगर इसके बजाय आप इसका इस्तेमाल करते हैं

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

फिर सक्षम पर निर्भर किसी भी स्थिति का मूल्यांकन जेआईटी कंपाइलर द्वारा किया जाएगा। इसके लिए ओवरहेड नगण्य है।


यह समाधान तो बेहतर है मेरा। जब मैंने एक निर्धारित बाहरी मान के साथ चर को शुरू करने की कोशिश की तो चलने का समय 3 सेकंड तक चला गया। लेकिन जब मैंने चर को स्थिर वर्ग चर के रूप में परिभाषित किया (और एक फ़ंक्शन स्थानीय चर नहीं) तो चल रहा समय 1 सेकंड में लौट आया। सहायता के लिए धन्यवाद।
jutky

6
IIRC, जावा के JIT कंपाइलर से पहले भी यह काम कर चुका है। javacमुझे लगता है कि कोड हटा दिया गया था । यह केवल तभी काम करता है जब अभिव्यक्ति (कहना) enableFastएक संकलित समय स्थिर अभिव्यक्ति थी।
स्टीफन सी

2
हां, लेकिन यह सशर्त एक विधि के भीतर रहना चाहिए, सही? उस मामले के बारे में जहां हमारे पास निजी स्थिर अंतिम स्ट्रिंग्स का एक गुच्छा है जिसे हम सेट करना चाहते हैं। (उदाहरण के लिए सर्वर URL का एक सेट जो उत्पादन बनाम स्टेजिंग के लिए अलग-अलग सेट किया गया है)
tomwhipple

3
@tomwhipple: सच है, इसके अलावा यह आपको कुछ करने की अनुमति नहीं देता है: private void foo(#ifdef DEBUG DebugClass obj #else ReleaseClass obj #endif )
Zonko

3
आयात के बारे में क्या है (उदाहरण के लिए, वर्गपथ के संबंध में)?
n611x007

44

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 निम्न आउटपुट देता है, यह दर्शाता है कि दो में से केवल एक पथ संकलित किया गया था (और यदि कथन नहीं था):

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

2
क्या यह जेवैक विशिष्ट है, या यह व्यवहार वास्तव में जेएलएस द्वारा गारंटीकृत है?
पचेरियर

@ स्पेसर, मुझे नहीं पता कि क्या यह जेएलएस द्वारा गारंटी दी गई है, लेकिन यह 90 के दशक के बाद से भर में आए हर जावा कंपाइलर के लिए सच है, 1.1.7 से पहले के संभावित अपवाद के साथ, और केवल इसलिए कि मैंने नहीं किया था इसे तब परखें।

12

मुझे लगता है कि मैंने इसका हल ढूंढ लिया है, यह बहुत सरल है।
यदि मैं "अंतिम" संशोधक के साथ बूलियन चर को परिभाषित करता हूं तो जावा कंपाइलर समस्या का हल करता है। क्योंकि यह पहले से पता है कि इस स्थिति का परीक्षण करने का परिणाम क्या होगा। उदाहरण के लिए यह कोड:

    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++;
    }

1
यह दिलचस्प है। ऐसा लगता है कि जेआईटी पहले से ही सशर्त संकलन का समर्थन करता है! क्या यह काम करता है अगर वे फाइनल दूसरे वर्ग या किसी अन्य पैकेज में हैं?
joeytwiddle

महान! फिर मेरा मानना ​​है कि यह एक रनटाइम ऑप्टिमाइज़ेशन होना चाहिए, कोड वास्तव में संकलन-समय पर नहीं छीना जा रहा है। जब तक आप एक परिपक्व वीएम का उपयोग करते हैं, तब तक यह ठीक है।
joeytwiddle

@joeytwiddle, कीवर्ड "जब तक आप उपयोग करते हैं" एक परिपक्व वीएम है।
पचेरियर

2

कभी इसका इस्तेमाल नहीं किया, लेकिन यह मौजूद है

जेसीपीपी एक पूर्ण, आज्ञाकारी, स्टैंडअलोन, सी प्रीप्रोसेसर का शुद्ध जावा कार्यान्वयन है। यह जावा में सी-स्टाइल कंपाइलर लिखने वाले लोगों के लिए उपयोग करने का इरादा है, जैसे कि sablecc, antlr, JLex, CUP और इसके बाद के टूल। इस परियोजना का उपयोग GNU C लाइब्रेरी के स्रोत कोड के बहुत पूर्वप्रयोग के लिए किया गया है। संस्करण 1.2.5 के रूप में, यह Apple ऑब्जेक्टिव सी लाइब्रेरी को भी प्रीप्रोसेस कर सकता है।

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


1
मुझे यकीन नहीं है कि यह मेरी ज़रूरत के अनुरूप है। मेरा कोड जावा में लिखा है। हो सकता है कि आप मुझे उनके स्रोतों को प्राप्त करने और मेरे कोड को प्रीप्रोसेस करने के लिए उपयोग करने का प्रस्ताव दे रहे हों?
21

2

यदि आपको वास्तव में सशर्त संकलन की आवश्यकता है और आप चींटी का उपयोग करते हैं , तो आप अपने कोड को फ़िल्टर करने और उसमें एक खोज-और-जगह करने में सक्षम हो सकते हैं।

उदाहरण के लिए: http://weblogs.java.net/blog/schaefa/archive/2005/01/how_to_do_condi.html

इसी तरह आप, उदाहरण के लिए, को बदलने के लिए एक फिल्टर लिख सकते हैं LOG.debug(...);के साथ /*LOG.debug(...);*/। यह अभी भी if (LOG.isDebugEnabled()) { ... }सामान की तुलना में तेजी से निष्पादित करेगा , एक ही समय में अधिक संक्षिप्त होने का उल्लेख नहीं करने के लिए।

यदि आप मावेन का उपयोग करते हैं , तो यहां वर्णित एक समान विशेषता है


2

मैनिफोल्ड एक पूरी तरह से एकीकृत जावा प्रीप्रोसेसर (कोई निर्माण चरण या उत्पन्न स्रोत नहीं) प्रदान करता है। यह विशेष रूप से सशर्त संकलन को लक्षित करता है और सी-शैली के निर्देशों का उपयोग करता है।

मैनिफोल्ड के जावा प्रीप्रोसेसर


1

किसी वर्ग के कार्यान्वयन के बीच स्विच करने के लिए फ़ैक्टरी पैटर्न का उपयोग करें?

ऑब्जेक्ट निर्माण समय अब ​​एक चिंता का विषय नहीं हो सकता है? जब एक लंबी चलने वाली समय अवधि में औसतन, समय का सबसे बड़ा घटक मुख्य एल्गोरिथ्म में होना चाहिए, तो क्या यह नहीं होगा?

कड़ाई से बोलते हुए, आपको वास्तव में एक प्रीप्रोसेसर की आवश्यकता नहीं है जो आप प्राप्त करना चाहते हैं। मेरे द्वारा निश्चित रूप से प्रस्तावित की तुलना में आपकी आवश्यकता को पूरा करने के अन्य तरीके हैं।


बदलाव बहुत मामूली हैं। पुनर्मूल्यांकन के बजाय अनुरोध किए गए परिणाम को पहले से जानने के लिए कुछ शर्तों का परीक्षण करना। इसलिए फ़ंक्शन को कॉल का ओवरहेड मेरे लिए उपयुक्त नहीं हो सकता है।
जूटकी

0
final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.