Wrapper classes for backward compatibility in Java

There is an interesting article about Java backward compatibility support. In the shell class section, I cannot figure out what the wrapper class does. In the following code from MyApp, WrapNewClass.checkAvailable()you can replace it with Class.forName("NewClass").

static {
    try {
        WrapNewClass.checkAvailable();
        mNewClassAvailable = true;
    } catch (Throwable ex) {
        mNewClassAvailable = false;
    }
}

Consider when NewClassunavailable. In the code where we use the shell (see below), all we did was replace the class that does not exist with the one that exists, but which cannot be compiled, since it uses a class that does not exist.

public void diddle() {
    if (mNewClassAvailable) {
        WrapNewClass.setGlobalDiv(4);
        WrapNewClass wnc = new WrapNewClass(40);
        System.out.println("newer API is available - " + wnc.doStuff(10));
    }else {
        System.out.println("newer API not available");
    }
}

Can anyone explain why this matters? I guess this has something to do with how Java compiles code, which I know little about.

+3
3

, , - , . WrapNewClass classpath javac, . .

, , WrapNewClass, mNewClassAvailable . , " API ".

, . , ​​, java.lang.reflect, , . , , .

+4

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 bad practice
        }
    }

Harder - Static Wrapper

: API, , API , . JVM.

-; , . :

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;
 * </pre>
 * <p>
 * @return          The current value of the system timer, in milliseconds.
 */
static public long getMilliTick() {
    return INSTANCE.milliTick();
    }

/**
 * 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 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;
 * </pre>
 * <p>
 * @return          The current value of the system timer, in nanoseconds.
 */
static public long getNanoTick() {
    return INSTANCE.nanoTick();
    }

} // END PUBLIC CLASS

, :

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
+3

spring richfaces. Spring, ,

  • JSF
  • private static, JSF
  • try/catch Class.forName(..) JSF
  • , ( spring )
  • , spring ( )

Note that inner classes are not loaded until they are referenced, so it’s quite normal that the dependency is not executed in it.

(Class spring org.springframework.web.context.request.RequestContextHolder)

+2
source

Source: https://habr.com/ru/post/1744867/


All Articles