简体   繁体   English

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

[英]Java: Overriding static variable of parent class?

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 = ?"然后,而不是查询: "SELECT id FROM user WHERE id = ?" , it is producing the query: "SELECT id from null WHERE id = ?". ,它正在生成查询:“SELECT id from null WHERE id = ?”。 So, the overriding of the table field in the User class doesn't seem to be having any effect.因此,覆盖User类中的table字段似乎没有任何效果。

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 table be available to all methods of the User class as well?如果我在 BaseModel 中添加了一个setTable()方法,并在User的构造函数中调用了setTable() ,那么table的新值是否也可用于User类的所有方法?

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#table that just happens to have the same name as BaseModel#table .这将创建一个新字段User#table恰好与BaseModel#table同名。 Most IDEs will warn you about that.大多数 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 BaseDAO class and have a UserDAO (one for each model class) that sets the field accordingly.如果您想使用字段方法,您必须创建一个BaseDAO类并拥有一个相应地设置字段的UserDAO (每个模型类一个)。 Then you create singleton instances of all the daos.然后创建所有 daos 的单例实例。

Because Java doesn't allow you to override static members, 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

In order to do what you are looking to do, don't make table static in the BaseModel .为了做你想做的事,不要在BaseModel中使table成为静态的。 Then in the other classes that inherit from BaseModel , you can set table in the default constructor to whatever you wish.然后在从BaseModel继承的其他类中,您可以将默认构造函数中的table设置为您想要的任何内容。

static {
    table = "user";
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM