Java: как «перезапустить» статический класс? - PullRequest
10 голосов
/ 08 января 2011

У меня есть статический класс (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 и мне нужно очистить параметры перед вторым тестом.


EDIT

ПОЧТИ РЕШЕНИЕ:

Используя ответ 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

Ответы [ 4 ]

4 голосов
/ 08 января 2011

Избегайте статического электричества.

Хорошо известно, что статическое электричество невозможно проверить, и поэтому его следует избегать.Например, избегание статичности является одним из ключевых мотивов внедрения зависимости.Если вам нужен только один экземпляр во время выполнения, используйте вместо этого шаблон синглтона.И создайте новый экземпляр для каждого запуска теста.

3 голосов
/ 08 января 2011

Только если вы можете выгрузить класс, перегрузите его, так как статический код класса выполняется при загрузке класса.

Но вы можете просто напрямую изменить значение:

Foo.i = 0;

(или создать эквивалентный метод для этого, особенно если статический член не является общедоступным)

3 голосов
/ 08 января 2011

Создайте статический метод, который устанавливает переменные класса в их начальные значения, а затем вызывайте его, когда вам это нужно.

0 голосов
/ 27 ноября 2014

Вы можете попробовать это.

Main MainObject = new Main;

MainObject.main(args);

Он будет перезапускать класс снова и снова, пока вы не остановите класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...