Я давно нуждался в поддержке каждой JVM начиная с версии 1.1 в JSE, и я использовал этот вид методов обертывания для совместимой поддержки дополнительных API-интерфейсов, то есть API-интерфейсов, которые улучшают работу приложения, но не являются необходимыми для него.
Кажется, что две техники, которые я использую, (плохо?) Описаны в статье, на которую вы ссылались. Вместо того, чтобы комментировать дальше, я приведу реальные примеры того, как я это сделал.
Самый простой - метод статической обертки
Необходимость: вызывать API, если он доступен, или иным образом ничего не делать. Это может быть скомпилировано для любой версии JVM.
Сначала настройте статический Method
с отраженным методом, например:
static private final java.lang.reflect.Method SET_ACCELERATION_PRIORITY;
static {
java.lang.reflect.Method mth=null;
try { mth=java.awt.Image.class.getMethod("setAccelerationPriority",new Class[]{Float.TYPE}); } catch(Throwable thr) { mth=null; }
SET_ACCELERATION_PRIORITY=mth;
}
и обернуть отраженный метод вместо прямого вызова:
static public void setImageAcceleration(Image img, int accpty) {
if(accpty>0 && SET_ACCELERATION_PRIORITY!=null) {
try { SET_ACCELERATION_PRIORITY.invoke(img,new Object[]{new Float(accpty)}); }
catch(Throwable thr) { throw new RuntimeException(thr); } // exception will never happen, but don't swallow - that's bad practice
}
}
Сложнее - класс статической обертки
Необходимость: вызывать API, если он доступен, или иным образом вызывать более старый API для эквивалентной, но ухудшенной функциональности. Это должно быть скомпилировано с более новой версией JVM.
Сначала настройте статический класс-оболочку; это может быть статическая одноэлементная оболочка, или вам может понадобиться обернуть каждый экземпляр создания. В следующем примере используется статический синглтон:
<code>package xxx;
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();
}
/** 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 milliTick() {
return System.currentTimeMillis();
}
/** Package protected to allow subclass SysUtil_J5 to override it. */
long nanoTick() {
return (System.currentTimeMillis()*1000000L);
}
// *****************************************************************************
// STATIC PROPERTIES
// *****************************************************************************
static private final SysUtil INSTANCE;
static {
SysUtil instance=null;
try { instance=(SysUtil)Class.forName("xxx.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 value of the most precise available system timer, in milliseconds.
* <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 milliseconds since some fixed but arbitrary time (perhaps in the future, so
* values may be negative). This method provides millisecond precision, but not necessarily millisecond accuracy. No
* guarantees are made about how frequently values change. Differences in successive calls that span greater than
* approximately 292,000 years 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.getNanoTick();
* // ... the code being measured ...
* long estimatedTime = SysUtil.getNanoTick() - startTime;
*
*
* @return Текущее значение системного таймера в миллисекундах.
* /
static public long getMilliTick () {
return INSTANCE.milliTick ();
}
/ **
* Возвращает текущее значение наиболее точного доступного системного таймера в наносекундах.
*
* Этот метод может использоваться только для измерения прошедшего времени и не связан с какими-либо другими понятиями системы или настенных часов
* время Возвращаемое значение представляет наносекунды с некоторого фиксированного, но произвольного времени (возможно, в будущем, поэтому значения
* может быть отрицательным). Этот метод обеспечивает точность наносекунды, но не обязательно точность наносекунды. Нет гарантий
* сделаны о том, как часто значения меняются. Различия в последовательных вызовах, превышающие приблизительно 292
* годы не будут точно рассчитывать истекшее время из-за числового переполнения.
*
* Например, чтобы измерить, сколько времени занимает выполнение кода:
*
* long startTime = SysUtil.getNanoTick();
* // ... the code being measured ...
* long estimatedTime = SysUtil.getNanoTick() - startTime;
*
*
* @return Текущее значение системного таймера в наносекундах.
* /
static public long getNanoTick () {
return INSTANCE.nanoTick ();
}
} // КОНЕЦ ОБЩЕСТВЕННОГО КЛАССА
и создайте подкласс для предоставления новых функциональных возможностей, если они доступны:
package xxx;
import java.util.*;
class SysUtil_J5
extends SysUtil
{
private final Runtime runtime;
SysUtil_J5() {
super();
runtime=Runtime.getRuntime();
}
int availableProcessors() {
return runtime.availableProcessors();
}
long milliTick() {
return (System.nanoTime()/1000000);
}
long nanoTick() {
return System.nanoTime();
}
} // END PUBLIC CLASS