public class DiscernVariable 
{
	private String prop = "外部类属性";
	private class InClass
	{
		private String prop = "内部类属性";
		public void info()
		{
			String prop = "局部变量";
			//通过外部类类名.this.varName 访问外部类实例属性
			System.out.println("外部类的属性值:" + DiscernVariable.this.prop);
			//通过this.varName 访问内部类实例的属性
			System.out.println("内部类的属性值:" + this.prop);
			//直接访问局部变量
			System.out.println("局部变量的值:" + prop);
		}
	}
	public void test()
	{
		InClass in = new InClass();
		();
	}
	public static void main(String[] args) 
	{
		new DiscernVariable().test();
	}
}

非静态内部类可以访问外部类private实例属性,但是反过来外部类访问内部类的private实例属性就不行了,原因在于,内部类保有外部类的对象引用,而外部类没有内部类的引用

如果要访问内部类的实例属性, 可以这样 new Inner().inProp

编译上面的程序,文件所有路径会生成两个class文件,一个是DiscernVariable,一个是DiscernVariable$InClass.class

成员内部类(包括,静态,非静态)的class文件总是这种形式: OuterClass$InnerClass.class

Java不允许在非静态类里定义静态成员(静态方法,静态属性,静态初始化块)

如果是静态内部类,同样用static修饰,这个内部类与外部类相关,属于整个外部类,而不是单独属于外部类的某个对象,因此静态内部类称为类内部类,静态类不能访问外部类的实例成员,换句话说,就是不能访问非静态的成员,只要是静态的就是对类而言,非静态就是对类的实例而言,而且它们保存的内存位置也不相同,类保存在栈区,类的实例保存在堆区

如果在外部类以处使用非静态内部类,那么就不能对内部类使用private修饰符.因为非静态内部类的对象必须寄存在外部类的对象里,因此创建非静态内部类对象之前,必须先创建 其外部类的对象.

public class out 
{
	//定义一个内部类,不使用访问控制符,即同一个包中其他类可访问该内部类
	class In
	{
		public In(String msg)
		{
			System.out.println(msg);
		}
	}
}
public class CreateInnerInstance 
{
	public static void main(String[] args) 
	{
		 in = new Out().new In("测试信息");
		/*
		上面代码可以改为如下三行代码
		使用OuterClass.InnerClass 的形式定义内部类变量
		 in;
		创建外部类实例,非静态内部类实例将寄存在该实例中
		Out out = new Out();
		通过外部类实例和new来调用内部类构造器创建非静态内部类实例
		in = out.new In("测试信息")
		*/
	}
}

 in = new Out().new In("测试信息"); 这样的写法真的让人觉得很怪异,但它就是合理的

内部类可以被当成父类继承,这听起来很怪,但确实可行,下面的代码看起来也那么一点怪异

public class SubClass extends 
{
	public SubClass(Out out) 
	{
		//通过传入的Out对象显式调用In的构造器
		out.super("hello");
	}
}

非静态内部类In类的构造器必须使用外部类对象来调用,上面的super代表In类的构造器,真的很怪异的写法,不是吗?要使用内部类,必须先创建它的外部类

Java还支持在方法体里定义类,即局部类,就是局部变量一样,并可以定义局部类的子类,即继承一个局部类的另一个局部类

public class LocalInnerClass 
{
	public static void main(String[] args) 
	{
		class InnerBase
		{
			int a;
		}
		class InnerSub extends InnerBase
		{
			int b;
		}
		InnerSub is = new InnerSub();
		is.a = 5;
		is.b = 8;
		System.out.println("InnerSub对象的a和b属性是:" + is.a + "," + is.b);
	}
}

输出 InnerSub对象的a和b属性是:5,8, 最后is对象也确实继承到父类的成员a

InnerSub对象的a和b属性是: