Java:如何“重新启动”静态类?

发布于 2024-10-11 03:22:19 字数 2828 浏览 2 评论 0原文

我有一个静态类 (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.");
    }


}

输出

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤蝉 2024-10-18 03:22:19

仅当您可以卸载类时,才重新加载它,因为类加载时会执行类静态代码。

但您可以直接修改该值:(

Foo.i = 0;

或创建等效方法来执行此操作,特别是如果静态成员不是公共的)

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)

和我恋爱吧 2024-10-18 03:22:19

创建一个静态方法,将类变量设置为其初始值,然后在需要时调用它。

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

九公里浅绿 2024-10-18 03:22:19

避免静电。

众所周知,静态是不可测试的,因此应该避免。例如,避免静态是依赖注入背后的关键动机之一。如果您仅在运行时需要一个实例,请改用单例模式。并为每次测试运行创建一个新实例。

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.

想你只要分分秒秒 2024-10-18 03:22:19

你可以试试这个。

Main MainObject = new Main;

MainObject.main(args);

它将一次又一次地重新启动课程,直到您停止课程。

You can try this.

Main MainObject = new Main;

MainObject.main(args);

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文