1、内部类?什么是内部类?
内部类我们从文字看是非常容易理解的,其实就是在一个类的内部再定义一个类。
2、为什么要使用内部类?
使用内部类最吸引人的原因是:
每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。
3、内部类概念?
内部类是指在一个外部类的内部再定义一个类。类名不需要和文件名相同。
内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。
内部类的访问修饰符?
内部类可以是静态static的,也可用public,default,protected和private修饰。
注:外部顶级类即类名和文件名相同的只能使用public和default
4、内部类的分类
a. 成员内部类
成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
在成员内部类中要注意两点:
第一:成员内部类中不能存在任何static的变量和方法;
第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。
举例:
如何创建内部类?
package com.dome; public class InnerClass { //非静态内部类 class Inner{ public void sayHello(String name){ System.out.println("Hello!"+name); //调用外部类的成员方法 sayName("破晓"); } } //静态内部类 static class StaticInner{ public void sayHi(String name){ System.out.println("Hi!"+name); } } //推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 。 public Inner getInner(){ return new Inner(); } //成员方法 public void sayName(String name){ System.out.println("my name is "+name); } }
接下来,如何实例化内部类?我们新建一个Test类。
package com.dome; public class Test { public static void main(String[] args) { //实例化InnerClass类里的非静态内部类 InnerClass.Inner inner=new InnerClass().new Inner(); inner.sayHello("君帅"); //实例化InnerClass类里的静态内部类 InnerClass.StaticInner staticInner=new InnerClass.StaticInner(); staticInner.sayHi("君小帅"); } }
运行结果:
总结:
非静态内部类因为是了属于对象的,所以初始化时需要先初始化一个外部类实例对象,然后使用此对象调用内部类的构造方法。
静态内部类属于类本身,初始化时直接使用外部类调用静态内部类的构造方法即可。
注:推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 。
b.局部内部类
局部内部类,是指内部类定义在方法和作用域内的。局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域
内才能使用,退出这些作用域后无法引用的。
引用《Think in java》中的经典例子:
定义在方法内:
public class Parcel4 { public Destination destination(String s) { class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } } return new PDestination(s); } public static void main(String[] args) { Parcel4 p = new Parcel4(); Destination d = p.destination("Tasmania"); } }
定义在作用域里:
public class Parcel5 { 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("slip"); String s = ts.getSlip(); } } public void track() { internalTracking(true); } public static void main(String[] args) { Parcel5 p = new Parcel5(); p.track(); } }
局部内部类:
局部内部类就是在类内的方法中定义的类。
局部类有一个优势,即对外部世界完全隐藏。即使是同一个类中其他的方法也不能访问它。
局部类可以访问包含它的外部类,同时也可以访问局部变量。
局部类不能用public或private访问说明符进行声明,他的作用域被限定在这个方法中。
c. 嵌套内部类
嵌套内部类,就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用
outer.inner,即不需要创建外部类,也不需要创建内部类。
嵌套类和普通的内部类还有一个区别:普通内部类不能有static数据和static属性,也不能包含嵌套类,但嵌套类可以。而嵌套类不能声明为
private,一般声明为public,方便调用。
d. 匿名内部类
匿名内部类是没有访问修饰符的。
new 匿名内部类,这个类首先是要存在的。
所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。
匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。
举例:
package com.dome; public abstract class AnonymousInnerClass { //完整的成员方法 public void doSport() { System.out.println("运动ing"); } //抽象的方法 public abstract void doEat(String food); }
实例化:
package com.dome; public class Test { public static void main(String[] args) { //匿名内部类 AnonymousInnerClass amic=new AnonymousInnerClass() { public void doEat(String food) { System.out.println("Eating..."+food); } }; amic.doSport(); amic.doEat("西红柿"); } }
总结:只要一个类是抽象的类或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现