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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14353620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:58:35  来源:igfitidea点击:

Get instance of subclass with superclass static method

javasubclassstatic-methodssuperclass

提问by CorrieKay

I have a superclass that I would like to forward a static method called getInstance()to all subclasses.

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

When creating an instance of a subclass, I then register the instance in the superclass (perhaps using a hashtable, where the key is based on getClass()). Then, I wish to use the aforementioned static method ( getInstance) where the superclass method will return the instance of the correct type.

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

For example, I have a superclass A, and a subclass B extends A. I want to write a static method A.getInstance(); when called from B (B.getInstance()), I would like it to return the instance of B that I stored earlier.

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

Its kinda hard to explain, but I am going to be using this superclass a lot, and I would rather not code a getInstancemethod into every single subclass.

这有点难以解释,但我将大量使用这个超类,我宁愿不将getInstance方法编码到每个子类中。

How would I go about doing something like this?

我将如何去做这样的事情?

edit: I just realized that my question may be misconstrued as creating a NEW instance of the object. I have already created the instance, and i wish to get the existing instance of the class

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

回答by David Tanzer

As many others have noted in the comments, what you are trying to do is not possible with static methods. Also, you should try to avoid static methods whenever possible because they can result in a testing and maintanance nightmare (*).

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

You named your method "getInstance", so I guesswhat you want to do is a mix of Factory- and Singleton patterns. Here is some information to get you started about these patterns:

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

Singleton: http://en.wikipedia.org/wiki/Singleton_pattern
Factory Method: http://en.wikipedia.org/wiki/Factory_method_pattern
Abstract Factory: http://en.wikipedia.org/wiki/Abstract_factory

单例:http: //en.wikipedia.org/wiki/Singleton_pattern
工厂方法:http: //en.wikipedia.org/wiki/Factory_method_pattern
抽象工厂:http: //en.wikipedia.org/wiki/Abstract_factory

Both should not be coded by hand in these days (*) - Have a look at a good "Dependency Injection" (DI) container like Google Guice or Spring. I am not 100% sure what exactly you want to achieve, but it looks like a DI container will do it for you.

在这些日子里,两者都不应该手工编码 (*) - 看看一个好的“依赖注入”(DI) 容器,比如 Google Guice 或 Spring。我不是 100% 确定您到底想要实现什么,但看起来 DI 容器可以为您完成。

Edit:This is a response to an edit of the question. You want to receive a cached instance of the sub classes. In this case, I would still advise against static methods. You could create a singleton instance of a "BCache" class (using a DI container or programming it by hand), and then use this cache object to look up your registered objects. Using Guice as a DI container, it could look like this (warning, untested):

编辑:这是对问题编辑的回应。您希望接收子类的缓存实例。在这种情况下,我仍然建议不要使用静态方法。您可以创建“BCache”类的单例实例(使用 DI 容器或手动对其进行编程),然后使用此缓存对象来查找您注册的对象。使用 Guice 作为 DI 容器,它可能看起来像这样(警告,未经测试):

@Singleton
public class BCache {
    private Map<Class<? extends B>, B> cache = ...;

    public <T> T getInstance(Class<? extends T> type) {
        return (T) cache.get(type);
    }
}

I still think it would be possible to get rid of the cache class completely using a DI container, though. Again, this is untested code, using Guice, but it could look like this:

不过,我仍然认为可以使用 DI 容器完全摆脱缓存类。同样,这是使用 Guice 的未经测试的代码,但它可能如下所示:

@Singleton
public class A extends B {
    public A() {
        //I am not sure if you need to register in this case, because your
        //DI container keeps track of the singleton instances.
        super.register(this);
    }
}

public class SomeClassUsingA {
    @Inject private A a;
}

(*) Note that "all generalizations are wrong", that is, in some projects it might make sense, but in most it will not.

(*) 请注意“所有概括都是错误的”,也就是说,在某些项目中它可能有意义,但在大多数情况下则不然。

回答by partlov

You can't do exactly what you want with the static methods, in good OOP way. You can can do something with the reflection or bunch of if .. else if.

你不能用静态方法以良好的 OOP 方式做你想做的事。你可以用反射或一堆if .. else if.

You however, should use some well defined design patterns like Abstract fectoryor Factory method. This is the way you should go, like someone said "Don't invent warm water".

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

回答by spathirana

You can always assign a subClass instance to a superClass reference. Therefore your superClass's static methods can set or get a subClass instance. But make sure to cast the returned instance before using.

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

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;
    }

Usage:

用法:

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());
}

回答by Amol Fasale

You can do like this way,

你可以这样做,

 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";
   }
 }

inside main :

内部主要:

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

回答by AlexR

Static methods are cannot know which class is used to invoke them. If for example you have class A and B that extends A and static getInstance()implemented in Athere is no difference whether you invoke getInstance()using Aor B. Moreover attempt to call B.getIntance()will produce compilation warning (at least in Eclipse).

静态方法无法知道使用哪个类来调用它们。例如,如果您有类 A 和 B 扩展 A 并static getInstance()A其中实现,则调用getInstance()usingAB. 此外,尝试调用B.getIntance()会产生编译警告(至少在 Eclipse 中)。

However you can pass the class as a parameter of getInstance():

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

public class A {
    public static <T extends A> T getInstance(Class<T> clazz) {
        return clazz.newInstance(); // I do not catch exceptions here: do it yourself
    }
}

public class B extends A {
}

...............
B b = A.getInstance(B.class);

回答by Govind Balaji

Change form getInstance()to getInstance(String class)in the superclass:

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

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

}