接口的常量为什么必须是static?而方法缺不能是static?

王小白-1 2016-10-20 01:47:13
接口的常量 默认 public static final

public 和 final很好理解,一个是为了实现【对扩展开放】,一个是为了对【修改关闭】。那么static呢?
查看了一些解释,其中有说如果没有static了就和抽象类一下,个人认为没有说服力,java不会为了区别接口和抽象类而设置这种多余的功能,肯定是为了实现某个目的而定。
还有一个说法是说,担心多个接口中,常量重名的问题,为了区分是那个接口的常量而设置static,那么这样一来,就不用担心多个接口中方法重名的问题吗?而且如果给接口种的方法加static的话,反而不允许。
...全文
5788 36 打赏 收藏 转发到动态 举报
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
PC_大侠 2020-02-07
  • 打赏
  • 举报
回复
引用 5 楼 一个睿智的人 的回复:
我也是初学者,我想说下我的观点啊,你可以看看源码文件,很多东西可以再那里得到理解,接口的的变量用public staic final修饰的话可以直接接口名调用成员变量,因为接口不能被实例化,而用了静态常量的话 我们能直接不需要实例化接口 从而用里面的常量


简单直接容易理解。
j江柯 2020-02-06
  • 打赏
  • 举报
回复
因为Java就是这样规定的,其实真正使用的时候有时还是会觉得不方便,而用抽象类来代替。kotlin就可以重写接口里的属性。
永远的渣科 2018-02-24
  • 打赏
  • 举报
回复
引用 33 楼 ZachLaVine 的回复:
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);
    }
}
我知道了,在创建tt时就把i的值改变成了4,如果不创建tt那么就会打印5
永远的渣科 2018-02-24
  • 打赏
  • 举报
回复
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);
    }
}
Rocketbear_lu 2018-02-16
  • 打赏
  • 举报
回复 1
理解接口:接口就是定义一个规范. 先说接口中的方法:void ooxx().默认就是public abstratct,抽象方法必须被子类实现才有意义.为什么不能用static?static修饰符说明这个方法属于类,不属于对象.在多态思想中,把子类对象赋值给父类/接口变量,那么此时就存在多态.而多态是属于对象级别的特性.接口中的方法如果用static 修饰,那么怎么也不会被实现,所以编译就报错. 再说字段,字段也不存在多态的特征.要访问接口中的字段,只有通过类来访问(因为接口不能创造对象),所以字段必须用static修饰.为什么用finnal,因为是定义规范,不能被修改~
  • 打赏
  • 举报
回复
这样定义而已,如果当时定义接口不能为static 那么现在也会有人问为啥不能为static
遗失在银河 2018-02-01
  • 打赏
  • 举报
回复
接口不可以实现方法,只可以定义方法,所以不能使用静态方法(因为静态方法必须实现)。 要实现静态方法的继承,可以使用抽象类,抽象类中实现静态的方法后,其他类继承。
dgqjava 2018-01-05
  • 打赏
  • 举报
回复
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. 问题到了这里我想总结出来就是, 为什么是这样呢? 因为语法就是这么设计的, 那么为什么这么设计呢? 因为接口的设计目的是提供规范, 而抽象类是提供模版, 那么为什么不把他们合并到一起让用户自己选择是否需要提供非抽象内容呢? 因为语法特性细化是一种好的设计, 不应该把所有特性糅合在一起让用户来选择并承担犯错成本
zhouyi936 2018-01-04
  • 打赏
  • 举报
回复
5楼讲的可以啊 简单粗暴容易理解
启-骋 2018-01-04
  • 打赏
  • 举报
