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)
{
Out.In in = new Out().new In("测试信息");
/*
上面代码可以改为如下三行代码
使用OuterClass.InnerClass 的形式定义内部类变量
Out.In in;
创建外部类实例,非静态内部类实例将寄存在该实例中
Out out = new Out();
通过外部类实例和new来调用内部类构造器创建非静态内部类实例
in = out.new In("测试信息")
*/
}
}
Out.In in = new Out().new In("测试信息"); 这样的写法真的让人觉得很怪异,但它就是合理的
内部类可以被当成父类继承,这听起来很怪,但确实可行,下面的代码看起来也那么一点怪异
public class SubClass extends Out.In
{
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属性是: