Java 获取子类';静态数据

Java 获取子类';静态数据,java,class,subclass,Java,Class,Subclass,我有一个类Player,需要获得一个位置类。每个location类都扩展了location,它有一个返回静态实例的方法get() 如果该字符有一个引用位置扩展类名称的字符串,如何获取实例 人物: public class Player { public static Location getLocation() { try { //return location } catch (Exception ex) {

我有一个类
Player
,需要获得一个
位置
类。每个location类都扩展了
location
,它有一个返回静态实例的方法
get()

如果该字符有一个引用位置扩展类名称的字符串,如何获取实例

人物:

public class Player {
    public static Location getLocation() {
        try {
            //return location
        } catch (Exception ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
}
地点:

public class Location{
    protected static Location singleton;
    public static Location get() {
        return null;
    }
地点类别:

public class Finleydale extends Location{
    public static Location get() {
        if (Finleydale.singleton == null) {
            Finleydale.singleton = new Finleydale();
        }
        return singleton;
    }
}
我有多个location扩展,location类中有singleton,所以所有location扩展都有它;而单例是静态的,因为只有一个版本的位置。
有人能帮我吗?

您在基类中声明静态字段的方式意味着您在整个程序中只有一个引用。如果您有多个子类,并且每个子类都分配给它,那么每个子类都分配给
位置
基类中的相同(静态)字段。我认为您希望在每个子类中都有一个单独的单例

如果您想通过键(比如字符串值)查找特定位置,那么我认为单例模式并不是您想要的。我将创建一个“location registry”类,如下所示:

public class LocationRegistry
    {
    private static final Map<String, Location> registry;
    static
        {
        final Map<String, Location> _registry = new HashMap<>();
        _registry.put("Finleydale", new Finleydale());
        // ...
        registry = Collections.unmodifiablemap(_registry);
        }

    public static Location getLocation(final String id)
        {
        return registry.get(id);
        }
    }
公共类位置注册表
{
私有静态最终地图注册表;
静止的
{
final Map_registry=new HashMap();
_registry.put(“Finleydale”,new Finleydale());
// ...
registry=Collections.unmodifiablemap(_registry);
}
公共静态位置getLocation(最终字符串id)
{
返回registry.get(id);
}
}
一些注意事项:

  • 您仍然可以使用单例模式来填充注册表
  • 正如您在问题中所演示的,经典的单例模式不是线程安全的。如果不是不可能的话,没有不必要的锁定的线程安全版本是非常棘手的。
    静态final
    字段很好地解决了这个问题
  • 没有必要让注册表显式引用每个Location子类。您可以让每个位置注册自己。唯一的诀窍是使用一种机制来加载这些位置,以便它们可以自己注册
  • 子类是否确实适合此用途?不同的位置是否有不同的行为或只是不同的数据(即名称)?如果是后者,那么我将只使用一个Location类和一个factory(如上面的静态初始值设定项)来创建每个位置

您的对象模型似乎有问题。为什么不在接口
Locatable
上使用
getLocation()
方法,接口的实现者可以返回各自的位置呢。单例
位置
在概念上似乎是错误的

interface Locatable { 
   Location getLocation();
}

class FinleyLand implements Locatable { 
    @Override
    Location getLocation() { 
       //whatever it takes to get you there...
    }     
}
我去掉了get()函数的静态修饰符,并更改了Player类,如图所示。
所有其他人,您的输入都很棒

    String locationS; //Class name
    public static Location getLocation() {
        return ((Location) Class.forName(locationS).newInstance()).get();
    }

唷,谢谢你的编辑@hovercraftfullofels。抱歉,我不习惯这篇帖子。我看不到会引发异常,所以你想捕获什么?
如何从字符串中获取该实例。
我不清楚你在这里试图实现什么,但你不能真正“覆盖”静态方法,但看起来您正在尝试这样做?静态意味着该类的所有实例将共享同一个字段,因此在基类中使用
静态位置单例
很可能会导致严重问题-所有子类将共享同一个实例。@Makoto Netbeans给了我一个错误。好主意,我会仔细考虑,然后告诉你我的想法。location类中还有其他方法,我只是省略了它们,因为它们不能直接关联。好的-将它们提取到接口中。如果您不是针对接口编程,那么您的对象模型往往更脆弱。您所说的“针对接口”是什么意思?对不起,这是措词不当的。我的意思是,如果你能提取出你程序中的行为模式,你就能创造出更多可重用、可分解的代码,这些代码隐藏了丑陋的细节。阅读Josh Bloch的高效Java,看看我的建议。