2008-09-16 18 views
10

मैं जावा स्विंग एप्लिकेशन को बनाए रखता हूं।जावा संकलन - क्या मेरे कोड के हिस्सों को अनदेखा करने के लिए संकलक को बताने का कोई तरीका है?

जावा 5 (ऐप्पल मशीनों के लिए) के साथ पिछड़ा संगतता के लिए, हम दो कोडबेस बनाए रखते हैं, 1 जावा 6 की सुविधाओं का उपयोग करते हुए, अन्य सुविधाओं के बिना।

यह कोड काफी हद तक समान है, जावा 6 सुविधाओं का उपयोग करने वाले 3-4 वर्गों को छोड़कर।

मैं केवल 1 कोडबेस बनाए रखना चाहता हूं। क्या मेरे कोड के कुछ हिस्सों को 'अनदेखा' करने के लिए जावा 5 कंपाइलर प्राप्त करने के लिए संकलन के दौरान कोई तरीका है?

मैं अपने जावा कंपाइलर के संस्करण के आधार पर, बस मेरे कोड के हिस्सों को टिप्पणी/असम्बद्ध करना नहीं चाहता हूं।

उत्तर

4

मानते हैं कि कक्षाओं में कार्यान्वयन में 1.5 बनाम 6.0 अंतर के साथ समान कार्यक्षमता है, तो आप उन्हें एक वर्ग में विलय कर सकते हैं। फिर, टिप्पणी/असम्बद्धता के स्रोत को संपादित किए बिना, आप अनुकूलन पर भरोसा कर सकते हैं कि संकलक हमेशा करता है। यदि कोई अभिव्यक्ति हमेशा गलत होती है, तो अगर कथन में कोड संकलन में शामिल नहीं किया जाएगा।

निर्धारित करें कि किस संस्करण आप चलाना चाहते हैं करने के लिए अपने वर्गों में से एक में एक स्थिर चर बना सकते हैं:

public static final boolean COMPILED_IN_JAVA_6 = false; 

और फिर प्रभावित वर्गों है कि स्थिर चर की जाँच की है और एक में कोड के विभिन्न वर्गों डाल सरल अगर कथन

if (VersionUtil.COMPILED_IN_JAVA_6) { 
    // Java 6 stuff goes here 
} else { 
    // Java 1.5 stuff goes here 
} 

तब जब आप अन्य संस्करण को संकलित करना चाहते हैं तो आपको केवल एक चर और पुन: संकलित करना होगा। यह जावा फ़ाइल को बड़ा कर सकता है लेकिन यह आपके कोड को समेकित करेगा और आपके पास मौजूद किसी भी कोड डुप्लिकेशन को खत्म करेगा। आपका संपादक पहुंचने योग्य कोड के बारे में शिकायत कर सकता है या जो कुछ भी संकलक को खुशी से अनदेखा कर सकता है।

+0

क्या यह जावा कंपाइलर्स का एक दस्तावेज व्यवहार है? –

+3

यह उत्तर गलत लगता है। मैंने एक त्वरित जावा ऐप किया जो java.io.Console और उपर्युक्त दृष्टिकोण का उपयोग करता था। संकलक 1.5 में विफल होने के साथ 1.5 में विफल रहा: Test.java:8: प्रतीक नहीं मिल सकता: विधि कंसोल() स्थान: कक्षा java.lang.System – noahlz

+0

मैं देख सकता था कि आप 1.6 में कैसे संकलित कर सकते हैं और कुछ को बहिष्कृत कर सकते हैं 1.5 जेवीएम में चलते समय रनटाइम फीचर्स। बेशक, आपको "अवैध मामूली संस्करण 49.0" त्रुटि से बचने के लिए 1.5 जेवीएम बाइटकोड प्रारूप में फिर से संकलित करने की आवश्यकता होगी। उस दृष्टिकोण के लिए, यह समाधान काम कर सकता है। – noahlz

4

मुझे लगता है कि बिल्ड स्क्रिप्ट का उपयोग करने के लिए शायद यहां सबसे अच्छा तरीका है। आपके पास एक ही स्थान पर आपका पूरा कोड हो सकता है, और कौन से फाइलों को शामिल करना है, और जो शामिल नहीं करना है, आप चुन सकते हैं कि संकलित करने के लिए आपके कोड का कौन सा संस्करण है। ध्यान दें कि यदि आपको प्रति फ़ाइल की तुलना में बेहतर अनाज नियंत्रण की आवश्यकता है तो इससे मदद नहीं मिल सकती है।

1

वास्तव में नहीं, लेकिन कामकाज हैं। देखें http://forums.sun.com/thread.jspa?threadID=154106&messageID=447625

यह कहा गया है कि आपको जावा 5 के लिए कम से कम एक फ़ाइल संस्करण और जावा 6 के लिए एक फ़ाइल संस्करण रखना चाहिए, और उन्हें एक बिल्ड के माध्यम से शामिल करना या उचित बनाना चाहिए। इसे एक बड़ी फाइल में चिपकाकर और 5 के लिए कंपाइलर को उन चीज़ों को अनदेखा करने की कोशिश कर रहा है जो समझ में नहीं आता है, यह एक अच्छा समाधान नहीं है।

