一,什么是内部类?
内部类是指在一个外部类的内部再定义一个类,类名不需要和文件名相同。而对于一般的,类定义代码不嵌套在其它类定义中的类,成为顶层(top-level)类,对于一个内部类,包含定义代码的类称为外部类(outer class)。
内部类和外部类的比较:
1,内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)。
2,内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现 outer.class和outer$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。
二,内部类的作用?
内部类存在的目的应该只是为它的外围类(outer class)提供服务,如果内部类可能用于其它的某个环境中,它就应该是顶层类。
内部类的作用(这个是这篇博客总结的比较好http://andy136566.iteye.com/blog/1061951):
可以很好的实现隐藏(因为内部类可以有private与protected权限)。
内部类有外部类所以元素的访问权限。
可以实现伪多重继承。
三,内部类的分类
A.成员内部类
成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。 要注意的是,成员内部类不能含有static的变量和方法。成员内部类需要先创建了外部类,才能创建它自己的。
在成员内部类要引用外部类对象时,使用outer.this来表示外部类对象
而需要创建内部类对象,可以使用outer.inner obj = outerobj.new inner();
public class Outer {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.print("Outer.new");
inner = outer.getInner();
inner.print("Outer.get");
}
// 个人推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时
public Inner getInner() {
return new Inner();
}
public class Inner {
public void print(String str) {
System.out.println(str);
}
}
}
B.局部内部类
局部内部类,是指内部类定义在方法和作用域内(局部内部类用的比较少)
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();
}
}
局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的
C.静态内部类
就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用ou ter.inner,即不需要创建外部类,也不需要创建内部类。嵌套类和普通的内部类还有一个区别:普通内部类不能有static数据和static属性,也不能包含嵌套类,但嵌套类可以。而静态内部类,一般声明为public,方便调用,如果声明为private只能在外部类的内部使用。
public class Outer {
static int x =1;
static class Nest {
void print(){
System.out.println("Nest "+x);
}
}
public static void main(String[] args){
Outer.Nest nest = new Outer.Nest();
nest.print();
}
}
因为静态嵌套类和其他静态方法一样只能访问其它静态的成员,而不能访问实例成员。因此静态嵌套类和外部类(封装类)之间的联系就很少了,他们之间可能也就 是命名空间上的一些关联。上面例子中你需要注意的就是静态嵌套类的声明方法 new Outer.Nest() 连续写了两个类名,以至于我们都怀疑前面的Outer是个包名了,好在包名一般都小写的,要不还真分不清……
D.匿名内部类 当我们把内部类的定义和声明写到一起时,就不用给这个类起个类名而是直接使用了,这种形式的内部类根本就没有类名,因此我们叫它匿名内部类。匿名类在事件处理中最常用。
public class Dog {
public interface Pet {
public void beFriendly();
public void play();
}
public static void main(String[] args){
Pet dog = new Pet(){
@Override
public void beFriendly() {
System.out.println("蹭蹭你^_^");
}
@Override
public void play() {
System.out.println("把飞盘叼给你,逼你把飞盘丢出去,然后它再捡回来让你继续扔,连续500次^_^");
}
};
dog.beFriendly();
dog.play();
}
}
好吧我们再看一个例子,方法参数内的匿名内部类:在事件处理中很常见
public class Dog {
static abstract class Ball {
abstract String getName();
}
void play(Ball b){
System.out.println(b.getName());
}
public static void main(String[] args){
Dog dog = new Dog();
dog.play(new Ball(){
@Override
String getName() {
return "qiu qiu";
}});
}
}