Java:如何“重启”静态类?
我有一个静态类(Foo)和一个主类(Main)
请参阅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 } }
见Foo.java:
public class Foo { public static int i = 0; }
有没有办法重启或重置静态类?
注意:我需要这个,因为我正在使用jUnit测试静态类,我需要在第二次测试之前清理参数。
编辑
几乎解决方案:
使用StanMax答案,我可以这样:
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.
问题:如果我做了演员:
Foo foo = (Foo) fooClass.newInstance();
我收到错误:
java.lang.ClassCastException
只有当你可以卸载类时,才能重新加载它,因为在加载类时会执行类静态代码。
但你可以直接修改值:
Foo.i = 0;
(或创建相同的方法,特别是如果静态成员不公开)
避免静电。
众所周知,静电是不可测试的,因此应该避免。 例如,避免静态是dependency injection背后的关键动机之一。 如果仅在运行时需要一个实例,请改用单例模式。 并为每个测试运行创建一个新实例。
创建一个静态方法,将类变量设置为初始值,然后在需要时调用它。
你可以试试这个。
Main MainObject = new Main; MainObject.main(args);
它会一次又一次地重启课程,直到你停止上课。