内部类是指一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。
内部类可以是静态,可用protected和private修饰。而外部类只能是使用public和缺省的包访问权限。
内部类主要有以下几类:成员内部类、局部内部类、静态内部类、匿名内部类。
为什么需要内部类?
典型的情况是、内部类继承某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以内部类提供了某种进入外围类的窗口,使用内部类最吸引人的地方是:
每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否继承了某个接口,对于内部类没用影响。如果没有内部类提供的可以继承多个具体后抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效的实现了“多重继承”。
内部类的特性:
1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
2、在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
3、创建内部类对象的时刻并不依赖于外围类对象的创建。
4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
5、内部类提供了更好的封装,除了该外围类,其他类都不能访问。
引用内部类:OuterClassName.InnerClassName。
创建某个内部类对象,必须要利用外部类的对象通过.new来创建内部类:OuterClass.InnerClass innerClass = outClass.new InnerClass()。
需要生成外部类对象的引用,使用OuterClassName.this ,这样就能够产生一个正确的引用外部类的引用了。
内部类是一个编译时的概念,一旦编译成功后,它就与外围类属于两个完全不同的类,对于一个名为OutClass的外围类和一个名为InnerClass的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$InnerClass.class。
public class OutClass {
private String name;
private int age;
{
name = "lisi";
age = 24;
}
// public OutClass(String name, int age) {
// super();
// this.name = name;
// this.age = age;
// }
//
// public OutClass() {
// this.name = "lisi";
// this.age = 24;
//
// }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void display() {
System.out.println("name: " + getName() + " age: " + getAge());
System.out.println("OutClass.....");
}
public class InnerClass {
private String name;
private int age;
public InnerClass() {
this.name = "zhangsan";
this.age = 23;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void display() {
System.out.println("name: " + getName() + " age: " + getAge());
System.out.println("name: " + OutClass.this.getName() + " age: " + OutClass.this.getAge());
}
public OutClass getOutClass() {
return OutClass.this;
}
}
public static void main(String[] args) {
OutClass outclass = new OutClass();
OutClass.InnerClass innerClass = outclass.new InnerClass();
//innerClass.display();
innerClass.getOutClass().display();
outclass.display();
}
}
成员内部类
成员内部类是最普通的内部类,它是外围类的一个成员,所以它是可以无限制的访问外围类的所有成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
在使用成员内部类要注意两点:第一,成员内部类中不能存在任何static的变量和方法;第二,成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。
注:
在内部类中访问内部类自己的变量直接用变量名
在内部类中访问内部类自己的变量也可以用this.变量名
在内部类中访问外部类中与内部类同名的实例变量用外部类名.this.变量名
如果内部类中没有与外部类同名的变量,则可以直接用变量名访问外部类变量
局部内部类
嵌套在方法和作用域内的类称为局部内部类,局部内部类的作用域只能是该该方法和属性被使用,出了该方法和属性就会失效。局部内部类不能有访问修饰符。
匿名内部类
用到类的一个实例。
类在定义后马上用到。
类非常小(SUN推荐是在4行代码以下)
给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
匿名内部类不能有构造方法。
匿名内部类不能定义任何静态成员、方法和类。
匿名内部类不能是public,protected,private,static。
只能创建匿名内部类的一个实例。
一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
静态内部类
关键字static修饰的类,它的创建是不需要依赖于外围类的,不能使用任何外围类的非static成员变量和方法。
局部内部类和匿名内部类只能访问局部final变量:会因为作用域造成数据不一致
匿名类的继承:
class WithInner{
class Inner{
}
}
public class InheritInner extends WithInner.Inner {
InheritInner(WithInner wi){
wi.super();//必须这么写才能初始化
}
public static void main(String[] args){
WithInner wi = new WithInner();
InheritInner ii = new InheritInner();
}
}