Java Nested Class
Java Nested Class 对不少人来说是个让人迷惑的东西, 也是面试中容易考倒人的概念, 笔者最近稍微深入研究了一下这个题目,现将一点心得体会跟大家分享, 希望能对其他人有所帮助, 讲错的地方也欢迎大家指正.
首先先澄清一个相对比较简单的让人模糊概念.
- Static Nested Class 不是 Inner Class.
Jave Nested Class 分为两大类:1. Static Nested Class;2. Non-static Nested Class.
Non-Static Nested Class 才是真正的Inner Class. 正统的书上是这么区分的, 至于有没有道理, 是个仁者见仁, 智者见智的问题.
在笔者看来, 我觉得如此分没有什么意义, 甚至觉得将 Non-Static Nested Class 归入 Inner Class更合理一些, 因为, Inner Class 跟 其他 class member 和 class method 一样, 都是 outerclass 的一个成员.
但权威们要这么区分, 我等也只能跟风了.
- Inner Class 的 Scope 问题.
A. 如果 outer class 的 scope 是 public, 那么四个不同的 scope 对 Inner Class 都有不同的意义.
public – 任何一个其他class 都能看到和使用.
private – Scope只限于包含这个Inner Class 的 Outer Class 中, 也就说只有 Outer Class 的成员能够看到和使用, 在这个Outer Class 外面看不到这个Inner Class.
package – 这个是默认行为(default), 只有同一个package 的 才能看到和使用这个 Inner Class.
protected – 比package稍微多一点, 不同package, 但继承了Outer Class 的 子 类 ( extended class of Outer Class), 也能使用这个 Inner Class.
B. 我们知道主类(CLASS) 的 scope 只能是 public 或者 package, private 和protected 对 主类(CLASS)没有意义. 主CLASS就是供其他CLASS 使用的, 要不给所有的CLASS 用, 要不给同一个 package 的CLASS 用. 其他两个scope没有任何意义, JAVA compiler 禁止主类(Main Class)使用 private和protected.
好,有意思的地方来了, 如果 主类的scope 是 package, 那么作为成员的Inner Class的 scope 该如何定义?
因为主类(Outer Class) 的 scope 是 package, 那么 , 只有同一个package的CLASS可以看到这个Outer Class.
既然如此, 对Inner Class 而言, 只有private 和 默认(defalut package) 有意义.
至于其他的protected, public和package, 对 Inner Class来说, 含义是一样的, 都是 只有 同一个package的其他CLASS 可以 看到和使用这个Inner Class.
在这种情况下, public 和 protected 纯属扯蛋, 除了把人脑子搞乱外,没有任何意义.
我不了解的是, 为什么compiler不象针对Main Class一样, 对scope为package(默认)的CLASS 的 Inner Class 使用相似的限制, 只允许有private和package(默认), 这样可以避免混乱.
private scope的意思没有变, 还是只有同一个OUT CLASS的其他成员才可以看到和使用这个 Inner Class, private only to this “Outer Class”.
- Static-Nested Class
多数情况下, 使用比较多的都是这类CLASS, 因为比较简单, 方便. 学过一些JAVA的人知道, 使用Nested Class
的主要目的有两个:1. 将逻辑上紧密相关的CLASS放在一起(在同一个主CLASS中); 2. 只被一个主CLASS使用的非常局限性辅佐功能, 换句话说, 相当于你要写个HELPER CLASS, 但又只被一个主CLASS使用.
这么做,可以让你的程序更加紧凑, 容易阅读, 也安全.
谈到安全问题, 一般情况下, 我都喜欢将 Static-Nested Class 的scope设计成private. 这样, 外面的CLASS根本看不到我的implementation, 这样我就Hide了我的Logic, 这个叫encapsulation ,是面象程序一个很重要的概念.
如果你是个熟手, 甚至可以更进一步, 将你的Nested Class up-casting成 interface(接口), 人家更不知道你里面是什么东西了.
- Static-Nested Class 的成员, 既可以定义为静态的(static), 也可以定义为动态的(instance).
Nested Class的静态成员(Method)只能对Outer Class的静态成员(static memebr)进行操作(ACCESS), 而不能Access Outer Class的动态成员(instance member).
而 Nested Class的动态成员(instance method) 却可以 Access Outer Class的所有成员, 这个概念很重要, 许多人对这个概念模糊.
有一个普通的原则, 因为静态方法(static method) 总是跟 CLASS 相关联(bind CLASS), 而 动态方法( (instance method) 总是跟 instance object 相关联, 所以,
静态方法(static method)永远不可以Access跟 object 相关的动态成员(instance member),
反过来就可以, 一个CLASS的 instance object 可以 Access 这个 Class 的任何成员, 包括静态成员(static member).
- 跟其他普通CLASS成员的区别.
虽然 nested class 跟其他CLASS成员在绝大多数情况下一样, 地位和功能上没有什么不同.
Nested Class 是个类(Class) ,是可以初始化和赋值的(create an instance object), 请注意, Static Nested Class 和 Inner Class( Non-Static Nested Class) 在 语法上是不同的.
举个简单的例子.
class A
{
private int i = 6;
private static String s = “Nested Class”;
int getValue()
{
return i;
}
private static class B
{
void setIntValue(int i)
{
new A().i = i;
}
int getIntValue()
{
return new A().i;
}
static void setStrValue(String s)
{
A.s = s;
}
static String getStrValue()
{
return A.s;
}
}
// Be careful , all members of C must not static!!!!!
private class C
{
void setIntValue(int i)
{
new A().i = i;
}
int getIntValue()
{
return new A().i;
}
}
public static void main(String[] args)
{
System.out.println(“String value:” + B.getStrValue()); // OK, class access static method
System.out.println(“String value:” + new B().getStrValue()); // OK, object access it’s static method
System.out.println(“Int value:” + new B().getIntValue()); // OK, object access instance method
// System.out.println(“Int value:” + B.getIntValue()); // Not OK. class can not access instance method.
// creat an instance object from outside.
A.B myClass = new A.B(); // ok. because B is static member of A.
// If nested class is not static, you have to do this to create an object.
A.C myClass2 = new A().new C(); // OK. create instance of C from an instance of A.
//A.C myClass3 = new A.C(); // ERROR. can not access a instance member from Class.
}
}
请注意CLASS B 和 CLASS C 的区别, 其中B就是常见的Static Nested Class, 而C就是最常见的Inner Class. 定义C 跟 定义 B 是不一样的. 关键要理解
静态的成员只跟CLASS挂钩, 而动态成员必须跟object挂钩.
其中 Inner Class又可分为两类或者三类.
普通的 Inner Class, 在 Outer Class 中定义, 跟 其他成员一样.
Local Inner Class. 在 Outer Class 的方法中或者任何一个block{}中定义,
方法中定义的Inner Class, 其 input parameter 必须是 Final 修饰过的变量.匿名 Inner Class(Anonymous Inner Class). 简单的说就是没有名字.
2 和 3 区别不到, 只有 Syntax上的区别.
Local Inner Class, 顾名思义, 它的SCOPE, 只在 定义它的 那个 block 中, 也就是在
包围它的 {} 中.
其他的使用,跟 普通的 Inner Class 差不多, 就不多说了.
举个简单的例子.
public class AbstracDemo
{
private abstract class MyAbs
{
abstract void print();
int readline()
{
return i;
}
}/*
private class MyAbsDemo extends MyAbs
{
void print()
{
System.out.println(“———-:”+readline());
}
int readline()
{
return i;
}
}
*/
public int i = 12;
public static void main(String[] args)
{
AbstracDemo d = new AbstracDemo();
System.out.println(“**:”+d.i);
class MyAbsDemo extends MyAbs
{
MyAbsDemo()
{
new AbstracDemo().super();
}
void print()
{
System.out.println(“———-:”+readline());
}
int readline()
{
return new AbstracDemo().i;
}
}
MyAbsDemo m = new MyAbsDemo();
System.out.println(“**:”+m.readline());
m.print();
}
}
Main当中的MyAbsDemo, 就是个典型的Local Inner Class.