Mam klasy statycznej (foo) i główne klasy (główny)Java: jak "zrestartować" klasę statyczną?
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;
}
Czy istnieje jakiś sposób, aby zrestartować lub zresetować klasę statyczną?
Uwaga: Potrzebuję tego, ponieważ testuję klasę statyczną z jUnit i muszę wyczyścić parametry przed drugim testem.
EDIT
PRAWIE ROZWIĄZANIE:
Korzystanie StanMax odpowiedź, mogę do tego:
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.");
}
}
WYJŚCIE
test()
Foo - BEGIN ---------------------------------
Checking classloader: [email protected]
GC called!
MyClassLoader - End.
Foo - End.
test()
Foo - BEGIN ---------------------------------
Checking classloader: [email protected]
GC called!
MyClassLoader - End.
Foo - End.
PROBLEM: jeśli robię obsady poniżej:
Foo foo = (Foo) fooClass.newInstance();
otrzymuję błąd:
java.lang.ClassCastException
Dla tego konkretnego przykładu po prostu wykonaj 'Foo.i = 0;' wewnątrz twojej metody 'Main'. – LukeH
Masz wyjątek ClassCastException, ponieważ klasa Foo załadowana przez obiekt URLClassLoader różni się od klasy Foo ładowanej przez klasę ClassLoader, na której działa kod (nie są ==). Nawet jeśli mają dokładnie taką samą definicję, nie można rzutować jednego na drugi. Jedyny sposób działania tego rodzaju sztuczki polega na tym, że Foo implementuje interfejs FooInterface, który jest ładowany przez klasę ClassLoader, która jest współdzielona między dwa programy ładujące klasy, w którym to przypadku można rzutować na FooInterface. Ale to nie ułatwia dostępu do pól statycznych. – NamshubWriter
NamshubWriter: ok, Zrobiłem to ... ale głównym problemem jest to, że używam typu dynamicznego ... Dostaję "fooClass nie może być rozwiązany na typ". Może coś w Refletion API może pomóc .... – Topera