Java-samestelling - Is daar 'n manier om die samesteller te vertel om dele van my kode te ignoreer?

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

  •  09-06-2019
  •  | 
  •  

Vra

Ek handhaaf 'n Java Swing-toepassing.

Vir terugwaartse versoenbaarheid met Java 5 (vir Apple-masjiene), handhaaf ons twee kodebasisse, 1 met kenmerke van Java 6, 'n ander sonder daardie kenmerke.

Die kode is grootliks dieselfde, behalwe vir 3-4 klasse wat Java 6-kenmerke gebruik.

Ek wil net 1 kodebasis in stand hou.Is daar 'n manier tydens samestelling om die Java 5-samesteller te kry om sommige dele van my kode te 'ignoreer'?

Ek wil nie bloot kommentaar lewer op dele van my kode nie, afhangende van die weergawe van my java-samesteller.

Was dit nuttig?

Oplossing

As ons aanneem dat die klasse het 'n soortgelyke funksie met 1.5 vs. 6.0 verskille in die implementering jy kan hulle saam te smelt in een klas. Dan, sonder wysiging van die bron om kommentaar te lewer / uncomment, kan jy staatmaak op die optimalisering dat die samesteller altyd doen. As 'n as uitdrukking is altyd vals, die kode in die as verklaring sal nie ingesluit word in die samestelling.

Jy kan 'n statiese veranderlike in een van jou klasse om te bepaal watter weergawe jy wil uit te voer:

public static final boolean COMPILED_IN_JAVA_6 = false;

En dan het die geaffekteerde klasse seker te maak dat statiese veranderlike en sit die verskillende afdelings van die kode in 'n eenvoudige as verklaring

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

Dan wanneer jy wil die ander weergawe op te stel wat jy net moet dat een veranderlike verander en heropstel. Dit mag dalk die java lêer groter te maak, maar dit sal jou kode te konsolideer en uit te skakel enige kode duplisering wat jy het. Jou redakteur kan kla oor onbereikbaar kode of wat ook al, maar die samesteller moet salig ignoreer dit.

Ander wenke

Die voorstelle oor die gebruik van persoonlike klas loaders en dinamiese kommentaar kode is 'n bietjie ongelowig wanneer dit kom by die instandhouding en die behoud van die gesonde verstand van wat ook al arme siel tel die projek nadat jy skuif na nuwe weivelde.

Die oplossing is maklik. Trek die geaffekteerde klasse uit in twee afsonderlike, onafhanklike projekte - maak seker dat die pakket name is dieselfde, en net saam te stel in potte wat jy dan kan verteer in jou belangrikste projek. As jy die pakket name dieselfde te hou, en die metode handtekeninge dieselfde, geen probleme nie - net laat val ookal weergawe van die pot wat jy nodig het in jou ontplooiing script. Ek neem aan jy aparte bou skrifte loop of het 'n aparte teikens in dieselfde script -. Mier en Maven kan beide maklik hanteer voorwaardelik gryp lêers en hulle kopiëring

Ek dink die beste benadering hier is waarskynlik om te gebruik te bou skrifte. Jy kan al jou kode in een plek, en deur te kies watter lêers in te sluit, en wat om nie te sluit, jy kan kies watter weergawe van jou kode op te stel. Let daarop dat dit nie kan help as jy fyner korrelige beheer as per lêer nodig.

Jy kan waarskynlik refactor jou kode sodat voorwaardelike Stel regtig is nie nodig nie, net voorwaardelike classloading. Iets soos hierdie:

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

}

Dit kan 'n baie moeite wees, afhangende van hoeveel weergawe-spesifieke stukke van die kode wat jy het.

Hou een "meester" bron wortel wat bou onder JDK 5. Voeg 'n tweede parallel bron wortel wat te bou onder JDK 6 of hoër. (Daar moet geen oorvleueling, dit wil sê geen klasse teenwoordig in beide wees.) Gebruik 'n koppelvlak tot die beginpunt tussen die twee, en 'n klein bietjie van die beraad te definieer.

Byvoorbeeld:

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

Jy kan hierdie as afsonderlike projekte in 'n IDE instel met behulp van verskillende JDKs, ens Die punt is dat die hoofwortel kan onafhanklik saamgestel en dit is baie duidelik wat jy kan gebruik in wil maak wat root, terwyl as jy probeer om anders te stel dele van 'n enkele wortel apart dit is te maklik om per ongeluk "lek" gebruik van JDK 6 in die verkeerde lêers.

