• 再学Java 之 interface的成员变量


    前言:最近在学多线程,写“哲学家就餐问题(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类的编译信息:

      

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

      

  • 相关阅读:
    ThinkPHP中自定义常量
    【转】在Asp.net中弹出对话框,然后跳转到其他页面问题
    【转】SVN版本控制器的安装和配置
    【原】用上传控件进行文件上传时,页面程序代码都不执行,显示“页面信息无法显示”
    【转】net Web Service 方法重载
    【转】SQL里的EXISTS与in、not exists与not in
    【转】利用wsdl.exe生成webservice代理类
    【转】获取图片大小
    【转】用了AJAX后,不能用javascript弹出对话框
    【转】net Web Service 方法重载
  • 原文地址:https://www.cnblogs.com/scutwang/p/4120749.html
Copyright © 2020-2023  润新知