Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 抽象类中的静态方法_Java_Oop_Inheritance_Static - Fatal编程技术网

Java 抽象类中的静态方法

Java 抽象类中的静态方法,java,oop,inheritance,static,Java,Oop,Inheritance,Static,我想这样定义一个抽象方法: public abstract class Saveable { public Set<Field> getFieldSet(); ... } 公共抽象类可保存{ 公共集getFieldSet(); ... } 无论对象的状态如何,getFields()都应始终返回相同的输出。但是,我不能将其声明为静态方法,因为我希望它被重写。现在我正在实现一个类User,它扩展了Saveable,并且它有一些需要字段集的静态方法。很明显,我拿不到它,

我想这样定义一个抽象方法:

public abstract class Saveable {
    public Set<Field> getFieldSet();
    ...
}
公共抽象类可保存{
公共集getFieldSet();
...
}

无论对象的状态如何,
getFields()
都应始终返回相同的输出。但是,我不能将其声明为静态方法,因为我希望它被重写。现在我正在实现一个类
User
,它扩展了
Saveable
,并且它有一些需要字段集的静态方法。很明显,我拿不到它,因为我没有物体。关于允许我在静态方法中获取字段的设计有什么想法吗?

不幸的是继承的类不能覆盖静态方法,但它可以通过声明具有相同签名的静态方法来隐藏它


如果您的最终目的是在
Saveable
类中的另一个继承方法中使用
GetFields()
,则这对您没有帮助,因为它将始终调用
Saveable.GetFields()
,不是扩展类中的静态方法。

您可以将当前方法保留为非静态且抽象的可保存方法,并返回非静态实现的静态集合

public class User extends Savable {

    public static Set<AField> aSet = new HashSet<AField>();

    @Override
    public Set<? extends Field> getFields() {
        return aSet;
    }
}
公共类用户扩展可存储{
public static Set aSet=new HashSet();
@凌驾
publicset一种方法是通过将正确对象的实例传递给静态方法,然后对该对象调用
getFields
,从而“伪造”该
引用

另一个选项是将字段列表存储在类的静态字段中。重写的
getFields()
实现可以返回它(或者最好是它的副本),静态方法可以直接访问它


我更倾向于实现后一个选项,因为它不那么笨拙(因为你永远不必重新创建一个无用的对象来传递给静态方法)。此外,它捕获了这样一个想法,即类的字段不依赖于给定的实例。

当调用静态方法时,你调用的是类的名称作为作用域

因此,实际上没有覆盖的意义,你只是在隐藏它

此外,由于同样的原因,它不能被继承,因为它属于类类型,而不是类实例


最好是在派生类中调用基类的静态方法,并使用相同的方法名。

扩展@dlev的答案,将字段存储在一个哈希映射中,该哈希映射由每个类的唯一标识符设置


如果您使用的是Spring,那么您可以在每个对象中注入字段集。因此,只有引用会被复制。

这是我的建议,我得出结论。但是您必须以某种方式命名派生类名,在加载这些字段时,除了声明静态方法之外,没有其他方法

public abstract class Saveable {
    public static Set<? extends Field> getFields(Class<? extends Saveable> clazz) {
        return FieldsProvider.get(clazz);
    }
}

public class FieldsProvider {
    private static final Map<Class<? extends Saveable>, Set<? extends Field>> map =
        new HashMap<Class<? extends Saveable>, Set<? extends Field>>();

public static void registerFields(Class<? extends Saveable> clazz, Collection<? extends Field> col) {
    Set<? extends Saveable> set = new HashSet<? extends Saveable>();
    set.addAll(col);
    map.put(clazz, set);
}

public static Set<? extends Field> getFieldSet(Class<? extends Saveable> clazz) {
    Set<? extends Field> set = map.get(clazz);
    if (set != null) {
        return set;
    }
    return Collections.emptySet();
}
}

public class User extends Saveable {
static {
    FieldsProvider.registerFields(User.class, new HashSet<? extends Field>... ;
}

static void someMethod() {
    Set<? extends Field> fieldsSet = getFields(User.class);
    ...
}
}
公共抽象类可保存{

公共静态集他知道这一点,因为他说“但是,我不能将其声明为静态方法,因为我希望它被重写。”这不是一个有用的答案。它们是继承的,但不是虚拟iirc。@如果您有
specificsavable扩展Saveable
getFields()
将是静态的,
SpecificSaveable.getFields()
有效吗?是的,谢谢,我阅读了文档,我将更新我的答案。鉴于您明确指出“
getFields()
应该始终返回相同的输出,而不管对象的状态如何”,它们引用的字段可能应该是静态的(可能是最终的)无论如何。如果您确实需要额外的分离,您可以编写一个额外的、静态的,
getFields()
方法,您可以调用非静态版本(和其他静态方法)。否则,我可能会选择@dlev提供的答案。