Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在针对Java1.5优雅地降级时,如何引用Java1.6API?_Java_Graceful Degradation - Fatal编程技术网

在针对Java1.5优雅地降级时,如何引用Java1.6API?

在针对Java1.5优雅地降级时,如何引用Java1.6API?,java,graceful-degradation,Java,Graceful Degradation,我想使用Java1.6中的类来进行Unicode规范化,但我的代码必须能够在Java1.5上运行 我不介意运行在1.5上的代码是否没有进行规范化,但我不希望它在运行时给出NoClassDefFoundErrors或ClassNotFoundExceptions 实现这一目标的最佳方式是什么 public interface NfcNormalizer { public String normalize(String str); } public class IdentityNfcNorma

我想使用Java1.6中的类来进行Unicode规范化,但我的代码必须能够在Java1.5上运行

我不介意运行在1.5上的代码是否没有进行规范化,但我不希望它在运行时给出
NoClassDefFoundError
s或
ClassNotFoundException
s

实现这一目标的最佳方式是什么

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);
  }
}
在客户端代码中:

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

通常的方法是通过反射,即不直接引用所讨论的类,而是通过编程方式调用它。这允许您在相关代码不存在时优雅地捕获异常,然后忽略它,或者尝试其他方法。反射抛出
ClassNotFoundException
,这是一个很好的正常异常,而不是有点可怕的
noclassdefounderror

对于
java.text.Normalizer
,这应该很容易,因为它只是几个静态方法,并且很容易通过反射调用

我不介意运行在1.5上的代码是否没有进行规范化,但我不希望它在运行时给出NoClassDefFoundErrors或ClassNotFoundException

如果您想避免反射,实际上可以捕获这些错误

通过这种方式,您可以使用Java6编译器针对闪亮的新类进行编译,并且它仍然可以在Java5上工作(如“不做任何事情,但也不会崩溃”)

您还可以将这两种方法结合起来,检查类是否使用反射存在,以及它是否继续以非反射方式调用它。这就是安德鲁的解决方案所做的


如果您还需要在Java5上编译,那么您需要一直进行反射。

我也有同样的需求,因为我们有需要在Java 1.2的所有Java版本上运行的代码,但是有些代码需要利用更新的API(如果有)

在使用反射来获取方法对象并动态调用它们的各种排列之后,我通常选择了包装器样式的方法作为最佳方法(尽管在某些情况下,仅将反射的方法存储为静态方法并调用它会更好—这取决于具体情况)

下面是一个示例“System Utility”类,它在运行早期版本时为Java 5公开了某些较新的API—早期JVM中的Java 6也遵循同样的原则。本例使用单例,但如果底层API需要,可以轻松实例化多个对象

有两类:

  • SysUtil
  • SysUtil_J5
如果运行时JVM是Java 5或更高版本,则使用后者。否则,从SysUtil中的默认实现中使用与contract兼容的回退方法,SysUtil仅使用Java4或更早版本的API。每个类都使用特定版本的编译器进行编译,因此Java 4类中不会意外使用Java 5+API:

SysUtil(使用Java4编译器编译) 在Phramer项目(,www.Phramer.org)中检查/使用/修改类-代码是BSD许可的

这些代码可以在Java5中编译并在Java5或Java6(或未来的Java版本)中运行。此外,它可以在Java6中编译,也可以在Java5中运行(如果为了字节码兼容性而使用适当的“-target”进行编译),或者在Java6或任何其他未来版本中运行

IMHO这完全解决了您的问题-您可以在任何Java 5+平台上自由编译,并且可以在任何Java 5+平台(*)上获得所需的功能(规范化)

(*)SUN Java 5规范化解决方案很可能不会出现在所有Java 5实现中,因此在最坏的情况下,当您调用getNormalizationStringFilter()方法时,您将得到ClassNotFoundException; 试一试{ Class c=Class.forName(“java.text.Normalizer”); Class f=Class.forName(“java.text.Normalizer$Form”); 字段ff=f.getField(“NFD”); 方法m=c.getDeclaredMethod(“normalize”,新类[]{java.lang.CharSequence.Class,f}); temp=(String)m.invoke(null,新对象[]{str,ff.get(null)}); }捕获(可丢弃的e){
System.err.println(“不支持的规范化方法(jvm)这是一个老问题,但仍然是实际问题。我发现了一些答案中没有提到的可能性

通常建议使用反射,如其他一些答案所示。但如果您不想让代码变得混乱,可以使用。它包含
com.ibm.icu.text.Normalizer
类和
normalize()
方法,这些方法执行与java.text.Normalizer/sun.text.Normalizer.icu库相同的任务(应该有)拥有Normalizer的实现,这样您就可以与库共享您的项目,并且应该是独立于java的。
缺点是icu图书馆很大

如果您使用Normalizer类只是为了从字符串中删除重音符号/变音符号,还有另一种方法。您可以使用包含
StringUtils
的方法
stripeAccents()


Lang3库可能会根据java版本使用反射来调用适当的规范化程序。因此,优点是您的代码中没有反射混乱。

这并不能直接回答您的问题,但如果您想在java 5上实现规范化,请使用ICU项目libs:@simonn:See,以获取可能满足您需要的代码。
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
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
    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]");
String noAccentsString = org.apache.commons.lang3.StringUtils.stripAccents(s);