关于java:使用interface(RIGHT / WRONG)导入最终字段

importing final fields using interface (RIGHT/WRONG)

本问题已经有最佳答案,请猛点这里访问。

最近我在某人的代码中看到,他在一个接口ex中实现了他的最后一个类变量字段:

1
2
3
4
public interface commentSchema{
  static final String DB_TABLE_NAME ="comment";
  ...
}

&他实现了一个类,该类确实需要这些变量,如下所示:

1
2
3
4
public class DbComment implements commentSchema {
  // use the DB_TABLE_NAME value here ...
  ...
}

如您所知,如果有人因为继承方面的原因而创建了dbcomment类的实例,他将能够访问db_table_name,这是不正确的,因为我们只想在dbcomment方法中使用这些值。

现在我有几个问题:

1)此实施是否正确?

2)如果不是这样,我们如何在dbcomment类之外声明这些变量,使这个类成为唯一看到这些值的类。(我们不想使用抽象类,因为一个类只能在Java中扩展一个其他类)

3)为什么我们需要对接口内存在的值和方法使用static?(当我们为一个特定的类实现某些接口时,为什么我们需要使它成为静态的,以便随处可见?)

4)有没有精确确定Java方法、类、枚举等各种声明的规范?


1) is this implementation proper & ok ?

是的,会很好的。

2) if It's not how I'm gonna declare these variable outside of DbComment class & make this class be the only class who does see DB_TABLE_NAME value. (I don't want to use abstract class coz a class can only extends one other class in java)

不需要,因为使用的实现按预期工作。

3) why we do need to use static for values & methods which exist inside an interface ? (when we implements certain interface for a specific class why do we need to make it static to be seen everywhere?)

不能在接口finalstatic中生成方法。方法所允许的唯一限定符是publicabstract,顺便说一下,它们完全没有任何效果。

对于字段,static存在,但也没有作用。接口中声明的所有字段都将由实现人员静态访问,并被视为常量。

4) is there any specification that exactly determine kinds of different declarations for java methods, classes, enums, etc ?

官方规范中有一章是关于名字和声明的。


默认情况下,接口内声明的任何字段都标记为public static final,即使程序员不这样做。这意味着,接口中的任何字段都将是常量,无法修改。

如果您不想使用这个功能(不管您有什么原因),那么最好使用一个抽象类,并将字段标记为protected static final

1
2
3
public abstract class CommentSchema{
    protected static final String DB_TABLE_NAME ="comment";
}

但是,如果您希望将设计建立在接口的基础上,那么您可以拥有不带此字段的接口,然后是一个实现此接口并添加字段的抽象类。通过这样做,扩展抽象类的每个类都将实现接口并可以访问字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface CommentSchema {
    foo();
}

public abstract class CommentSchemaAbstractImpl implements CommentSchema {
    protected static final String DB_TABLE_NAME ="comment";
}

public class CommentSchemaRealImpl extends CommentSchemaAbstractImpl {
    @Override
    public void foo() {
        //do something...
        baz(DB_TABLE_NAME);
    }
    private void baz(String s) {
        //fancy code here...
    }
}

最后,您可以忘记所有这些,并创建一个枚举来处理常量。

1
2
3
4
5
6
7
public enum TableName {
    COMMENT("comment");
    private String tableName;
    private TableName(String tableName) {
        this.tableName = tableName;
    }
}