【问题标题】:How to change the class of an object without creating a new one?如何在不创建新对象的情况下更改对象的类?
【发布时间】:2014-06-09 23:51:46
【问题描述】:

假设我有一个类 Foo,还有两个类 Foo1 和 Foo2 扩展了 Foo。

假设我有一个 Foo f,结果是一个 Foo1,我想在不使用构造函数的情况下更改它。如果只是改变 f 的字段,我可以手动完成:

f.field1= ..
f.field2= ..

但是,如果我想将其更改为 Foo2 该怎么办?

NB:关键是我想做这样的事情:

Foo f=new Foo1( ...);
Foo g=f;
g=new Foo2(...);

并且当g改变时让f改变,但显然这不起作用。

【问题讨论】:

  • 您无法更改 Java 中的内容。你只能做不同的事情。
  • 也许您想详细说明一下?如果你做 Foo1 f1 = new Foo1();富 g=f1;然后像 g.setSomething("val") 这样的东西 - 这会改变 g 和 f1。我不确定你为什么在那里有 g = new Foo2() 以及在这种情况下“当 g 改变时改变 f”是什么意思。
  • 我想让f和g变成Foo2,这是g.setSomething("...")做不到的

标签: java


【解决方案1】:

您可能可以围绕这些线做点什么。注意:此代码为伪代码。

abstract class Common{
...
}

class Foo{
  private Common currentReference;

  public Foo(...){
    currentReference = new Foo1();
  }

  public Foo changeReferenceToClass(Class clazz){
    ...
    currentReference = clazz.newInstance();
    ...
    return this;
  }

  public <T extends Common> T getReference()
  {
    return (T) currentReference;
  }
}

class Foo1 extends Common{
...
}

class Foo2 extends Common{
...
}

Foo f=new Foo( ... );
Foo g=f;
g=g.changeReferenceToClass(Foo2.class);

这是做什么的:

  • 创建一个类,其中包含对具有common 接口的对象的引用(在示例中为Common 抽象类。
  • 在构造时实例化对默认值的引用(示例中为Foo1)。
  • 提供changeget 参考的方法。
  • 当您在一处将引用更改为 Foo2 时,您可以在所有地方访问它

在示例中,当您将 g 更改为持有对 Foo2 的引用时,f 也将持有对 Foo2 的引用。

【讨论】:

    【解决方案2】:

    注意Java是static typed programming languagestrong typed,所以除非Foo2Foo的子类,否则它不会工作。但即使这样做,您也只能更改变量的对象引用类型(并启用多态性),而不是变量的类型。

    【讨论】:

    • 我怀疑这是因为 Java 是静态类型的。它可以是动态类型的,您仍然无法更改对象的类。类型系统是在运行时起作用的东西,编译器只是帮助遵循类型系统的规则。
    • @EdwinDalorzo 我忘了补充一点,Java 也是强类型的。
    【解决方案3】:

    你不能在 Java 中这样做,因为你声明它的类型是你被限制的类型。这就是静态类型的工作原理。也就是说你可以这样做:

    Foo g = new Foo2();
    ((Foo2)g).gInstanceMethod();
    

    【讨论】:

      【解决方案4】:

      其他人已经解释了为什么您不能更改现有对象的类。但即使可以,由于 Java 引用的工作方式,您尝试做的事情也行不通。

       Foo f=new Foo1( ...);
      

      这一行在堆上分配一个新对象,调用Foo1构造函数对其进行初始化,并将对该对象的引用存储在变量f中。

       Foo g=f;
      

      这一行复制引用的(即复制地址,而不是被引用的对象)到一个新变量g

       g=new Foo2(...);
      

      这一行在堆上分配一个新对象,调用Foo2构造函数对其进行初始化,并将一个对新对象的引用存储到g中,覆盖之前存储的引用那里。 g 之前引用的对象永远不会受到此操作的影响。

      【讨论】:

        猜你喜欢
        • 2012-04-14
        • 1970-01-01
        • 2022-11-30
        • 2021-08-06
        • 2020-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多