【问题标题】:Problems with inheritance of static variables in JavaJava中静态变量的继承问题
【发布时间】:2014-11-15 12:00:01
【问题描述】:

我有三个无法修改的类。简而言之,我有一个类 Program,以及其他两个类 ProgramClient 和 ProgramServer,它们继承自 Program。 Program 类有一个静态变量。

到目前为止,我在两个不同的应用程序中运行 ProgramClient 和 ProgramServer,没有任何问题。 现在我需要在同一个应用程序中运行这两个类。这样做,他们共享父类的静态变量,因此发生了不好的事情。

我怎样才能将这两个类保留在它们自己的“上下文”(JVM?)中,以确保静态变量仅由其中一个子类使用?

【问题讨论】:

  • 在单独的虚拟机中运行每个?这有什么问题?
  • 我认为您的 OO 概念/设计在这一点上没有得到正确考虑。如果 2 个类从一个超类继承,你总是必须应用 is-a-rule(从你的类名来看似乎是这样)但是如果你在超类中有静态字段,它们应该是相同的子类。最好的办法是将静态字段移动到子类中而不是继承它。如果子类在这个变量中应该有不同的值,那么从超类继承它是错误的设计方式
  • 这不是有点违背静态变量的观点吗?
  • @MuhammadHamed 是的,我认为这是正确的做法,但我不知道该怎么做,因为这两个类是同一个应用程序(eclipse 项目)的一部分。你能解释一下怎么做吗?
  • @gutenmorgenuhu 我同意你的观点,但正如我所写,我无法修改类

标签: java inheritance static-members


【解决方案1】:

静态变量,根据定义,不能在类之间覆盖或复制。

然而,这两个类可以通过使用两个独立的类加载器来分隔,它们没有被链接。这正是 J2EE 容器提供者在 Web 应用程序之间分离的方式。

换句话说,您会将基类Program 加载到JVM 中两次,然后将它们分开沙箱。从而为每个单独的“程序”提供自己的实例。可以了解更多关于类加载器的信息here

这是一个非常简单的示例引导程序。当您启动java 命令时,请确保ProgramClientProgramServer 的代码不在系统类路径中。您还需要将 url 更改为包含目标程序代码的 jar 文件。

public class Bootstrap  {
    public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        URLClassLoader cl1 = new URLClassLoader(
                new URL[] {
                        new URL("file:///client.jar")
                },
                Bootstrap.class.getClassLoader()

        );

        URLClassLoader cl2 = new URLClassLoader(
                new URL[] {
                        new URL("file:///server.jar")
                },
                Bootstrap.class.getClassLoader()
        );

        invokeAsync(cl1, "a.b.c.ProgramClient");
        invokeAsync(cl2, "a.b.c.ProgramServer");
    }

    private static void invokeAsync(final ClassLoader cl, final String fqn, final String...progArgs) {
        new Thread() {
            public void run() {
                try {
                    Class p1 = cl.loadClass(fqn);
                    Class argType = String[].class;

                    Method m = p1.getMethod("main", argType);

                    m.invoke(null, (Object) progArgs);
                } catch ( Exception e ) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

}

【讨论】:

  • 在我调用 ProgramClient.run() 和 ProgramServer.run() 来获得这个效果之前,你能不能给我一个例子来说明我应该写什么?
  • @ssnape 我添加了一个简单的示例。请注意,它将对您运行它的环境敏感,特别是系统类路径。但这应该足以让您入门。
  • 谢谢你的回答很清楚。但是我仍然有问题,我想是因为ProgramClientProgramServer 使用了第三类的静态成员Common。你能解释一下我应该怎么做吗?
  • @ssnape 如果您将类加载器配置为不共享第三个类,则该第三个类将被加载两次。因此不会发生冲突。您的问题很可能与类路径有关,请确保任一程序中的任何类都不在其上。只有引导程序应该是。
【解决方案2】:

没有继承或覆盖静态方法或变量,因为在所有程序中只有一个引用。那目标如果是静态的。 也许你必须为每个程序类创建一个实例化的上下文类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-28
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    相关资源
    最近更新 更多