Java:覆盖父类的静态变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19457114/
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-08-12 17:23:05  来源:igfitidea点击:

Java: Overriding static variable of parent class?

javaoopstaticstatic-members

提问by Click Upvote

I have the following class which I'm using as the base of all the models in my project:

我有以下类,我将其用作项目中所有模型的基础:

public abstract class BaseModel
{
    static String table;
    static String idField = "id";       

    public static boolean exists(long id) throws Exception
    {
        Db db = Util.getDb();
        Query q = db.query();
        q.select( idField ).whereLong(idField, id).limit(1).get(table);

        return q.hasResults();
    }

    //snip..
}

I'm then trying to extend from it, in the following way:

然后我试图通过以下方式扩展它:

public class User extends BaseModel
{
    static String table = "user";
    //snip
}

However, if I try to do the following:

但是,如果我尝试执行以下操作:

if ( User.exists( 4 ) )
   //do something

Then, rather than the query: "SELECT id FROM user WHERE id = ?", it is producing the query: "SELECT id from null WHERE id = ?". So, the overriding of the tablefield in the Userclass doesn't seem to be having any effect.

然后,而不是查询:"SELECT id FROM user WHERE id = ?",它生成查询:“SELECT id from null WHERE id = ?”。因此,类中的table字段的覆盖User似乎没有任何效果。

How do I overcome this? If I added a setTable()method to BaseModel, and called setTable()in the constructor of User, then will the new value of tablebe available to all methods of the Userclass as well?

我如何克服这个问题?如果我setTable()向 BaseModel添加了一个方法,并setTable()在 的构造函数中调用User,那么该类的table所有方法都可以使用的新值User吗?

采纳答案by Cephalopod

You cannot override static methods or fields of any type in Java.

您不能覆盖 Java 中任何类型的静态方法或字段。

public class User extends BaseModel
{
    static String table = "user";
    //snip
}

This creates a new field User#tablethat just happens to have the same name as BaseModel#table. Most IDEs will warn you about that.

这会创建一个新字段User#table,该字段恰好与BaseModel#table. 大多数 IDE 会对此发出警告。

If you change the value of the field in BaseModel, it will apply to all other model classes as well.

如果您更改 BaseModel 中字段的值,它也将适用于所有其他模型类。

One way is to have the base methods generic

一种方法是让基本方法通用

protected static boolean exists(String table, long id) throws Exception
{
    Db db = Util.getDb();
    Query q = db.query();
    q.select( idField ).whereLong(idField, id).limit(1).get(table);

    return q.hasResults();
}

and use it in the subclass

并在子类中使用它

public static boolean exists(long id)
{
    return exists("user", id);
}

If you want to use the field approach, you have to create a BaseDAOclass and have a UserDAO(one for each model class) that sets the field accordingly. Then you create singleton instances of all the daos.

如果你想使用字段方法,你必须创建一个BaseDAO类并有一个UserDAO(每个模型类一个)相应地设置字段。然后创建所有 daos 的单例实例。

回答by Brian Dishaw

In order to do what you are looking to do, don't make tablestatic in the BaseModel. Then in the other classes that inherit from BaseModel, you can set tablein the default constructor to whatever you wish.

为了做你想做的事情,不要tableBaseModel. 然后在继承自 的其他类中BaseModel,您可以将table默认构造函数设置为您希望的任何内容。

static {
    table = "user";
}

回答by Erik Kaplun

Because Java doesn't allow you to override staticmembers, you basically need to resort to the slightly more verbose but overall nicer singleton pattern, wherein you're still conceptually writing "static" code, but you're technically using (global/singleton/"static") instances, so you're not restricted by the limitations of static.

因为 Java 不允许您覆盖static成员,所以您基本上需要求助于稍微冗长但整体更好的单例模式,其中您仍然在概念上编写“静态”代码,但您在技术上使用 (global/singleton/ "static") 实例,因此您不受static.

(note that you also need to use methods because fields don't participate in polymorphism, and thus cannot be overridden)

(请注意,您还需要使用方法,因为字段不参与多态,因此不能被覆盖)

public abstract class BaseTable {
    public abstract String table();
    public String idField() { return "id"; }

    public boolean exists(long id) {
        // don't build queries this way in real life though!
        System.out.println("SELECT count(*) FROM " + table() + " WHERE " + idField() + " = " + id);
        return true;
    }
}

public class UserTable extends BaseTable {
    public static final User INSTANCE = new UserTable();
    private UseTabler() {}

    @Override public String table() { return "user"; }
}

public class PostTable extends BaseTable {
    public static final Post INSTANCE = new PostTable();
    private PostTable() {}

    @Override public String table() { return "post"; }
}

public static void main(String[] args) {
    UserTable.INSTANCE.exists(123);
    PostTable.INSTANCE.exists(456);
}

Outputs:

输出:

SELECT count(*) FROM user WHERE id = 123
SELECT count(*) FROM post WHERE id = 456