欢迎访问生活随笔!

生活随笔

您现在的位置是:首页 > 形式科学 > 计算机科学 > IT网络

IT网络

重新学习Java接口的成员变量

发布时间:2022-11-21IT网络 小博士
最近在学习多线程和写《用餐哲学家》的时候,需要定义一个全局变量,就是哲学家的数量。然而,通常的做法是在其中一个类中定义一个静态最终变量

前言:最近在学多线程,写“哲学家就餐问题(Dining Philosophers)”的时候,需要定义一个全局的变量,即哲学家的人数。常用的做法是在其中一个类中定义一个static final的变量,然后让其他类通过类名访问他。在这里,想使用之前实训项目的第一版应用层协议的设计想法,即使用一个接口类来定义所有子类都会使用到的变量。然后,就引出了一个interface成员变量和static final的问题。

(一)一个简单的问题  

  首先,看一段代码:

1 //Variable.java 2 public interface Variable { 3 public int NUM_PHILOSOPHERS = 5; 4 } 5 6 //DiningPhilosophers.java 7 public class DiningPhilosophers implements Variable{ 8 public static void main(String[] args) { 9 Lock[] chopsticks = new ReentrantLock[NUM_PHILOSOPHERS]; 10 System.out.println(chopsticks.length); 11 } 12 }

  上述代码中,DiningPhilosophers类的static方法直接使用接口中的public int变量,是否会出错?

(二)解析

  可能会有人第一反应是不可以,因为静态方法不能直接使用类的非静态成员变量。我的一部分朋友也是这么想的(好吧,不排除我的误导)。

  实际上,上面的程序并没有问题

  (1)首先,静态方法的确不能直接使用类的非静态成员变量。我曾经写过一篇类似的博文《再学Java 之 解决No enclosing of type * is accessable》大家可以参考一下。

  (2)其次,所有的interface成员变量都必须是public static final 的(原因后面会解释),所以我们在写代码的时候可以省略一部分修饰符,所以上面的NUM_PHILOSOPHERS就算声明语句为 int NUM_PHILOSOPHERS=5;它依然是一个public static final变量(所以,这也解释了,如果我们不对其赋初始值,为什么会报错)。我们可以使用javap工具查看Variable类的编译信息:

  再学Java 之 interface的成员变量-风君子博客

  (3)最后解释一下为什么interface的成员变量必须是public static final的。

  我在Google上搜到了一篇比较不错的文章《Why do we have only public static final variables in interfaces?》,下面大概翻译一下(有改动):

  接口定义了行为的协议,而不是行为如何执行实现。实现接口的类支持该接口中定义的行为协议。

  接口中声明的所有字段都是public static final的。为什么?

如果一个变量没有被定义为final,任何类的实现都可以改变变量的值。同时他就会变成类的实现的一部分,而接口是一个不带任何实现的纯粹的规范;
如果变量是静态的,那么这个变量就是属于接口的,而不是属于实例对象或者运行时的对象的。(注:由于接口不能被实例化,所以,定义为非静态,其实也没有意义。);
接口定义了调用者如何跟接口的实现类的实例对象交互,所以如果成员不是public,那么调用者没办法去方法它;

  接口的每一个字段的声明都必须是pubic static final 的,它允许我们在声明时指定所有或者部分修饰符。同时,任何字段的声明必须有一个初始化表达式,它可以不用一定是一个常量表达式,它的计算和赋值只会进行一次,然后这个接口字段就被初始化了(注:这是一个很有趣的特性,有兴趣可以一起聊聊:-))。