HTH

- निकी -

1

यह सब जावा शुद्धतावादियों चापलूसी कर देगा (जो, मजेदार है हे हे), लेकिन मैं सी पूर्वप्रक्रमक का उपयोग करें, मेरे स्रोत में #ifdefs जाते थे। एक मेकफ़ाइल, रेकैकाइल, या जो कुछ भी आपके निर्माण को नियंत्रित करता है, उसे कंपाइलर को खिलाने के लिए अस्थायी फ़ाइलों को बनाने के लिए सीपीपी चलाने की आवश्यकता होगी। मुझे नहीं पता कि अगर ऐसा करने के लिए चींटी बनाई जा सकती है।

stackoverflow लग रहा है, वहीं की तरह यह सब जवाब के लिए जगह हो जाएगा, तो आप जावा ज्ञान के लिए अधिक करने के लिए http://www.javaranch.com पर कोई किसी की तलाश में खिसक जाना wehn सकता है। मुझे कल्पना है कि इस सवाल का सामना बहुत समय पहले किया गया था।

0

जावा में कोई प्री-कंपाइलर नहीं है। इस प्रकार, सी #में #ifdef करने का कोई तरीका नहीं है स्क्रिप्ट बनाएं सबसे अच्छा तरीका होगा।

+0

वह वास्तविक सी प्री-प्रोसेसर चलाने के लिए एस सी कंपाइलर का उपयोग करने का सुझाव दे रहा है, जो संशोधित स्रोत फ़ाइलों को आउटपुट करेगा, फिर उन पर जावा कंपाइलर चलाएगा। अधिकांश यदि सभी सी कंपाइलर्स के पास केवल प्री-प्रोसेसर चलाने के लिए स्विच नहीं है। –

0

आप सशर्त संकलन प्राप्त कर सकते हैं, लेकिन बहुत अच्छी तरह से नहीं - जावैक पहुंचने योग्य कोड को अनदेखा कर देगा। इस प्रकार यदि आपने अपना कोड सही ढंग से संरचित किया है, तो आप अपने कोड के हिस्सों को अनदेखा करने के लिए कंपाइलर प्राप्त कर सकते हैं। इसे सही तरीके से उपयोग करने के लिए, आपको javac में सही तर्कों को पारित करने की भी आवश्यकता होगी, इसलिए यह त्रुटियों के रूप में पहुंचने योग्य कोड की रिपोर्ट नहीं करता है, और संकलन करने से इंकार कर देता है :-)

2

जेडीके 5 के तहत निर्मित एक "मास्टर" स्रोत रूट रखें एक दूसरी समांतर स्रोत रूट जोड़ें जिसे जेडीके 6 या उसके बाद के तहत बनाना है। (कोई ओवरलैप नहीं होना चाहिए, यानी दोनों में कोई कक्षा मौजूद नहीं है।) दोनों के बीच प्रविष्टि बिंदु को परिभाषित करने के लिए एक इंटरफेस का उपयोग करें, और प्रतिबिंब का एक छोटा सा हिस्सा।

उदाहरण के लिए:

---%<--- main/RandomClass.java 
// ... 
if (...is JDK 6+...) { 
    try { 
     JDK6Interface i = (JDK6Interface) 
      Class.forName("JDK6Impl").newInstance(); 
     i.browseDesktop(...); 
    } catch (Exception x) { 
     // fall back... 
    } 
} 
---%<--- main/JDK6Interface.java 
public interface JDK6Interface { 
    void browseDesktop(URI uri); 
} 
---%<--- jdk6/JDK6Impl.java 
public class JDK6Impl implements JDK6Interface { 
    public void browseDesktop(URI uri) { 
     java.awt.Desktop.getDesktop().browse(uri); 
    } 
} 
---%<--- 

आप एक IDE में अलग परियोजनाओं अलग JDKs का उपयोग कर, आदि के रूप में इन कॉन्फ़िगर कर सकता हैमुद्दा यह है कि मुख्य रूट को स्वतंत्र रूप से संकलित किया जा सकता है और यह बहुत स्पष्ट है कि आप किस रूट में उपयोग कर सकते हैं, जबकि यदि आप एक ही रूट के अलग-अलग हिस्सों को अलग-अलग संकलित करने का प्रयास करते हैं तो यह जेडीके 6 के गलती से "रिसाव" उपयोग करना बहुत आसान है गलत फाइलों में।

इस तरह कक्षा.forName का उपयोग करने के बजाय, आप किसी भी प्रकार की सेवा पंजीकरण प्रणाली का उपयोग भी कर सकते हैं - java.util.ServiceLoader (यदि मुख्य जेडीके 6 का उपयोग कर सकता है और आप जेडीके 7 के लिए वैकल्पिक समर्थन चाहते थे!), नेटबीन लुकअप, वसंत, इत्यादि।

एक ही तकनीक का उपयोग नए जेडीके की बजाय वैकल्पिक पुस्तकालय के लिए समर्थन बनाने के लिए किया जा सकता है।

