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

我有以下类,我正在使用它作为我项目中所有模型的基础:

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

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

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

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

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

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

我该如何克服这个问题? 如果我将一个setTable()方法添加到BaseModel,并在User的构造函数中调用setTable() ,那么table的新值是否也可用于User类的所有方法?

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

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

这将创建一个新的字段User#table ,它恰好与BaseModel#table具有相同的名称。 大多数IDE会警告你。

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

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

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

并在子类中使用它

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

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

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

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

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

输出:

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

为了做你想做的事情,不要在BaseModel中使table静态。 然后在从BaseModelinheritance的其他类中,您可以将默认构造函数中的table设置为您想要的任何内容。

 static { table = "user"; }