回复
对待这个问题,我建议用辩证的角度去看待!首先我们来看只有final没有static的情况,也就是说每个实现类里面都会有一个名字和值都一样的变量(final强调不准改变引用地址),那么在初始化相关实现类的时候,都会单独为这个属性开辟一个存储空间,这个时候问题就来了--》不觉得很浪费内存吗?如果我用static关键字修饰了,不管你创建多少个实现类实例,他们都共享这个成员属性并且内存中也只会开销紧够存储这一个属性的内存,而不会每个实例都去开销这个属性所需的内存,这是为毛要用static。反过来,我们看看不用final,只用static的情况,打个比方我们有A,V(名字取的不错)两个实现类,A类中的某个函数需要改变这个属性的值为50才能使逻辑正确,B类中的某个函数需要改变这个属性的值为100才能使逻辑正确,那么问题来了,A类中的函数改成了50美滋滋,B类中的属性也要变成50啊!所以B类在被运用的时候就报错了,这个时候就造成了属性歧义的问题,然而我们加上static这个关键字就不一样了,开发看到这个属性就知道不能再依赖这个属性写逻辑了,所以就自己另写属性,也就避免了后面的奇异性问题。。。或者我们从书本的角度来说,接口本来就是最高层次的抽象,你给我在里面定义普通变量(我至少觉得变量一点不具抽象概念),玩呢?所以直接定死属性值,他的作用我们暂时不用考虑,但是乱用它的风险我们还是规避,仅此而已。或许现在隔壁老王出来说,那我既不用static也不用final为毛也不行呢?我就想说你这个脑子是怎么做到绿万千男人的大事的?接口本来就是为了充分利用多态特性来增加框架扩展性,你在接口里面定义一个name属性,实现类都要去利用它,那万一有的需求根本不需要用到这个属性,而只是单纯的想扩展架构呢?放在这里好看吗?对于这个情况,无论是官方还是个人意见都是在实现类定义自己需要的属性,避免属性值歧义和没有必要的耦合度,所以你在接口中不能也是没有必要去定义一个普通属性,解答完毕!
臭蛋丶 2017-05-18
  • 打赏
  • 举报
回复
5楼新手都懂~ 哈哈
sqq4290 2017-05-18
  • 打赏
  • 举报
回复
static是编译时就分配内存,适合系统使用频繁的一些常量或者参数配置
Just_illusion 2017-05-08
  • 打赏
  • 举报
回复
引用 22 楼 qq2890974020 的回复:
1、接口没有实例,所以只能有static修饰的属性,可以不实例化就调用 2、static修饰的方法是静态方法,静态方法不能被重写,可以不实例化就调用,但是接口里都是抽象方法,而且接口就是用来实现的,接口中的方法就是用来重写的,所以接口里不能有static方法
小伙子,可以的
zy_arhahaha 2017-05-08
  • 打赏
  • 举报
回复
1、接口没有实例,所以只能有static修饰的属性,可以不实例化就调用 2、static修饰的方法是静态方法,静态方法不能被重写,可以不实例化就调用,但是接口里都是抽象方法,而且接口就是用来实现的,接口中的方法就是用来重写的,所以接口里不能有static方法
动森万岁 2017-05-08
  • 打赏
  • 举报
回复
这个帖子好啊,看完又有新的感悟
解开者 2017-05-08
  • 打赏
  • 举报
回复
Java9将允许接口定义私有方法和私有静态方法 实际上,Java8就已经允许接口定义默认方法了
KiH_Jim 2017-05-07
  • 打赏
  • 举报
回复
引用 19 楼 dracularking 的回复:
[quote=引用 18 楼 sdweiziyu 的回复:] 是和Java语言的本身机制有关,Java不支持多继承,但是一个类可是现实多个接口。假设有两个接口A和B,而类C实现了接口A和B。假设,此时,A和B中都有一个变量N,如果N不是static类型的,那么在C中该如何区分N到底是A的还是B的呢?而,如果是static类型的,我们可以通过A.N和B.N来区别调用A或者B中的成员变量N。
如果是static的,在C中仍然存在无法区分N到底是A的还是B的的问题 [/quote] 刚刚试了下,好像可以哦~
dracularking 2017-03-28
  • 打赏
  • 举报
回复
引用 18 楼 sdweiziyu 的回复:
是和Java语言的本身机制有关,Java不支持多继承,但是一个类可是现实多个接口。假设有两个接口A和B,而类C实现了接口A和B。假设,此时,A和B中都有一个变量N,如果N不是static类型的,那么在C中该如何区分N到底是A的还是B的呢?而,如果是static类型的,我们可以通过A.N和B.N来区别调用A或者B中的成员变量N。
如果是static的,在C中仍然存在无法区分N到底是A的还是B的的问题
牧师不奶你 2017-03-28
  • 打赏
  • 举报
回复
是和Java语言的本身机制有关,Java不支持多继承,但是一个类可是现实多个接口。假设有两个接口A和B,而类C实现了接口A和B。假设,此时,A和B中都有一个变量N,如果N不是static类型的,那么在C中该如何区分N到底是A的还是B的呢?而,如果是static类型的,我们可以通过A.N和B.N来区别调用A或者B中的成员变量N。
我爱娃哈哈 2017-03-27
  • 打赏
  • 举报
回复
static修饰的变量是类变量,可以通过类名.变量直接调用,所以常量一般就设置为static
加载更多回复(16)

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