Java: how to “restart” a static class?

2019-01-15 13:30发布

I have a static class (Foo) and a main class (Main)

See Main.java:

public class Main {

    public static void main(String[] args) {
        System.out.println(Foo.i); // 0
        Foo.i++;
        System.out.println(Foo.i); // 1
        // restart Foo here 
        System.out.println(Foo.i); // 1 again...I need 0
    }

}

See Foo.java:

public class Foo {

    public static int i = 0;

}

Is there any way to restart or reset a static class?

Note: I need this because I'm testing a static class with jUnit and I need to clean parameters before second test.


EDIT

ALMOST SOLUTION:

Using StanMax answer, I can to this:

Main.java

public class Main {

    public static void main(String[] args) throws Exception {
        test();
        test();
    }

    public static void test() throws Exception {

        System.out.println("\ntest()");

        MyClassLoader myClassLoader = new MyClassLoader();
        Class<?> fooClass = myClassLoader.loadClass(Foo.class.getCanonicalName());

        Object foo = fooClass.newInstance();
        System.out.println("Checking classloader: " + foo.getClass().getClassLoader());

        System.out.println("GC called!");
        System.gc();
    }

}

MyClassLoader.java

public class MyClassLoader {

    private URLClassLoader urlClassLoader;

    public MyClassLoader() {
        try {
            URL url = new File(System.getProperty("user.dir") + "/bin/").toURL();
            URL[] urlArray = {url};  
            urlClassLoader = new URLClassLoader(urlArray, null);  
        } catch (Exception e) {
        }
    }

    public Class<?> loadClass(String name) {
          try {
            return (Class<?>) urlClassLoader.loadClass(name);
        } catch (Exception e) {
        }
        return null;
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("MyClassLoader - End.");     
    }


}

Foo.java

public class Foo {

    public static int i = 0;

    static {
        System.out.println("Foo - BEGIN ---------------------------------");
    }

    public void finalize() throws Throwable {
        System.out.println("Foo - End.");
    }


}

OUTPUT

test()
Foo - BEGIN ---------------------------------
Checking classloader: java.net.URLClassLoader@ec160c9
GC called!
MyClassLoader - End.
Foo - End.

test()
Foo - BEGIN ---------------------------------
Checking classloader: java.net.URLClassLoader@ec3fb9b
GC called!
MyClassLoader - End.
Foo - End.

PROBLEM: if I do the cast bellow:

Foo foo = (Foo) fooClass.newInstance();

I get error:

java.lang.ClassCastException

4条回答
Rolldiameter
2楼-- · 2019-01-15 14:17

You can try this.

Main MainObject = new Main;

MainObject.main(args);

It will restart the class again and again until you stop the class.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-01-15 14:20

Only if you can unload class, get it re-loaded, as class static code gets executed when class is loaded.

But you can just directly modify the value:

Foo.i = 0;

(or create equivalent method for doing it, esp. if static member is not public)

查看更多
smile是对你的礼貌
4楼-- · 2019-01-15 14:32

Avoid static.

It is well known that static is not testable and should thus be avoided. For example, avoiding static is one of the key motivations behind dependency injection. If you need one instance only at runtime, use the singleton pattern instead. And create a new instance for each test run.

查看更多
我命由我不由天
5楼-- · 2019-01-15 14:33

Create a static method that sets the class variables to their initial values, then call it when you need it.

查看更多
登录 后发表回答