一、什么是内部类
1、可以将一个类的定义放在另一个类的定义内部,这就是内部类
2、内部类我们在外面看非常简单,无非就是在一个类的内部在定义一个类
public class InnerClass { class innerClass{ public innerClass(){ System.out.println("innerClass...."); } } }
在这里InnerClass就是一个内部类,我们在使用内部类的同时,要明确知道为什么使用内部类,内部类有什么作用,内部类能给我们带来什么好处
二、为什么使用内部类
1、使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
2、在我们的程序设计中会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的可以继承多个具体的或者抽象的类的能力来解决问题
public interface A{ } public interface B{ } public class C implements A,B{
}
class A_ implements A{
public B_ implements B{
}
}
在这个代码中,我们可能很难看出内部类有什么优点,但当A、B不是接口,而是抽象类或者具体类时,这个时候我们只能使用内部类才能实现多继承
3、内部类的特性
1)内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
2)再单个外围类中,可以让多个内部类以不同方式实现同一个接口,或者继承同一个类。
3)创建内部类对象的时刻并不依赖于外围类对象的创建。
4)内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
5)内部类提供了更好的封装,除了该外围类,其他类都不能访问。
三、成员内部类
1、成员内部类也是最普通的内部类,他是外围的一个成员,他可以无限制的访问外围类的所有属性和方法,尽管是private,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
2、
1)成员内部类不存在任何的static变量和方法;
2)成员内部类是依附于外围类,所以只有先创建外围类才能创建内部类;
public class OuterClass { private String str; public void A(){ System.out.println("a"); } public class InnerClass{ public void str(){ //访问外围类的属性 str="aa"; //访问外围类的方法 A(); } } //通过get方法来获取成员内部类 public InnerClass getInnerClass(){ return new InnerClass(); } public static void main(String[] args) { OuterClass out = new OuterClass(); OuterClass.InnerClass inner = out.getInnerClass(); inner.str(); } }
四、局部内部类
有这样一种内部类,它是嵌套在方法和作用于内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。
定义在方法中:
A类: public class A { public void C(){ System.out.println("有病"); } } public class T { public void driver(){ System.out.println("开车中。。。撞死人"); //继承A类,局部内部类 class g extends A{ } //调用A类中的方法 new g().C(); System.out.println("没事"); } public static void main(String[] s){ new T().driver(); } }
定义在作用域中:
public class Parcel6 { private void internalTracking(boolean b){ if(b){ class TrackingSlip{ private String id; TrackingSlip(String s) { id = s; } String getSlip(){ return id; } } TrackingSlip ts = new TrackingSlip("chenssy"); String string = ts.getSlip(); } } public void track(){ internalTracking(true); } public static void main(String[] args) { Parcel6 parcel6 = new Parcel6(); parcel6.track(); } }
五、匿名内部类
1、匿名内部类是没有名字的,创建格式如下
new 父类构造器(参数列表)|实现接口(){ //匿名内部类的类体部分 }
2、匿名内部类必须要继承一个父类或实现一个接口,也只能继承一个父类或实现一个接口。匿名内部类没有class关键字,这是因为它是直接使用new来生成一个对象引用,当然这个引用是隐式的。
public class T { interface A{ public void a(); } public static void main(String[] s){
//创建匿名内部类 A a = new A(){ public void a() { System.out.println("a");//由于匿名内部类不能是抽象类,所以它必须要实现它的抽象父类或者接口里面所有的抽象方法。 } }; a.a();//方法调用 } }
对于匿名内部类的使用它是存在一个缺陷的,就是它仅能被使用一次,创建匿名内部类时它会立即创建一个该类的实例,该类的定义会立即消失,所以匿名内部类是不能够被重复使用。
3、注意事项
1)使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2)匿名内部类中是不能定义构造函数的。
3)匿名内部类中不能存在任何的静态成员变量和静态方法。
4)匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5)匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。