Comment puis-je me réfère à Java 1.6 API tout en dégradant grâce contre Java 1.5?

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

  •  16-09-2019
  •  | 
  •  

Autres conseils

public interface NfcNormalizer
{
  public String normalize(String str);
}

public class IdentityNfcNormalizer implements NfcNormalizer
{
  public String normalize(String str)
  {
    return str;
  }
}

public class JDK16NfcNormalizer implements NfcNormalizer
{
  public String normalize(String str)
  {
    return Normalizer.normalize(str, Normalizer.Form.NFC);
  }
}

Dans votre code client:

NfcNormalizer normalizer;
try
{
  normalizer = Class.forName("JDK16NfcNormalizer").newInstance();
}
catch(Exception e)
{
  normalizer = new IdentityNfcNormalizer();
}
  

Je ne me dérange pas si le code en cours d'exécution sur 1.5 ne fait pas la normalisation, mais je ne veux pas donner NoClassDefFoundErrors ou ClassNotFoundExceptions quand il fonctionne.

Si vous voulez éviter la réflexion, vous pouvez réellement attraper ces erreurs.

De cette façon, vous pouvez compiler contre les classes flambant neuf avec un compilateur java6, et il fonctionne toujours (comme dans « ne rien faire, mais pas non plus tomber en panne ») sur Java5.

Vous pouvez également combiner les deux approches, et de vérifier si la classe existe en utilisant la réflexion, et si elle ne continue à l'appeler d'une manière non réfléchissante. C'est ce que la solution d'Andrew est en train de faire.

Si vous devez également compilation sur Java5, alors vous devez aller tout le chemin réflexion.

J'ai eu ce même besoin, puisque nous avons un code qui doit fonctionner sur toutes les versions de Java à partir de Java 1.2, mais un code doit tirer parti des API les plus récents de si elles sont disponibles.

Après diverses permutations à l'aide de la réflexion pour obtenir des objets méthode et les invoquer dynamiquement, j'ai installé sur une approche de style wrapper mieux, en général (bien que dans certaines circonstances, juste stocker la méthode réfléchie en statique et en invoquant, il vaut mieux - cela dépend).

Voici un exemple « System Utility » classe qui expose certaines API les plus récents de Java 5 lors de l'exécution d'une version antérieure - les mêmes principes sont valables pour Java 6 dans JVMs antérieures. Cet exemple utilise un Singleton, mais pourrait facilement instancier plusieurs objets si l'API sous-jacente nécessaire que.

Il existe deux classes:

  • SysUtil
  • SysUtil_J5

Ce dernier est celui utilisé si l'exécution JVM est Java 5 ou version ultérieure. Sinon les méthodes de repli qui sont compatibles dans le contrat sont utilisés à partir de la mise en œuvre par défaut dans SysUtil qui utilise Java seulement 4 ou API antérieures. Chaque classe est compilé avec le compilateur de version spécifique, de sorte qu'il n'y a pas une utilisation accidentelle de l'API Java dans la classe Java 4:

SysUtil (compilé avec le compilateur Java 4)

import java.io.*;
import java.util.*;

/**
 * Masks direct use of select system methods to allow transparent use of facilities only
 * available in Java 5+ JVM.
 *
 * Threading Design : [ ] Single Threaded  [x] Threadsafe  [ ] Immutable  [ ] Isolated
 */

public class SysUtil
extends Object
{

/** Package protected to allow subclass SysUtil_J5 to invoke it. */
SysUtil() {
    super();
    }

// *****************************************************************************
// INSTANCE METHODS - SUBCLASS OVERRIDE REQUIRED
// *****************************************************************************

/** Package protected to allow subclass SysUtil_J5 to override it. */
int availableProcessors() {
    return 1;
    }

/** Package protected to allow subclass SysUtil_J5 to override it. */
long milliTime() {
    return System.currentTimeMillis();
    }

/** Package protected to allow subclass SysUtil_J5 to override it. */
long nanoTime() {
    return (System.currentTimeMillis()*1000000L);
    }

// *****************************************************************************
// STATIC PROPERTIES
// *****************************************************************************

static private final SysUtil            INSTANCE;
static {
    SysUtil                             instance=null;

    try                  { instance=(SysUtil)Class.forName("SysUtil_J5").newInstance(); } // can't use new SysUtil_J5() - compiler reports "class file has wrong version 49.0, should be 47.0"
    catch(Throwable thr) { instance=new SysUtil();                                                                    }
    INSTANCE=instance;
    }

// *****************************************************************************
// STATIC METHODS
// *****************************************************************************

/**
 * Returns the number of processors available to the Java virtual machine.
 * <p>
 * This value may change during a particular invocation of the virtual machine. Applications that are sensitive to the
 * number of available processors should therefore occasionally poll this property and adjust their resource usage
 * appropriately.
 */
static public int getAvailableProcessors() {
    return INSTANCE.availableProcessors();
    }

/**
 * Returns the current time in milliseconds.
 * <p>
 * Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the
 * underlying operating system and may be larger. For example, many operating systems measure time in units of tens of
 * milliseconds.
 * <p>
 * See the description of the class Date for a discussion of slight discrepancies that may arise between "computer time"
 * and coordinated universal time (UTC).
 * <p>
 * @return         The difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
 */
static public long getMilliTime() {
    return INSTANCE.milliTime();
    }

/**
 * Returns the current value of the most precise available system timer, in nanoseconds.
 * <p>
 * This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock
 * time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values
 * may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees
 * are made about how frequently values change. Differences in successive calls that span greater than approximately 292
 * years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.
 * <p>
 * For example, to measure how long some code takes to execute:
 * <p><pre>
 *    long startTime = SysUtil.getNanoTime();
 *    // ... the code being measured ...
 *    long estimatedTime = SysUtil.getNanoTime() - startTime;
 * </pre>
 * <p>
 * @return          The current value of the system timer, in nanoseconds.
 */
static public long getNanoTime() {
    return INSTANCE.nanoTime();
    }

} // END PUBLIC CLASS

