你真的了解Java内部类吗


Android开发中,很多情况下都要用到内部类,在使用的过程中,偶尔可能遇到内部类嵌套内部类、内部类嵌套interface,甚至interface嵌套内部类等奇特场景,在嵌套调用一些成员静态或非静态的成员变量时编译器可能会报错,大部分人会根据IDE的提示来规避这些错误,修改编译运行后ok就算过了,至于为什么语法规则这样定,很少有人去了解。

本文就针对java中静态内部类的语法规则做出一个分析

在分析语法前,我们要区分一下静态内部类和非静态内部类的区别:

  • 对于静态内部类,它不依赖于外部类对象,其内部类也是可以有非静态成员的,它对象的存储空间中,并没有指向外部类对象的引用。所以,在静态内部类中,不能直接访问外部类的非静态成员,只能访问外部类的静态成员。而外部类能访问静态内部类的静态成员,但是不能直接访-问静态内部类的非静态成员。

  • 对于非静态内部类,其对象的空间中,保留了一个指向外部类对象的指针,这就意味着要创建非静态的内部类,必须先要有外部类对象,所以,非静态的内部类是可以直接引用外部类的成员的。


搞清楚区别后我们再分析下使用内部类报错的一个场景: 
在一个class中定义一个内部类,之后在这个内部类中定义一个interface,IDE会报错The member interface xxx can only be defined inside a top-level class or interface or in a static 
context
翻译过来就是:interface作为成员的话只能够被定义在最外层,或者在静态上下文中。看不懂啊有木有,那就看一下例子:

interface OuterInterface { // Top-level interface

  interface NestedInterface {// top-level nested interface 
  }

}

class OuterClass {

  /*Nested top-level classes are always defined with a static keyword*/
  static class NestedClass { 
    interface NestedInterface { } //OK
  }

  /*Inner class */
  class InnerClass { 

  /* This will cause an error. Because, you can not define a static modifier
      inside an inner class. InnerClass is an inner class and NestedInterface 
      is implicitly static.  An compile time error will occurs. 
  */ 

    interface NestedInterface { //compile time error, 
    }
  }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

通过上面的例子,可以看到一个interface在class中被定义有以下几种情况:

  • 在outerclass或者outerinterface内被定义(Top-level)->编译ok
  • 在innerclass内部被定义(non-Top-level)->编译error
  • 在static修饰的innerclass内部被定义->编译ok

这就有一个问题了,为什么静态内部类中可以定义interface,而非静态的内部类中不能定义interface呢? 
为此我专门看了一下oracle的官方文档中对内部类的定义说明,地址如下Inner Classes and Enclosing Instances 其中有这样三句话指点了我:

An inner class may be a non-static member class, a local class, or an anonymous class. A member class of an interface is implicitly static so is never considered to be an inner class. 
… 
It is a compile-time error if an inner class declares a member that is explicitly or implicitly static, unless the member is a constant variable 
… 
A nested class that is not an inner class may declare static members freely, in accordance with the usual rules of the Java programming language.

翻译-> 
第一句:一个内部类可以是类的非静态的成员类,或局部类,再或者是一个匿名类。而interfce是一个隐式的static成员类,是不能被认为成内部类的。 
第二句:如果一个内部类中声明的一个成员是static的,编译就会报错,除非这个成员是被static和final共同修饰的常量。 
第三句:按照java的语法规则,一个嵌套类被声明为static的话就不是一个内部类了

总结:java的语法规定了非静态的内部类才叫做内部类,而静态内部类只能叫做静态嵌套类,由于interface隐式的被static修饰,而在内部类中除非声明那种static final类型的常量,声明其余的static类型的成员(包括interface)都是不符合java语法规则的。这就解释了为什么至于内部类中不能声明interface而添加了static的内部类又能使用声明的疑问。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值