内部类就是可以将一个类的定义放在另一个类的定义内部
注意:每个类都会产生.class文件,其中包含了如何创建该类型对象的全部信息,当然内部类也会生成一个.class文件,不过与外部类不同,内部类如果嵌套在别的类中,只需要在外部类后面加上$,再加上内部类的名字。如果内部类是匿名的,则编译器会简单的产生一个数字作为其标识符
内部类分为四种:成员内部类,局部内部类,静态内部类(嵌套内部类),匿名内部类
成员内部类
成员内部类就是作为外部类的成员,成员内部类会自动拥有对外部类所有成员的访问权,包括private修饰的成员。因为当生成一个内部类的对象时,这个内部类对象隐式的保存了一个引用来指向外部类对象。
外部类要想访问内部类就需要通过内部类的实例对象来访问。
如果在外部类之外的地方要想获取内部类对象可以用.new语法(外部类名.内部类名 引用 = 外部类对象名.new 内部类名(); )
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员可以用 外部类名.this来获取外部类的对象,然后通过调用对象来获取外部类的成员或方法
注意:在拥有外部类对象之前是不可能创建内部类对象的,所以成员内部类里不能有static变量或方法
下面来看一个简单的例子
public class Outer {//外部类
private int a = 9;
Inner i = new Inner();
class Inner{//内部类
private int a = 5;
//如果在内部类中需要生成对外部类对象的引用,可以使用.this
Outer outer = Outer.this;//获取到了外部类对象
}
public void print(){
System.out.println("外部类成员a="+a);
//通过内部类对象来调用内部类的成员和方法
System.out.println("内部类成员a="+i.a);
}
}
public class Test{
public static void main(String[] args){
Outer o = new Outer();
o.print();
//可以在实例化内部类对象
//外部类名.内部类名 引用 = 外部类对象.new 内部类名();
Outer.Inner i = o.new Inner();//获取到了内部类对象
}
}
输出:外部类成员a=9
内部类成员a=5
《Thinking in java》中有一个内部类与向上转型
可以将内部类向上转型,从而实现了某个接口的对象,得到此接口的引用。内部类向上转型的好处就是内部类能够完全不可见,从而隐藏实现细节
我们知道类的访问权限只能是包访问权限和public,但是内部类的访问权限可以是protected和private
public class Outer{
private class Aa implements A{}
protected class Bb implements B{}
public A a(){
return new Aa();
}
public B b(){
return new Bb();
}
}
public class Test{
public static void main(String[] args){
Outer o = new Outer();
A i = o.a();//向上转型了
B j = o.b();
}
}
局部内部类
局部内部类就是在方法的作用域内创建一个类,当然,这个类仅限于这个方法内部使用,对方法外不可见
注意:局部内部类不能有访问修饰符,因为它不是外部类的一部分
public class Outer{
public A m(){
//注意这个内部类不能有访问修饰符
class Inner implements A{
private a = 9;
}
return new Inner();//Inner向上转型了
}
}
public class Test{
public static void main(String[] args){
Outer o = new Outer();
A a = o.m();
}
}
静态内部类
如果不需要内部类对象与外部类对象之间有联系,可以将内部类声明为static,这个类在没有外部类的对象的情况下也可以创建对象,并且它不能使用外部类的非static成员变量或者方法
public class Test {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
}
}
public class Outter {
static class Inner {
public Inner() {
}
}
}
正常情况下,接口类是不能有任何代码的,但是嵌套类可以在接口中存在,并且放到接口中的类自动的就是public和static
接口中嵌套类的作用在于可以生成一些可以被接口实现类所共同使用的代码,让不同实现类可以共用。
http://blog.csdn.net/Jack_windows/article/details/75145096
匿名内部类
匿名内部类就是没有名字的内部类。使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用
使用匿名内部类的前提是,你不需要对父类做任何扩展,只能是重写其中的方法,因为即使你在匿名内部类中写了一个父类中没有的方法,你也不能在外部使用它。还有一点就是匿名内部类不能有自己的构造函数。
先来看一个例子
interface A{}
public class Outer{
public A method(){
return new A(){
private int a = 8;
public int value(){return a;}
}
}
}
上面的代码与下面的是一样的,只不过上面的是用匿名内部类写的
public class Outer{
class B implements A{
private int a = 8;
public int value(){return a;}
}
public A method(){
return new B();
}
}
用匿名内部类来写工厂方法就会方便很多,通常我们会为每个功能设计一个工厂,这样便于添加新的工厂
interface Car{
public void produce();
}
interface Factory{
Car makeCar();
}
//宝马
public class BMW inplements Car{
public void produce(){
System.out.println("produce BMW");
}
}
//奥迪
public class Audi implements Car{
public void produce(){
System.out.println("produce Audi");
}
}
//制造宝马的工厂
public class BMWFactory implements Factory{
Car makeCar(){
return new BMW();
}
}
//制造奥迪的工厂
public class AudiFactory implements Factory{
Car makeCar(){
return new Audi();
}
}
public class CarFactory{
//传进工厂,然后工厂生产相应的车
public void make(Factory factory){
Car cars = factory.makeCar();
cars.produce();
}
}
//测试类
public class Test{
public static void main(String[] args){
CarFactory p = new CarFactory();
p.maker(BMWFactory);
}
}
上面的代码用匿名内部类改写一下
interface Car{
public void produce();
}
interface Factory{
Car makeCar();
}
//宝马
public class BMW inplements Car{
public void produce(){
System.out.println("produce BMW");
}
public static Factory factory = new Factory(){
Car makeCar(){
return new BMW();
}
}
}
//奥迪
public class Audi implements Car{
public void produce(){
System.out.println("produce Audi");
}
public static Factory factory = new Factory(){
Car makeCar(){
return new Audi();
}
}
}
public class CarFactory{
//传进工厂,然后工厂生产相应的车
public void make(Factory factory){
Car cars = factory.makeCar();
cars.produce();
}
}
//测试类
public class Test{
public static void main(String[] args){
CarFactory p = new CarFactory();
p.make(BMW.factory);
}
}
内部类引用外部类的变量时这个变量必须是final的
http://blog.csdn.net/speedme/article/details/8041524
有一个关于内部类的文章写很好,下面是链接
http://www.cnblogs.com/dolphin0520/p/3811445.html