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
Java: Overriding static variable of parent class?
提问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 table
field in the User
class 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 table
be available to all methods of the User
class 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#table
that 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 BaseDAO
class 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 table
static in the BaseModel
. Then in the other classes that inherit from BaseModel
, you can set table
in the default constructor to whatever you wish.
为了做你想做的事情,不要table
在BaseModel
. 然后在继承自 的其他类中BaseModel
,您可以将table
默认构造函数设置为您希望的任何内容。
static {
table = "user";
}
回答by Erik Kaplun
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