Java Compilation - هل هناك طريقة لإخبار المترجم بتجاهل أجزاء من الكود الخاص بي؟

StackOverflow https://stackoverflow.com/questions/74171

  •  09-06-2019
  •  | 
  •  

سؤال

أحتفظ بتطبيق Java Swing.

من أجل التوافق مع الإصدارات السابقة مع Java 5 (لأجهزة Apple)، نحتفظ بقاعدتي تعليمات برمجية، واحدة تستخدم ميزات من Java 6، والأخرى بدون هذه الميزات.

الكود هو نفسه إلى حد كبير، باستثناء 3-4 فئات تستخدم ميزات Java 6.

أرغب في الاحتفاظ بقاعدة تعليمات برمجية واحدة فقط.هل هناك طريقة أثناء الترجمة لجعل مترجم Java 5 "يتجاهل" بعض أجزاء الكود الخاص بي؟

لا أرغب ببساطة في التعليق/إلغاء التعليق على أجزاء من الكود الخاص بي، اعتمادًا على إصدار مترجم جافا الخاص بي.

هل كانت مفيدة؟

المحلول

على افتراض أن الفئات لها وظائف مماثلة مع 1.5 مقابل 1.5.6.0 اختلافات في التنفيذ يمكنك دمجها في فئة واحدة.بعد ذلك، بدون تحرير المصدر للتعليق/إلغاء التعليق، يمكنك الاعتماد على التحسين الذي يقوم به المترجم دائمًا.إذا كان تعبير if دائمًا خاطئًا، فلن يتم تضمين الكود الموجود في عبارة if في التجميع.

يمكنك إنشاء متغير ثابت في إحدى فئاتك لتحديد الإصدار الذي تريد تشغيله:

public static final boolean COMPILED_IN_JAVA_6 = false;

ثم اطلب من الفئات المتأثرة التحقق من هذا المتغير الثابت ووضع الأقسام المختلفة من التعليمات البرمجية في عبارة if بسيطة

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

ثم عندما تريد ترجمة الإصدار الآخر، عليك فقط تغيير ذلك المتغير وإعادة الترجمة.قد يؤدي ذلك إلى زيادة حجم ملف جافا ولكنه سيعمل على دمج التعليمات البرمجية الخاصة بك وإزالة أي تكرار للتعليمات البرمجية لديك.قد يشكو المحرر الخاص بك من التعليمات البرمجية التي لا يمكن الوصول إليها أو أي شيء آخر ولكن يجب على المترجم أن يتجاهلها بكل سرور.

نصائح أخرى

تعتبر الاقتراحات المتعلقة باستخدام أدوات تحميل الفئة المخصصة والكود الذي تم التعليق عليه ديناميكيًا أمرًا مشكوكًا فيه بعض الشيء عندما يتعلق الأمر بالصيانة والحفاظ على سلامة أي روح فقيرة تلتقط المشروع بعد التبديل إلى المراعي الجديدة.

الحل سهل.قم بسحب الفئات المتأثرة إلى مشروعين منفصلين ومستقلين - تأكد من أن أسماء الحزم هي نفسها، وقم فقط بتجميعها في الجرار التي يمكنك بعد ذلك استهلاكها في مشروعك الرئيسي.إذا احتفظت بأسماء الحزم كما هي، وتوقيعات الطريقة كما هي، فلن تكون هناك مشاكل - ما عليك سوى إسقاط أي إصدار من الجرة تحتاجه في البرنامج النصي للنشر الخاص بك.أفترض أنك تقوم بتشغيل نصوص بناء منفصلة أو أن لديك أهدافًا منفصلة في نفس البرنامج النصي - يمكن لكل من ant وmaven التعامل بسهولة مع ملفات الاستيلاء المشروط ونسخها.

أعتقد أن أفضل طريقة هنا هي على الأرجح استخدام البرامج النصية للبناء.يمكنك الحصول على جميع التعليمات البرمجية الخاصة بك في مكان واحد، ومن خلال اختيار الملفات التي تريد تضمينها والملفات التي لا تريد تضمينها، يمكنك اختيار إصدار التعليمات البرمجية التي تريد تجميعها.لاحظ أن هذا قد لا يساعدك إذا كنت بحاجة إلى تحكم أكثر دقة من كل ملف.

ربما يمكنك إعادة بناء التعليمات البرمجية الخاصة بك بحيث لا تكون هناك حاجة إلى الترجمة الشرطية، فقط تحميل الفصل الشرطي.شيء من هذا القبيل:

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();
           }
        }
 }

}

قد يتطلب هذا الكثير من الجهد اعتمادًا على عدد أجزاء التعليمات البرمجية الخاصة بالإصدار لديك.

احتفظ بجذر مصدر "رئيسي" واحد يتم إنشاؤه ضمن JDK 5.أضف جذر مصدر موازيًا ثانيًا يجب إنشاؤه ضمن JDK 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 مختلفة، وما إلى ذلك.النقطة المهمة هي أنه يمكن تجميع الجذر الرئيسي بشكل مستقل ومن الواضح جدًا ما يمكنك استخدامه في أي جذر، بينما إذا حاولت تجميع أجزاء مختلفة من جذر واحد بشكل منفصل فمن السهل جدًا "تسريب" استخدام JDK 6 عن طريق الخطأ. في الملفات الخاطئة.

بدلاً من استخدام Class.forName بهذه الطريقة، يمكنك أيضًا استخدام نوع ما من نظام تسجيل الخدمة - java.util.ServiceLoader (إذا كان بإمكانك استخدام JDK 6 وأردت دعمًا اختياريًا لـ JDK 7!) وNetBeans Lookup وSpring وما إلى ذلك.إلخ.