SysUtil_J5 (compilé avec le compilateur Java 5)

import java.util.*;

class SysUtil_J5
extends SysUtil
{

private final Runtime                   runtime;

SysUtil_J5() {
    super();

    runtime=Runtime.getRuntime();
    }

// *****************************************************************************
// INSTANCE METHODS
// *****************************************************************************

int availableProcessors() {
    return runtime.availableProcessors();
    }

long milliTime() {
    return System.currentTimeMillis();
    }

long nanoTime() {
    return System.nanoTime();
    }

} // END PUBLIC CLASS

Vérifier la classe / utiliser / modifier info.olteanu.utils.TextNormalizer dans le projet Phramer ( http://sourceforge.net / projets / phramer / , www.phramer.org) -. le code est sous licence BSD

Ce code peut être compilé en Java 5 et fonctionne aussi bien en Java 5 ou Java 6 (ou futures versions Java). En outre, il peut être compilé en Java 6 et être exécuté en Java 5 (si elle a été compilé avec le bon « -target », pour la compatibilité de bytecode) ou Java 6 ou toute autre version future.

IMHO cela résout complètement votre problème - vous êtes libre de compiler sur la plate-forme Java tout, et vous êtes en mesure d'obtenir la fonctionnalité souhaitée (normalisation) sur la plate-forme Java tout (*)

(*) La solution SUN Java 5 pour la normalisation sera très probablement pas être présent sur toutes les implémentations Java 5, donc dans le scénario du pire des cas, vous finirez par obtenir un ClassNotFoundException lorsque vous appelez la méthode getNormalizationStringFilter ().

    String str = "éèà";
    try {
        Class c = Class.forName("java.text.Normalizer");
        Class f = Class.forName("java.text.Normalizer$Form");
        Field ff = f.getField("NFD");
        Method m = c.getDeclaredMethod("normalize", new Class[]{java.lang.CharSequence.class,f});
        temp = (String) m.invoke(null, new Object[]{str,ff.get(null)});
    } catch (Throwable e) {
        System.err.println("Unsupported Normalisation method (jvm <1.6)");
    }
    System.out.println(temp+" should produce [eea]");

est vieille question, mais toujours réelle. J'ai découvert quelques possibilités qui ne sont pas mentionnées dans les réponses.

En général, il est recommandé d'utiliser la réflexion comme le montre d'autres réponses ici. Mais si vous ne voulez pas mettre désordre dans votre code, vous pouvez utiliser bibliothèque icu4j . Il contient la classe com.ibm.icu.text.Normalizer avec la méthode normalize() qui effectuent le même travail que java.text.Normalizer / sun.text.Normalizer. bibliothèque ICU a (devrait avoir) propre implémentation de normalisateur afin que vous puissiez partager votre projet avec la bibliothèque et qui devrait être java indépendant.
est que la Inconvénient bibliothèque ICU est assez grand.

Si vous en utilisant la classe Normalizer juste pour enlever les accents / diacritiques de cordes, il y a aussi une autre façon. Vous pouvez utiliser Apache Commons bibliothèque lang (ver 3.) qui contient StringUtils avec la méthode stripAccents():

String noAccentsString = org.apache.commons.lang3.StringUtils.stripAccents(s);

bibliothèque Lang3 probablement utiliser la réflexion pour invoquer Normalizer approprié selon la version java. Alors avantage est que vous n'avez pas gâchis de réflexion dans votre code.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top