Java 使用超类静态方法获取子类的实例

Java 使用超类静态方法获取子类的实例,java,subclass,static-methods,superclass,Java,Subclass,Static Methods,Superclass,我有一个超类,我想将名为getInstance()的静态方法转发给所有子类 创建子类的实例时,我会在超类中注册该实例(可能使用哈希表,其中键基于getClass())。然后,我希望使用前面提到的静态方法(getInstance),其中超类方法将返回正确类型的实例 例如,我有一个超类a,子类B扩展了a。 我想写一个静态方法a.getInstance();从B(B.getInstance())调用时,我希望它返回我先前存储的B的实例 这有点难以解释,但我将经常使用这个超类,我不希望将getInsta

我有一个超类,我想将名为
getInstance()
的静态方法转发给所有子类

创建子类的实例时,我会在超类中注册该实例(可能使用哈希表,其中键基于
getClass()
)。然后,我希望使用前面提到的静态方法(
getInstance
),其中超类方法将返回正确类型的实例

例如,我有一个超类a,子类B扩展了a。 我想写一个静态方法
a.getInstance()
;从B(
B.getInstance()
)调用时,我希望它返回我先前存储的B的实例

这有点难以解释,但我将经常使用这个超类,我不希望将
getInstance
方法编码到每个子类中

我该怎么做这样的事情呢


编辑:我刚刚意识到我的问题可能被误解为创建对象的新实例。我已经创建了实例,我希望获得类的现有实例

将表单
getInstance()
更改为
getInstance(String类)
在超类中:

public static A getInstance(String class){
if(class.equals("A")){
RegisterObject(...);//User defined method
return new A(...);
}
else if(class.equals("B")){
RegisterObject(...);//User defined method
return  new B(...);
}
else if(class.equals("C")){
RegisterObject(...);//User defined method
return  new C(...);
}
//... and so on

}

正如许多其他人在评论中指出的那样,使用静态方法是不可能做到的。此外,您应该尽可能避免使用静态方法,因为它们可能导致测试和维护噩梦(*)

您将方法命名为“getInstance”,所以我想您要做的是混合使用工厂模式和单例模式。以下是一些让您开始了解这些模式的信息:

单身汉:
工厂方法:
摘要工厂:

这两种代码现在都不应该手工编写(*)-看看GoogleGuice或Spring这样的“依赖注入”(DI)容器吧。我不是100%确定您到底想要实现什么,但看起来DI容器可以为您实现这一点

编辑:这是对问题编辑的回应。您希望接收子类的缓存实例。在这种情况下,我仍然建议不要使用静态方法。您可以创建一个“BCache”类的单例实例(使用DI容器或手工编程),然后使用该缓存对象查找已注册的对象。将Guice用作DI容器时,它可能如下所示(警告,未测试):


(*)注意“所有的泛化都是错误的”,也就是说,在某些项目中它可能有意义,但在大多数项目中它不会。静态方法无法知道使用哪个类来调用它们。例如,如果在
A
中实现了扩展A和
static getInstance()
的类A和类B,那么无论是使用
A
还是
B
调用
getInstance()
都没有区别。此外,尝试调用
B.getIntance()
将产生编译警告(至少在Eclipse中是这样)

但是,您可以将该类作为
getInstance()
的参数传递:

公共A类{
公共静态getInstance(类clazz){
return clazz.newInstance();//我在这里不捕捉异常:自己做
}
}
公共类B扩展了A{
}
...............
B=A.getInstance(B.class);

用好的面向对象方法,静态方法不能完全满足您的需要。如果。。否则,如果


但是,您应该使用一些定义良好的设计模式,如或。这是你应该走的路,就像有人说的“不要发明温水”。

你可以这样做

 class A{
     public static A getInstance(){
     return new A();
   }

  @Override
  public String toString() {
   return "inside A";
   }
 }

 class B extends A{
public static A getInstance(){
  return new B();
 }

   @Override
   public String toString() {
      return "inside B";
   }
 }
内干管:

   public static void main(String[] args) {
  A a1 = A.getInstance();
  A a2 = B.getInstance();
      System.out.println(a1.toString());
  System.out.println(a2.toString());
   }

您始终可以将子类实例指定给超类引用。因此,超类的静态方法可以设置或获取子类实例。但请确保在使用之前强制转换返回的实例

public class A {
    private static A a;

    /**
     * @param a the a to set
     */
    public static void setA(A a) {
        A.a = a;
    }

    /**
     * @return the a
     */
    public static A getA() {
        return a;
    }


public class B extends A {
    private int index = 0;

    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * @return the index
     */
    public int getIndex() {
        return index;
    }
用法:

public static void main(String[] args) throws Exception {
        B b = new B();
        A.setA(b);

    B c = (B) A.getA();
    System.out.println(c.getIndex());
}

静态不知道“THIS”静态方法不是继承的。我意识到。我仍然很好奇是否有一种方法可以做到这一点,或者是否有其他方法可以实现同等价值的事情。请举个例子。摆脱这种静态方法,使用工厂。使用DI框架不会改善OP不知道“工厂”模式的事实。他应该了解这一点和一般的模式,然后决定DI框架是否有过大的杀伤力。这只是我的拙见。@Fildor你是对的,我已经在wikipedia上添加了模式描述的链接作为起点。即使有了上面的编辑,(我并不试图创建一个实例),工厂链接是否相关?@CoralineKay你在上面的评论中描述的是B类和C类的单例模式,这正好继承了A。那不是工厂,工厂可能不是你想要的。@Eloff大多数时候,它们真的很难测试。使用静态方法,您可以创建一个无法轻松替换的依赖项(用于测试或其他目的)。因此,您将调用方和被调用方紧密耦合。当你想重复使用来电者时,这经常会咬你。一个例外是纯实用程序方法:对于“Strings.notEmpty(str)”或“Arguments.notNull(argumentValue,argumentName)”之类的东西,静态方法可能是可以的。
   public static void main(String[] args) {
  A a1 = A.getInstance();
  A a2 = B.getInstance();
      System.out.println(a1.toString());
  System.out.println(a2.toString());
   }
public class A {
    private static A a;

    /**
     * @param a the a to set
     */
    public static void setA(A a) {
        A.a = a;
    }

    /**
     * @return the a
     */
    public static A getA() {
        return a;
    }


public class B extends A {
    private int index = 0;

    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * @return the index
     */
    public int getIndex() {
        return index;
    }
public static void main(String[] args) throws Exception {
        B b = new B();
        A.setA(b);

    B c = (B) A.getA();
    System.out.println(c.getIndex());
}