يمكن استخدام نفس التقنية لإنشاء دعم لمكتبة اختيارية بدلاً من JDK الأحدث.

ليس حقا، ولكن هناك حلول.يرىhttp://forums.sun.com/thread.jspa?threadID=154106&messageID=447625

ومع ذلك، يجب عليك الالتزام بوجود إصدار ملف واحد على الأقل لـ Java 5 وواحد لـ Java 6، وإدراجهما عبر إنشاء أو إنشاء حسب الاقتضاء.إن لصق كل شيء في ملف واحد كبير ومحاولة جعل المترجم المكون من 5 أشخاص يتجاهل الأشياء التي لا يفهمها ليس حلاً جيدًا.

هث

-- نيكي --

هذا سيجعل جميع خبراء Java يتراجعون (وهو أمر ممتع، هيه هيه) ولكنني سأستخدم معالج C الأولي، وأضع #ifdefs في المصدر الخاص بي.يجب أن يقوم ملف makefile أو rakefile أو أي شيء يتحكم في البناء الخاص بك بتشغيل cpp لإنشاء ملفات مؤقتة لتغذية المترجم.ليس لدي أي فكرة عما إذا كان من الممكن جعل النملة تفعل ذلك.

في حين يبدو أن stackoverflow سيكون كذلك ال مكانًا لجميع الإجابات، حيث لا يمكن لأحد أن ينظر إليه http://www.javaranch.com لجافا الحكمة.أتصور أن هذا السؤال قد تم تناوله هناك منذ وقت طويل.

يعتمد ذلك على ميزات Java 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
}

يجب أن يتم تجميع هذا الكود باستخدام Java 6، ولكن يمكن تشغيله مع أي إصدار (لا تتم الإشارة إلى فئات جديدة).

يحرر:ولكي أكون أكثر صحة، فإنه سيعمل مع أي إصدار منذ 1.3 (وفقًا لـ 1.3). هذه الصفحة).

يمكنك القيام بكل عمليات التجميع الخاصة بك حصريًا على Java6 ثم استخدام System.getProperty("java.version") لتشغيل Java5 أو مسار كود Java6 بشكل مشروط.

يمكن أن يكون لديك كود Java6 فقط في الفصل الدراسي وسيعمل الفصل بشكل جيد على Java5 طالما لم يتم تنفيذ مسار كود Java6 فقط.

هذه خدعة تُستخدم لكتابة التطبيقات الصغيرة التي سيتم تشغيلها على MSJVM القديم وصولاً إلى Java Plug-in JVMs الجديدة تمامًا.

لا يوجد مترجم مسبق في جافا.وبالتالي، لا توجد طريقة للقيام بـ #ifdef كما هو الحال في C.سيكون بناء البرامج النصية هو أفضل طريقة.

يمكنك الحصول على الترجمة الشرطية، ولكن ليس بشكل جيد جدًا - سوف يتجاهل javac التعليمات البرمجية التي لا يمكن الوصول إليها.وبالتالي، إذا قمت بتنظيم التعليمات البرمجية الخاصة بك بشكل صحيح، يمكنك جعل المترجم يتجاهل أجزاء من التعليمات البرمجية الخاصة بك.لاستخدام هذا بشكل صحيح، ستحتاج أيضًا إلى تمرير الوسيطات الصحيحة إلى javac حتى لا يُبلغ عن التعليمات البرمجية التي لا يمكن الوصول إليها كأخطاء، ويرفض التجميع :-)

الحل النهائي العام الثابت المذكور أعلاه له فائدة إضافية لم يذكرها المؤلف - كما أفهمها، سيتعرف عليها المترجم في وقت الترجمة ويجمع أي كود موجود ضمن عبارة if التي تشير إلى هذا المتغير النهائي.

لذلك أعتقد أن هذا هو الحل الدقيق الذي كنت تبحث عنه.

الحل البسيط يمكن أن يكون:

  • ضع الفئات المتباينة خارج مسار الفصل العادي الخاص بك.
  • اكتب أداة تحميل فئة مخصصة بسيطة وقم بتثبيتها بشكل رئيسي كأداة افتراضية.
  • بالنسبة لجميع الفئات باستثناء الفئات 5/6، يمكن للمحمل التسلسلي أن يتنازل عن الأصل (محمل فئة النظام العادي)
  • بالنسبة إلى العناصر 5/6 (والتي يجب أن تكون الوحيدة التي لا يمكن للوالد العثور عليها) يمكنه تحديد أي منها سيتم استخدامه عبر خاصية "os.name" أو خاصية خاصة بك.

يمكنك استخدام واجهة برمجة تطبيقات الانعكاس.ضع كل كود 1.5 الخاص بك في فئة واحدة و1.6 API في فئة أخرى.في برنامج النمل النصي الخاص بك، قم بإنشاء هدفين، أحدهما لـ 1.5 لن يقوم بتجميع الفئة 1.6 والآخر لـ 1.6 الذي لن يقوم بتجميع الفئة لـ 1.5.في الكود الخاص بك، تحقق من إصدار Java الخاص بك وقم بتحميل الفصل المناسب باستخدام الانعكاس بهذه الطريقة لن يشكو javac من الوظائف المفقودة.هذه هي الطريقة التي يمكنني من خلالها تجميع تطبيقات MRJ (Mac Runtime for Java) على نظام التشغيل Windows.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top