significa que maquina estructura eficiente cual compilar compilador caracteristicas java swing compilation

maquina - Compilación de Java: ¿hay alguna manera de decirle al compilador que ignore partes de mi código?



que es compilar en java (14)

Mantengo una aplicación Java Swing.

Por compatibilidad con versiones anteriores de java 5 (para máquinas Apple), mantenemos dos bases de código, 1 usando características de Java 6, otra sin esas características.

El código es básicamente el mismo, excepto para 3-4 clases que usan las características de Java 6.

Deseo mantener solo 1 base de código. ¿Hay alguna manera durante la compilación de hacer que el compilador Java 5 ''ignore'' algunas partes de mi código?

No deseo simplemente comentar / descomentar partes de mi código, dependiendo de la versión de mi compilador de Java.


Creo que el mejor enfoque aquí es probablemente usar scripts de compilación. Puede tener todo su código en una ubicación, y al elegir qué archivos incluir y cuáles no incluir, puede elegir qué versión de su código compilar. Tenga en cuenta que esto puede no ser de ayuda si necesita un control más fino que el que tiene por archivo.


Mantenga una raíz de origen "maestra" que se compila bajo JDK 5. Agregue una segunda raíz de fuente paralela que se debe compilar bajo JDK 6 o superior. (No debe haber superposición, es decir, no hay clases presentes en ambos). Utilice una interfaz para definir el punto de entrada entre los dos y un poco de reflexión.

Por ejemplo:

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

Puede configurarlos como proyectos separados en un IDE utilizando diferentes JDK, etc. El punto es que la raíz principal se puede compilar de forma independiente y está muy claro qué se puede usar en qué raíz, mientras que si se intenta compilar diferentes partes de un única raíz por separado, es demasiado fácil "perder" accidentalmente el uso de JDK 6 en los archivos incorrectos.

En lugar de utilizar Class.forName de esta manera, también puede usar algún tipo de sistema de registro de servicio: java.util.ServiceLoader (¡si main pudiera usar JDK 6 y quisiera soporte opcional para JDK 7!), NetBeans Lookup, Spring, etc. etc.

La misma técnica puede usarse para crear soporte para una biblioteca opcional en lugar de un JDK más nuevo.


No realmente, pero hay soluciones. Ver http://forums.sun.com/thread.jspa?threadID=154106&messageID=447625

Dicho esto, debe quedarse con al menos tener una versión de archivo para Java 5 y otra para Java 6, e incluirlas a través de una compilación o marca, según corresponda. Pegar todo en un archivo grande y tratar de hacer que el compilador ignore las cosas que no comprende no es una buena solución.

HTH

- nikki -


No hay precompilador en Java. Por lo tanto, no hay forma de hacer un #ifdef como en C. Crear scripts sería la mejor manera.


Puede obtener una compilación condicional, pero no muy bien: javac ignorará el código inalcanzable. Por lo tanto, si estructura su código correctamente, puede hacer que el compilador ignore partes de su código. Para usar esto correctamente, también necesitaría pasar los argumentos correctos a javac para que no reporte el código inalcanzable como errores y se rehúse a compilar :-)


Depende de las características de Java 6 que quiera usar. Para una cosa simple como agregar clasificadores de fila a JTables, puedes probar en tiempo de ejecución:

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 }

Este código debe compilarse con Java 6, pero se puede ejecutar con cualquier versión (no se hace referencia a clases nuevas).

EDITAR: para ser más correctos, funcionará con cualquier versión desde 1.3 (según esta página ).


Esto hará temblar a todos los puristas de Java (lo cual es divertido, je je) pero usaría el preprocesador C, pondré #ifdefs en mi fuente. Un archivo MAKE, RAKEFILE, o lo que sea que controle tu compilación, debería ejecutar cpp para crear archivos temporales para alimentar al compilador. No tengo idea de si se podría hacer una hormiga para hacer esto.

