Java和C#中内嵌类的区别

Java和C#都有内嵌类(Nested Class)这一概念,可以在一个类的内部定义另一个类。但Java和C#中的内嵌类是不太一样的。C#的内嵌类概念接近Java的静态内嵌类。

Java和C#中的内嵌类定义如下所示:

public class JavaClass {
    private int member;
    public class JavaNestedClass {
        private int innerMember;
    }
}
public class DotNetClass
{
    private int member;
    public class DotNetNestedClass
    {
        private int innerMember;
    }
}

但是这两种内嵌类有一个本质的不同:Java的非静态内嵌类对象是依附在外部类对象中的,并且在内嵌类中可以访问外部类的非静态成员:

public class JavaClass {
    private int value;

    public class JavaNestedClass {
        public int getValueOutside() {
            return value;
        }
    }

    public JavaClass(int value) {
        this.value = value;
    }
}

因此,在新建Java非静态内嵌类对象时,需要提供一个外部类对象:

var a = new JavaClass(25);
var b = a.new JavaNestedClass();

而C#的内嵌类并不依附于一个外部类的对象,内嵌类只起到控制可见性的功能。内嵌类中是不能访问外部类的非静态成员的:

public class DotNetClass
{
    private int value;

    public class DotNetNestedClass
    {
        // 以下属性将导致编译失败:
        // 对象引用对于非静态的字段、方法或属性“DotNetClass.value”是必需的
        // public int ValueOutside
        // {
        //     get => value; 
        // }
    }

    public DotNetClass(int value) {
        this.value = value;
    }
}

新建C#内嵌类对象时,只需提供外部类名称而不需要一个对象:

var a = new DotNetClass(25);
var b = new DotNetClass.DotNetNestedClass();

C#的内嵌类相当于Java的静态内嵌类。Java静态内嵌类与C#内嵌类一样,不需要外部类对象,也不能访问外部类非静态成员:

public class JavaClass {
    private int value;

    public static class JavaNestedClass {
        // 以下方法将导致编译失败:
        // 无法从静态上下文中引用非静态 变量 value
        // public int getValueOutside() {
        //     return value;
        // }
    }

    public JavaClass(int value) {
        this.value = value;
    }
}
var a = new JavaClass(25);
var b = new JavaClass.JavaNestedClass();