static nested class 和 inner class的不同,说得越多越好

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了static nested class 和 inner class的不同,说得越多越好相关的知识,希望对你有一定的参考价值。

1. Static Nested Class 不是 Inner Class. 

Jave Nested Class 分为两大类:1. Static Nested Class;2. Non-staticNested Class.
Non-Static Nested Class 才是真正的Inner Class. 正统的书上是这么区分的, 至于有没有道理, 是个仁者见仁, 智者见智的问题.

2. 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".

3. 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(接口), 人家更不知道你里面是什么东西了. 

4. 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). 

5. 跟其他普通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, classaccess 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 ofA.
//A.C myClass3 = new A.C(); // ERROR. can not access a instance member fromClass.



请注意CLASS B 和 CLASS C 的区别, 其中B就是常见的Static Nested Class, 而C就是最常见的Inner Class. 定义C 跟定义 B 是不一样的. 关键要理解 
静态的成员只跟CLASS挂钩, 而动态成员必须跟object挂钩.

其中 Inner Class又可分为两类或者三类.

1. 普通的 Inner Class, 在 Outer Class 中定义, 跟其他成员一样.


2. Local Inner Class. 在 Outer Class 的方法中或者任何一个block中定义, 
方法中定义的Inner Class, 其 input parameter 必须是 Final 修饰过的变量.

3. 匿名 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.

参考技术A static nested class

以上是关于static nested class 和 inner class的不同,说得越多越好的主要内容,如果未能解决你的问题,请参考以下文章

什么是内部类? Static Nested Class 和 Inner Class 的不同。

Java | 嵌套类(Nested Class)

使用 class-validator 和 Nest.js 验证对象数组

Nested Classes

nested class 例子

When to Use Nested Classes, Local Classes, Anonymous Classes, and Lambda Expressions