接口的常量 默认 public static finalpublic 和 final很好理解,一个是为了实现【对扩展开放】,一个是为了对【修改关闭】。那么static呢?
查看了一些解释,其中有说如果没有static了就和抽象类一下,个人认为没有说服力,java不会为了区别接口和抽象类而设置这种多余的功能,肯定是为了实现某个目的而定。
还有一个说法是说,担心多个接口中,常量重名的问题,为了区分是那个接口的常量而设置static,那么这样一来,就不用担心多个接口中方法重名的问题吗?而且如果给接口种的方法加static的话,反而不允许。

解决方案 »

  1.   

    继承这个接口的类,实现这个接口中的方法也必须全部static?
      

  2.   

    是静态修饰符,什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在。这样做有什么意义呢? 
    在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是有种情况例外,就是该成员是用static声明的(在这里所讲排除了类的访问控制),例如: 
    未声明为static 
    class ClassA{ 
    int b; 
    public void ex1(){ 
    … 


    class ClassB{ 
    void ex2{ 
    int i; 
    ClassA a = new ClassA(); 
    i = a.b; //这里通过对象引用访问成员变量b 
    a.ex1; //这里通过对象引用访问成员函数ex1 

    } 声明为static 
    class ClassA{ 
    static int b; 
    static void ex1(){ 
    … 


    class ClassB{ 
    void ex2{ 
    int i; 
    i = ClassA.b; //这里通过类名访问成员变量b 
    ClassA.ex1; //这里通过类名访问成员函数ex1 


    通过以上两种比较,就可以知道static用来修饰类成员的主要作用了,在java类库当中有很多类成员都声明为static,可以让用户不需要实例化对象就可以引用成员,最基本的有Integer.parseInt(),Float.parseFloat()等等用来把对象转换为所需要的基本数据类型。这样的变量和方法我们又叫做类变量和类方法。 
    接下来讲一下被static修饰后的变量的值的问题,刚才在前面讲过,被static修饰后的成员,在编译时由内存分配一块内存空间,直到程序停止运行才会释放,那么就是说该类的所有对象都会共享这块内存空间,看一下下面这个例子: 
    class TStatic{ 
    static int i; public TStatic(){ 
    i = 4; 
    } public TStatic(int j){ 
    i = j; 
    } public static void main(String args[]){ 
    TStatic t = new TStatic(5); //声明对象引用,并实例化 
    TStatic tt = new TStatic(); //同上 
    System.out.println(t.i); 
    System.out.println(tt.i); 
    System.out.println(t.i); 


    这段代码里面Tstatic类有一个static的int变量I,有两个构造函数,第一个用于初始化I为4,第二个用于初始化i为传进函数的值,在main中所传的值是5,程序首先声明对象的引用t,然后调用带参数的构造函数实例化对象,此时对象t的成员变量I的值为5,接着声明对象tt,调用无参数的构造函数,那么就把对象tt的成员变量i的值初始化为4了,注意了,在这里i是static,那就是说该类的所有对象都共享该内存,那也就是说在实例化对象tt的时候改变了i的值,那么实际上对象t的i值也变了,因为实际上他们引用的是同一个成员变量。最后打印的结果是三个4。呵呵,写到这里大家是否明白了呢?不明白就再看看书或者多写几个例子印证一下,呵呵。
      

  3.   

    3楼回答的很仔细,也让我对static有了更多了解。
    但是,我问的是为什么 接口的常量要必须是static的,感觉你没有说到点上。、
    而且我问的是接口,你是用类局里。
      

  4.   

    我也是初学者,我想说下我的观点啊,你可以看看源码文件,很多东西可以再那里得到理解,接口的的变量用public staic final修饰的话可以直接接口名调用成员变量,因为接口不能被实例化,而用了静态常量的话 我们能直接不需要实例化接口 从而用里面的常量
      

  5.   

    static表示是静态的,静态的东西独立于类之外,而接口不属于类,所以要加static。
      

  6.   

    这个回答真的个人感觉很完美,让我对static修饰符有了更好的了解,谢谢!
      

  7.   

    static: static修饰就表示它属于类的,随的类的加载而存在的,如果是非static的话,
    就表示属于对象的,只有建立对象时才有它,而接口是不能建立对象的,所以
    接口的常量必须定义为static
      

  8.   

    static: static修饰就表示它属于类的,随的类的加载而存在的,如果是非static的话,
    就表示属于对象的,只有建立对象时才有它,而接口是不能建立对象的,所以
    接口的常量必须定义为static言简意赅
      

  9.   

    接口不能new 你不用static修饰用什么啊?
      

  10.   

      接口就是实现的啊 你在里面没有static 怎么用它呢   9楼说的更能解答楼主的问题
      

  11.   

    为什么接口中的变量是static修饰的?
    1.接口中的变量如果不是static,就必须初始化一个接口的实例才能访问接口中的变量,初始化一个接口的实例就要实现接口所有的方法,代价很大。而接口中的变量都是final的,即所有实现接口的实例拥有的变量值都是一样的,用一个代价很大的方式(初始化一个接口的实例)去访问一个所有实例都相同的值,得不偿失
    那为什么接口中的变量是final修饰呢?
    2. 因为接口本身就是用来定义一个标准、规范,是用来设计用户可用的细节(public)且不能随意更改的(final),那么接口中的任何东西都应该被定义成统一,那么定义的数值应该是常量
    假如接口中可以定义非final,而仅仅是public和static修饰的变量,那么被实现的类可以随便修改接口中的变量,这样会造成标准不统一
    反证:银行的提款机 
    银行的提款机中的插卡口可以看做是一个接口,所有的提款机插卡口是被统一的标准(大小尺寸)所约束的,方便每个卡可以插入各个提款机中。假如可以随便修改插卡口接口的数值,某行在当地修改了插卡口的尺寸,当你去提款机取钱,却发现插卡口小了点,那么...... 
      

  12.   

    static: static修饰就表示它属于类的,随的类的加载而存在的,如果是非static的话,
    就表示属于对象的,只有建立对象时才有它,而接口是不能建立对象的,所以
    接口的常量必须定义为static
    老哥,稳
      

  13.   

    因为接口是无状态的
    正因为接口是无状态的,所以接口中不允许出现实例成员,这是一个原则。
    带有static修饰的成员属于类成员,不属于实例成员(不是跟着对象走的),不属于接口的状态。
    如果接口支持状态的话,那么抽象类还有其存在的价值么?
      

  14.   

    而接口中定义的方法需要被实现,它是abstract的,在实现类中,它是实例方法(instance method),而overriding method和overridden method之间根本属性势必不能冲突,因此不能是static的
      

  15.   

    static修饰的变量是类变量,可以通过类名.变量直接调用,所以常量一般就设置为static
      

  16.   

    是和Java语言的本身机制有关,Java不支持多继承,但是一个类可是现实多个接口。假设有两个接口A和B,而类C实现了接口A和B。假设,此时,A和B中都有一个变量N,如果N不是static类型的,那么在C中该如何区分N到底是A的还是B的呢?而,如果是static类型的,我们可以通过A.N和B.N来区别调用A或者B中的成员变量N。
      

  17.   

    如果是static的,在C中仍然存在无法区分N到底是A的还是B的的问题
      

  18.   

    如果是static的,在C中仍然存在无法区分N到底是A的还是B的的问题
    刚刚试了下,好像可以哦~
      

  19.   

    1、接口没有实例,所以只能有static修饰的属性,可以不实例化就调用
    2、static修饰的方法是静态方法,静态方法不能被重写,可以不实例化就调用,但是接口里都是抽象方法,而且接口就是用来实现的,接口中的方法就是用来重写的,所以接口里不能有static方法
      

  20.   

    Java9将允许接口定义私有方法和私有静态方法
    实际上,Java8就已经允许接口定义默认方法了
      

  21.   

    static是编译时就分配内存,适合系统使用频繁的一些常量或者参数配置
      

  22.   

    对待这个问题,我建议用辩证的角度去看待!首先我们来看只有final没有static的情况,也就是说每个实现类里面都会有一个名字和值都一样的变量(final强调不准改变引用地址),那么在初始化相关实现类的时候,都会单独为这个属性开辟一个存储空间,这个时候问题就来了--》不觉得很浪费内存吗?如果我用static关键字修饰了,不管你创建多少个实现类实例,他们都共享这个成员属性并且内存中也只会开销紧够存储这一个属性的内存,而不会每个实例都去开销这个属性所需的内存,这是为毛要用static。反过来,我们看看不用final,只用static的情况,打个比方我们有A,V(名字取的不错)两个实现类,A类中的某个函数需要改变这个属性的值为50才能使逻辑正确,B类中的某个函数需要改变这个属性的值为100才能使逻辑正确,那么问题来了,A类中的函数改成了50美滋滋,B类中的属性也要变成50啊!所以B类在被运用的时候就报错了,这个时候就造成了属性歧义的问题,然而我们加上static这个关键字就不一样了,开发看到这个属性就知道不能再依赖这个属性写逻辑了,所以就自己另写属性,也就避免了后面的奇异性问题或者我们从书本的角度来说,接口本来就是最高层次的抽象,你给我在里面定义普通变量(我至少觉得变量一点不具抽象概念),玩呢?所以直接定死属性值,他的作用我们暂时不用考虑,但是乱用它的风险我们还是规避,仅此而已。或许现在隔壁老王出来说,那我既不用static也不用final为毛也不行呢?我就想说你这个脑子是怎么做到绿万千男人的大事的?接口本来就是为了充分利用多态特性来增加框架扩展性,你在接口里面定义一个name属性,实现类都要去利用它,那万一有的需求根本不需要用到这个属性,而只是单纯的想扩展架构呢?放在这里好看吗?对于这个情况,无论是官方还是个人意见都是在实现类定义自己需要的属性,避免属性值歧义和没有必要的耦合度,所以你在接口中不能也是没有必要去定义一个普通属性,解答完毕!
      

  23.   

    1. 从语法层面来讲, 这些都是语法规定, 所以问题就在于为什么要制定这样的语法
    2. 假设接口有非静态字段, 那么情况会是怎样
    3. 接口的非静态不应该是public, 这样对成员属性的直接访问会破坏封装性, 就像我们最简单的一个javabean也是通常会把属性写成private然后提供getter/setter方法来访问
    4. 当接口的非静态字段是private的情况下, 那么这个字段失去了直接被访问的途径, 只剩下两种访问途径
    5. 一种是在构造方法中进行初始化, 而由于接口的多继承特性, 导致不可能有构造方法存在, 那么失去了构造方法, 这些属性无法被灵活的初始化, 在所有子类中都只能在初始化时设置一个固定值(进一步说只能是默认值)
    6. 在非静态方法中进行访问, 但是接口的方法都是抽象, 因此在接口这一级别是没有任何地方能够使用和初始化这些非静态字段的
    7. 这两种访问途径都是行不通的, 所以在接口级别提供这些非静态字段, 既不能被外部访问, 又不能被接口本身所使用, 其实没有什么意义, 与其如此倒不如将定义字段的这一步骤推迟到子类(就算是protected字段子类可以访问, 但是在接口中无法提供语法强制子类利用这个字段, 而在抽象类中可以通过构造方法强制传参初始化这个字段或者通过非抽象方法强制使用这个字段, 只有被使用字段才有意义)
    8. 简单的来讲, 由于接口没有构造方法并且全是抽象方法的特性, 定义非静态字段没有实际的意义
    9. 既然如此, 为什么不从语法上进行修改, 让接口支持非抽象的非静态方法呢(实际上java8的接口已经支持静态方法和非静态的非抽象方法)
    10. 问题的进一步就是为什么不把接口和抽象类进行合并呢
    11. 这个问题我认为至少有两个方面
    12. 第一, 抽象类的本质是类, 单继承, 所以可以有构造方法, 至少是有参构造方法, 而接口多继承无法做到
    13. 第二, 从设计的角度来讲, 接口原本的设计目的就是倾向于提供规范, 例如最常见的JDBC规范里的Statement, ResultSet, Connection, Servlet规范里的HttpSession, HttpServletRequest, HttpServletResponse, Servlet等等, 这些都是接口, 而规范只需要指定一个抽象的功能(入参, 出参, 方法名, 异常列表), 具体实现是不关注的, 而抽象类的设计目的更加倾向于提供模版, 在提供部分非抽象的逻辑实现的基础上, 结合一部分抽象的部分, 模版就像我们写年终总结网上抄来的范文, 大部分写好了不需要改动的部分就是抽象类里的非抽象部分, 而需要改动的年月日, 姓名, 公司名等细节就是抽象类里的抽象方法部分, 交给具体的子类来实现, 正是由于他们设计的出发点不同, 所以他们才有不同的语法限制
    14. 更进一步, 为何要设计出这样两种语言特性呢, 为何不合并呢(就算是多继承导致无法提供有参构造, 但是真有心改动也是可以实现的)
    15. 这个问题的进一步问题就是一个语言为什么要设计出这么多细化的特性, 为什么不把多个特性融合在一起让用户在使用时自己选择需要用到的部分
    16. 这个问题就像java里的基础数据类型byte char short int一样, 为什么要设计设计出一个字节, 两个字节, 四个字节这么多种整数? 可能有人觉得目的是节约内存, 但是实际上在虚拟机中进行数学运算的时候, 所有这几种类型都会转为int然后利用int类型的字节码来进行运算, 并不存在所谓的short比int更节省内存的所以, 至少在方法内的局部变量是这样
    17. 问题的答案就在与细化, 把功能和特性进行更加严格的细化和区分, 让结构更清晰, 更利于管理, 就像面向对象的设计原则中的高内聚低耦合一样, 把功能细化, 保持每个功能点的职责单一, 而不是所有功能一团混沌让用户自己来进行取舍, 减少用户犯错的机会18. 问题到了这里我想总结出来就是, 为什么是这样呢? 因为语法就是这么设计的, 那么为什么这么设计呢? 因为接口的设计目的是提供规范, 而抽象类是提供模版, 那么为什么不把他们合并到一起让用户自己选择是否需要提供非抽象内容呢? 因为语法特性细化是一种好的设计, 不应该把所有特性糅合在一起让用户来选择并承担犯错成本
      

  24.   

    这样定义而已,如果当时定义接口不能为static  那么现在也会有人问为啥不能为static
      

  25.   

    理解接口:接口就是定义一个规范.
    先说接口中的方法:void ooxx().默认就是public abstratct,抽象方法必须被子类实现才有意义.为什么不能用static?static修饰符说明这个方法属于类,不属于对象.在多态思想中,把子类对象赋值给父类/接口变量,那么此时就存在多态.而多态是属于对象级别的特性.接口中的方法如果用static 修饰,那么怎么也不会被实现,所以编译就报错.
    再说字段,字段也不存在多态的特征.要访问接口中的字段,只有通过类来访问(因为接口不能创造对象),所以字段必须用static修饰.为什么用finnal,因为是定义规范,不能被修改~
      

  26.   

    public class TStatic {
        static int i;
        
        public TStatic() {
            i = 4;
        }
        
        public TStatic(int j) {
            i = j;
        }
        
        @SuppressWarnings("static-access")
        public static void main(String[] args) {
            TStatic t = new TStatic(5);
            TStatic tt = new TStatic();
            System.out.println(t.i);//为什么在这里就是打印的4?
            //System.out.println(tt.i);
            //System.out.println(t.i);
        }
    }
      

  27.   

    我知道了,在创建tt时就把i的值改变成了4,如果不创建tt那么就会打印5