2

आप शायद अपने कोड को दोबारा कर सकते हैं ताकि सशर्त संकलन वास्तव में आवश्यक नहीं हो, केवल सशर्त वर्गीकरण। कुछ ऐसा:

public interface Opener{ 

public void open(File f); 

public static class Util{ 
     public Opener getOpener(){ 
      if(System.getProperty("java.version").beginsWith("1.5")){ 
      return new Java5Opener(); 
      } 
      try{ 
      return new Java6Opener(); 
      }catch(Throwable t){ 
      return new Java5Opener(); 
      } 
     } 
} 

} 

यह आपके पास कोड के कितने संस्करण-विशिष्ट टुकड़ों के आधार पर बहुत प्रयास हो सकता है।

0

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

तो मुझे लगता है कि यह सही समाधान है जिसे आप ढूंढ रहे थे।

0

एक सरल समाधान हो सकता है:

  • प्लेस अपने सामान्य classpath के बाहर अलग-अलग वर्गों।
  • एक साधारण कस्टम क्लासलोडर लिखें और इसे अपने डिफ़ॉल्ट के रूप में मुख्य रूप से इंस्टॉल करें।
  • 5/6 से अलग सभी वर्गों के लिए कैसलोडर अपने माता-पिता (सामान्य सिस्टम क्लासलोडर)
  • के लिए 5/6 वाले (जो माता-पिता द्वारा नहीं मिल सकते हैं) यह तय कर सकता है कि 'os.name' संपत्ति या अपने आप में से कौन सा उपयोग करना है।
1

यह जावा 6 विशेषताओं के उपयोग पर निर्भर करता है जो आप उपयोग करना चाहते हैं।JTables को पंक्ति छांटने जोड़ने की तरह एक साधारण बात के लिए, आप वास्तव में रनटाइम पर परीक्षण कर सकते हैं:

private static final double javaVersion = 
     Double.parseDouble(System.getProperty("java.version").substring(0, 3)); 
private static final boolean supportsRowSorter = 
     (javaVersion >= 1.6); 

//... 

if (supportsRowSorter) { 
    myTable.setAutoCreateRowSorter(true); 
} else { 
    // not supported 
} 

इस कोड जावा 6 के साथ संकलित किया जाना चाहिए, लेकिन किसी भी संस्करण (कोई नए वर्गों संदर्भित) के साथ चलाया जा सकता है।

संपादित करें: अधिक सही होने के लिए, यह 1.3 के बाद से किसी भी संस्करण के साथ काम करेगा (this page के अनुसार)।

5

कस्टम क्लास लोडर और गतिशील रूप से टिप्पणी किए गए कोड का उपयोग करने के बारे में सुझाव थोड़ा सा अविश्वसनीय हैं जब रखरखाव की बात आती है और जो भी गरीब आत्मा प्रकृति को उठाती है, उसके बाद आप चरागाहों को नए स्थानांतरित कर देते हैं।

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

+1

स्वतंत्र परियोजनाएं ओवरकिल हैं, अलग-अलग स्रोत फ़ोल्डर्स और कस्टम बिल्ड स्क्रिप्ट ठीक काम करेगी। सामान्य कोडबेस के साथ स्रोत/फ़ोल्डर्स के लिए स्रोत फ़ोल्डर का उपयोग करें, और कहें, प्रत्येक संस्करण पर निर्भर सुविधाओं के लिए src/java5 और src/java6। – Leonel

1

आप अपने सभी संकलन विशेष रूप से जावा 6 पर कर सकते हैं और फिर System5getProperty ("java.version") को सशर्त रूप से Java5 या Java6 कोड पथ चलाने के लिए उपयोग कर सकते हैं।

आपके पास कक्षा में केवल जावा 6-कोड हो सकता है और कक्षा जावा 5 पर ठीक चल जाएगी जब तक कि जावा 6-केवल कोड पथ निष्पादित नहीं किया जाता है।

यह एक चाल है जिसका उपयोग एप्लेट लिखने के लिए किया जाता है जो प्राचीन एमएसजेवीएम पर नए-नए जावा प्लग-इन जेवीएम तक चलता है।

0

आप प्रतिबिंब API का उपयोग कर सकते हैं। अपने सभी 1.5 कोड को एक कक्षा में और 1.6 एपीआई दूसरे में रखें। आपकी चींटी स्क्रिप्ट में 1.5 के लिए दो लक्ष्य एक बनाते हैं जो 1.6 वर्ग और 1.6 के लिए एक संकलित नहीं करेगा जो कक्षा 1.5 को संकलित नहीं करेगा। अपने कोड में अपने जावा संस्करण की जांच करें और उचित वर्ग को प्रतिबिंब का उपयोग करके लोड करें जिससे जैवैक लापता कार्यों के बारे में शिकायत नहीं करेगा। इस तरह मैं विंडोज़ पर अपने एमआरजे (जावा के लिए मैक रनटाइम) अनुप्रयोगों को संकलित कर सकता हूं।

संबंधित मुद्दे

 संबंधित मुद्दे