块代码的定义:简单来说就是处于一对{}之间的代码。
内部类的定义:处于另外一个类中的具有类型名称定义块代码。
匿名类的定义:已知父类或者接口标准的内部类,且不具有具体的类型名称的块代码。匿名类的实例创建必须使用new 父类名|接口名 ()来创建。)
一、命名内部类——用于临时创建实例或者类型,且该类型或实例需要控制是否允许使用该类的人调用
1-1:命名局部内部类
public class OutClass{
public int f()
{
private class InnerClass
{
int i=10;
}
return new InnerClass().i;
}
public static void main(String[] args)
{
OutClass o=new OutClass();
System.out.println(o.f());
}
}
此例中对于使用OutClass的人来说,无需关注于InnerClass类的存在,只关注于f()函数具体的
返回值;使用者无法访问InnerClass类的成员.
1-2:命名成员内部类
public class OutClass{
public class InnerClass{
int i=10;
}
public int f()
{
return new InnerClass().i;
}
public static void main(String[] args)
{
OutClass o=new OutClass();
System.out.println(o.f());
}
}
此例将简单内部类提升至成员等级,在此等级中,我们可以自由设定该内部类是允许OutClass使用者实例化InnerClass实例,如果为public 类型,则允许实例化,如果为private 类型,则不允许实例化(除开OutClass的成员方法将InnerClass类型的实例作为返回值返回)
1-3:命名内部类的实例化方法
public class OutClass{
public class InnerClass{
public InnerClass()
{
System.out.println("InnerClass construction start");
}
}
//public static void test()
//{
// InnerClass ic=new InnerClass();//错误的实例化内部类
//}
//public static InnerClass ic=new InnerClass();//错误的实例化内部类
public InnerClass ic=new InnerClass();
public InnerClass test()
{
return new InnerClass();
}
public static void main (String[] args)
{
OutClass oc=new OutClass();
OutClass.InnerClass ic=oc.new InnerClass();
}
}
注意:此处的输出结果为:
InnerClass construction start
InnerClass construction start
原因是外部类实例化时,需要产生一个内部类InnerClass成员,因此会调用内部类的构造函数,所以会有第一条InnerClass construction start
而当在主方法中实例化内部类时,也需要调用内部类的构造函数,因此产生了第二条
InnerClass construction start
内部类实例化的前提条件:内部类实例的存在,必须依赖于外部类实例的存在,也就是说,在没有实例化外部类的情况下,不允许产生内部类实例,同样的,由于静态方法及静态成员的存在必须依赖于包含该静态方法或该静态成员的类型的实例,所以内部类的实例不能存在于外部类的静态方法或静态成员中,同理,非静态的内部类也不能包含静态的成员。
二、匿名内部类——用于临时创建实例,且该实例不希望类的使用者关注
匿名内部类的存在前提有两种:1、已知该类型的父类 或者 2、已知该类型的接口标准
通常对于一个临时的实例,我们并不希望他被使用者关注,比如一个人类Person,我们在处理一些他的特例的时候——比如BlindMan类型的人,而这种类型并不常见,所以我们可以不需要实体创建BlindMan这个类型,而直接使用它的具体实例:
1-1:已知父类的匿名内部类
public class Test
{
public void see()
{
Person p=new Person()
{
name="I";
void r(){
System.out.println(this.name+" can see nothing.");
}
};
p.r();
}
}
注意:由于此处的匿名类是创建p指针的具体膜板,必须在{}外添加";"号,表示是创建Person
实例的语句结束。
1-2:已知接口标准的内部类
interface IFly{
void fly();
}
class Plan{
public void run()
{
IFly f=new IFly()//使用匿名类创建飞机实例
{
public void fly()
{
System.out.println("Plan is flying");
}
};
f.fly();
}
}
三、静态内部类
静态内部类的出现主要是为了解决内部类的重复实例化问题,对于一个经常调用的内部类,在我们不需要关注其具体内容的时候,重复的多次出现会消耗大量资源,因此利用了静态类的特性——只需要实例化一次,产生了静态内部类,静态内部类中可以声明静态成员也可以存在非静态成员,且静态内部类遵循静态规则既:静态的方法或者类型,不能直接调用其外部的非静态成员。
需要注意的是 静态内部类的存在并不依赖于其外部类的实例,原因是普通类的实例化顺序是先静态成员,再成员变量初始化,再构造;由于在外部类实例化之前就已经产生了静态内部类(将他作为静态成员),因此静态内部类并不具有对外部类的依赖性。
四、其他普通类继承内部类
前提:由于内部类实例的存在依赖与外部类的实例,因此普通类继承内部类的时候,必须将外
部类的实例作为参数传递给子类的构造函数,此处似乎并不符合语法逻辑:
public class A
{
public class B
{
public B()
{
System.out.println("Construction start");
}
}
}
public class Test extends A.B
{
public Test(A a)
{
a.super();//不符合语法逻辑,a.super怎么能是B的构造函数呢?.操作符应该是表示前一个
实例的具体成员阿,a对象不该有super成员函数,况且该函数还是内部类B的构造函数!
}
public static void main(String [] args)
{
Test t=new Test();
}
}
输出结果为:Construction start