外部类:包含内部类的类。java
内部类: 把一个类放在另外一个类的内部。测试
形式: public class 外部类{
【修饰符】【访问控制符】class 【类名】{spa
}code
}对象
做用: 1。内部类提供了更好的封装,能够把内部类隐藏在外部类以内,不容许同一个包中的其余类访问该类。继承
2。内部类成员能够直接访问外部类的私有数据,由于内部类被当成其外部类成员,同一个类的成员之间能够互相访问。接口
public class Out{ private int a= 12; public class Int{ public void say(){ System.out.println(a);//直接访问外部类私有属性 } } public void test(){ Int i = new Int();//外部类不能直接访问非静态内部类的实例属性,必须显式建立内部类对象 i.say(); } public static void main(String[] args){ Out o = new Out();//只是建立了外部类,还未建立内部类对象 o.test(); } }
PS:非静态内部类对象中保留外部类对象的引用。 get
非静态内部类不能有静态方法,静态属性,静态初始化块。it
非静态内部类的对象必须寄存在外部类的对象里,所以建立非静态内部类以前,必须先建立其外部类的对象。class
静态内部类能够包含静态成员,也能够包含非静态成员。静态内部类不能访问外部类的实例变量,只能访问外部类的类成员。即便静态内部类的实例方法也不能访问外部类的实例成员。
静态内部类是外部类的类相关,而不是外部类的对象相关的,也就是说,静态内部类的对象不是寄存在外部类对象里的,而是寄存在外部类的类自己中。当一个静态内部类的对象存在时,并不存在一个被它寄存的外部类对象,静态内部类的对象里只有外部类的类引用,没有外部类对象的引用。
3。 匿名内部类适合用于建立那些仅须要一次使用的类。
外部类之外定义内部类: Outclass.Inclass var;
外部类之外建立内部类实例:Outclass.new Inclass();
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("测试信息"); /* 上面代码可改成以下三行代码: 使用OutterClass.InnerClass的形式定义内部类变量 Out.In in; 建立外部类实例,非静态内部类实例将寄存在该实例中 Out out = new Out(); 经过外部类实例和new来调用内部类构造器建立非静态内部类实例 in = out.new In("测试信息"); */ } }
非静态内部类的构造器必须使用外部类对象来调用
public class SubClass extends Out.In { //显示定义SubClass的构造器 public SubClass(Out out) { //经过传入的Out对象显式调用In的构造器 out.super("hello"); } }
匿名内部类: 建立匿名内部类时会当即建立一个该类的实例。 1 不能是抽象类 2 不能定义构造器 3 能够定义实例初始化块
new 父类构造器(实参列表) |实现接口()
{
//匿名内部类的类体部分
}
匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类或实现一个接口。
最经常使用的建立匿名内部类的方式是 :须要建立某个接口类型的对象。
interface Product //接口 { public double getPrice(); public String getName(); } public class TestAnonymous { public void test(Product p) { System.out.println("购买了一个" + p.getName() + ",花掉了" + p.getPrice()); } public static void main(String[] args) { TestAnonymous ta = new TestAnonymous(); //调用test方法时,须要传入一个Product参数,此处传入其匿名实现类的实例 ta.test( new Product() { public double getPrice() { return 567.8; } public String getName() { return "AGP显卡"; } }); } }