Mientras que parece ser el lugar para todas las respuestas, no podrías haber visto a nadie en Java en http://www.javaranch.com . Me imagino que esta pregunta ha sido tratada allí, prolly hace mucho tiempo.


La solución final pública estática mencionada anteriormente tiene un beneficio adicional que el autor no mencionó; según tengo entendido, el compilador lo reconocerá en tiempo de compilación y compilará cualquier código que esté dentro de una declaración if que haga referencia a esa variable final.

Entonces creo que esa es la solución exacta que estabas buscando.


Las sugerencias sobre el uso de cargadores de clase personalizados y el código dinámicamente comentado son un poco incrédulos cuando se trata de mantenimiento y la preservación de la cordura de cualquier alma pobre que retoma el proyecto después de barajar nuevas pasturas.

La solución es fácil. Extraiga las clases afectadas en dos proyectos separados e independientes: asegúrese de que los nombres de los paquetes sean los mismos, y simplemente compile en recipientes que luego puede consumir en su proyecto principal. Si mantiene los nombres de los paquetes iguales, y las firmas del método son iguales, no hay problemas, simplemente coloque la versión del archivo jar que necesite en su secuencia de comandos de implementación. Asumiría que ejecuta scripts de compilación separados o tiene objetivos separados en la misma secuencia de comandos, y maven puede manejar fácilmente los archivos de captura condicional y copiarlos.


Probablemente pueda refactorizar su código para que la compilación condicional realmente no sea necesaria, solo carga de clases condicional. Algo como esto:

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

Esto podría ser un gran esfuerzo, dependiendo de la cantidad de códigos de versión específicos que tenga.


Puede hacer toda su compilación exclusivamente en Java6 y luego usar System.getProperty ("java.version") para ejecutar condicionalmente la ruta del código Java5 o Java6.

Puede tener código Java6-only en una clase y la clase se ejecutará bien en Java5 siempre que no se ejecute la ruta del código Java6-only.

Este es un truco que se usa para escribir applets que se ejecutarán en el antiguo MSJVM hasta llegar a las nuevas JVM Java Plug-in.


Suponiendo que las clases tengan una funcionalidad similar con diferencias de implementación de 1.5 vs. 6.0, podrías fusionarlas en una sola clase. Luego, sin editar la fuente para comentar / descomentar, puede confiar en la optimización que el compilador siempre hace. Si una expresión if es siempre falsa, el código en la instrucción if no se incluirá en la compilación.

Puede crear una variable estática en una de sus clases para determinar qué versión desea ejecutar:

public static final boolean COMPILED_IN_JAVA_6 = false;

Y luego haga que las clases afectadas verifiquen esa variable estática y coloquen las diferentes secciones de código en una declaración if simple

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

Luego, cuando desee compilar la otra versión, solo tiene que cambiar esa variable y volver a compilarla. Puede hacer que el archivo java sea más grande, pero consolidará su código y eliminará cualquier duplicación de código que tenga. Su editor puede quejarse sobre el código inalcanzable o lo que sea, pero el compilador debería ignorarlo felizmente.


Una solución simple podría ser:

  • Coloque las clases divergentes fuera de su classpath normal.
  • Escriba un cargador de clases personalizado simple e instálelo en principal como su predeterminado.
  • Para todas las clases, aparte de las 5/6, el cargador de cassette puede diferir a su padre (el cargador de clases del sistema normal)
  • Para los 5/6 (que deberían ser los únicos que no pueden ser encontrados por el padre) puede decidir cuál usar a través de la propiedad ''os.name'' o una propia.

Puedes usar la API de reflexión. pon todo tu código 1.5 en una clase y 1.6 api en otra. En su script ant, cree dos objetivos, uno para 1.5 que no compilará la clase 1.6 y otro para 1.6 que no compilará la clase para 1.5. en su código verifique su versión de java y cargue la clase apropiada usando la reflexión de esa manera javac no se quejará de las funciones que faltan. Así es como puedo compilar mis aplicaciones MRJ (Mac Runtime para Java) en Windows.