In plaas van die gebruik van Class.forName soos hierdie, jy kan ook 'n soort van diens registrasie stelsel gebruik - java.util.ServiceLoader (indien hoof kon JDK 6 gebruik en jy wil opsionele ondersteuning vir JDK 7!), NetBeans Lookup, Lente , ens ens.

Dieselfde tegniek kan gebruik word om ondersteuning te skep vir 'n opsionele biblioteek eerder as 'n nuwer JDK.

Nie regtig nie, maar daar is oplossings.Sienhttp://forums.sun.com/thread.jspa?threadID=154106&messageID=447625

Dit gesê, jy moet by ten minste een lêerweergawe vir Java 5 en een vir Java 6 hou, en dit insluit via 'n bou of maak soos toepaslik.Om dit alles in een groot lêer te plaas en die samesteller vir 5 te probeer kry om goed te ignoreer wat dit nie verstaan ​​nie, is nie 'n goeie oplossing nie.

HTH

-- nikki --

Dit sal al die Java puriste vleien (wat is pret, heh heh), maar ek sal die C preprocessor gebruik, sit #ifdefs in my bron. A makefile, rakefile, of wat ook al jou bou beheer, sou hê om CPP hardloop om 'n tydelike lêers te maak om die samesteller voed. Ek het geen idee as mier gemaak kan word om dit te doen.

Hoewel StackOverflow lyk soos dit sal wees die plek vir al die antwoorde, kan jy nie 'n mens se soek rond hang wehn op na http://www.javaranch.com vir Java wysheid. Ek neem aan hierdie vraag afgehandel is daar, prolly 'n lang tyd gelede.

Dit hang af van wat Java 6 eienskappe wat jy wil gebruik. Vir 'n eenvoudige ding soos die toevoeging van ry sorteerders om JTables, kan jy eintlik toets tydens looptyd:

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
}

Die kode word opgestel met Java 6, maar kan gebruik word met enige weergawe (geen nuwe klasse word verwys).

EDIT: om meer korrek te wees, sal dit werk met enige weergawe sedert 1.3 (volgens hierdie bladsy ).

Jy kan al doen van uitsluitlik jou die opstel van op Java6 en dan gebruik System.getProperty ( "java.version") om óf die Java5 of die Java6 kode pad voorwaardelik loop.

Jy kan Java6-net-kode moet in 'n klas en die klas sal so lank as wat die Java6-net-kode pad nie uitgevoer word fyn loop op Java5.

Dit is 'n truuk wat gebruik word om applets wat sal loop op die ou MSJVM al die pad tot by skryf splinternuwe Java Plug-in JVMs.

Daar is geen pre-samesteller in Java. Dus, geen manier om 'n #ifdef doen soos in C. Bou skrifte sal die beste manier wees.

Jy kan voorwaardelike Stel kry, maar nie baie mooi - javac sal onbereikbaar kode ignoreer. So as jy jou kode behoorlik gestruktureer, kan jy die samesteller om dele van jou kode te ignoreer kry. Om hierdie reg te gebruik, sal jy ook nodig om die korrekte argumente slaag om javac so dit nie onbereikbaar kode as foute maak rapporteer, en weier om saam te stel: -)

Die openbare statiese finale oplossing bogenoemde het een bykomende voordeel van die skrywer het geen melding van - soos ek dit verstaan, sal die samesteller dit erken tydens kompilering en stel uit enige kode wat binne 'n as verklaring wat verwys na wat finale veranderlike.

So ek dink dit is die presiese oplossing wat jy soek.

'n eenvoudige oplossing kan wees:

  • Plaas die uiteenlopende klasse buite jou normale classpath.
  • Skryf 'n eenvoudige persoonlike classloader en installeer dit in hoof as jou verstek.
  • Vir alle klasse afgesien van die 5/6 kinders die cassloader kan stel om sy ouer (die normale stelsel classloader)
  • Vir die 5/6 kinders (wat behoort te wees die enigstes wat nie gevind kan word deur die ouer) kan besluit watter om te gebruik via die 'os.name' eiendom of een van jou eie.

Jy kan weerspieëling API te gebruik. sit al jou 1.5 kode in een klas en 1.6 api in 'n ander. In jou mier script te skep twee teikens een vir 1.5 wat nie sal stel die klas 1.6 en een vir 1.6 wat nie die klas sal saamstel vir 1.5. in jou kode check jou Java weergawe en laai die toepaslike klas met behulp van besinning op die manier javac sal nie kla oor vermiste funksies. Dit is hoe ek my MRJ (Mac Runtime vir Java) programme op vensters kan saamstel.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top