java内部类详解

一、分类:

    内部类:成员内部类,静态内部类,局部内部类,匿名内部类

二、成员内部类

    定义在外部类成员区,作为外部类的一个成员。

public class  Demo{

	public static void main(String[] args) throws Exception
	{
		new Outer().new Inner().prints();
	}
}

class Outer{    //外部类

	private int i;

	class Inner{    //内部类

		private int i = 1;

        Inner() {
			System.out.println("Inner");  //内部类构造函数
		}
		void prints(){
			System.out.println("Inner prints method !" + i);  
		}
	}

	Outer() {  //外部类构造方法
		System.out.println("Outer");
	}
}
      
      /*
         Outer
	 Inner
	 Inner prints method ! 1
      */

注意事项:
       1.内部类创建对象需要外部类先创建一个对象,即new Outer().new Inner()
       2.内部类创建时会持有外部类对象的隐式引用,所以外部类的private对内部类一样可见,这也是普通内部类需要先创建外部类对象才能被创建的原因。但内部类的private对外部类不可见。

        
       3. 当外部类和内部类成员或方法重名时默认调用内部类成员。若类的成员和内部类方法
           的成员同名,则调用方法内的临时变量

       4. 例Demo编译后出现三个class文件,内部类有单独的class文件,命名方式是   外部类$内部类.class

         


三、静态内部类

       和普通内部类一样定义在外部类成员区。只是加了static修饰词。

public class  Demo{

	public static void main(String[] args) throws Exception
	{
		//new Outer().new Inner().prints(); //普通内部类
		new Outer.Inner().prints();//静态内部类
	}
}

class Outer{

	static class Inner{

		void prints(){
			int i = 2;
			System.out.println("Inner prints method !" + i);
		}
	}
}

注意:1.不用外部类先实例化,就像调用静态变量一样用类名引用实例化内部类就可以。new Outer.Inner().  注意Outer不用写()!
          2.不持有外部类引用,只可以随意引用外部类中的静态变量。

        

四、局部内部类

       定义在外部类方法中的类。

public class  Demo{
	public static void main(String[] args) throws Exception
	{
		new Outer().inner();
	}
}

class Outer{

    private int i;

    public void inner(){
        class Inner{
		void prints(){
			int i = 2;
			System.out.println("Inner prints method !" + i);
		}
	}
	new Inner().prints();
	}

}
输出:Inner prints emthod ! 2

注意: 1.编译后仍然出现三个class文件,但命名略有不同,Outer$1Inner(). 因为临时内部类在同一个类中可能同名。所以加数字作为区分。

            重复情况:

class Outer{

    public void inner(){  //外部类的方法1
	class Inner{ //Inner --- 1
		void prints(){ //prints---1
			int i = 2;
			System.out.println("Inner prints method !" + i);
		}
	}
	new Inner().prints();
	}//endInner

	/****不会报错****/
    public void inner2(){   //外部类的方法2
	class Inner{ //Inner --- 2
		void prints(){  //  prints---2
			int i = 3;
			System.out.println("Inner2 prints method !" + i);
		}
	}
	new Inner2().prints();
	}//endInner2

}

          2. 局部内部类等同局部变量,方法执行完毕就等待虚拟机回收,无法在方法外去引用。
          3.  局部内部类在构造对象时也持有外部类的引用,所以同样不受外部类权限控制
          4.  局部内部类不能用static public private protected修饰,但可以用final。

五、匿名内部类

    先来看一个例子。

public class  Demo{

	public static void main(String[] args) throws Exception
	{
		new Outer().set();
	}
}

abstract class Father{
	abstract public void getInstance();
}

class Outer{

	Outer() {
		System.out.println("Outer");
	}
    
	public void get(Father f) {
	    f.getInstance();
	}

	public void set() {
	    get(new Father(){
			@Override
				public void getInstance(){
				System.out.println("I am a Father !");
			} //end getInstance
		} //end 匿名内部类,整个匿名内部类只有这一个方法,整个类体到此结束
		);//end get()方法刚刚结束!
	}//end set()方法结束!
}
输出:

Outer

I am a Father !

例子中Father类作为abstract是不能实例化的,但在Outer类的set()中

public void set() {
    get(new Father(){
    @Override
        public void getInstance(){
            System.out.println("I am a Father !");
        }
    }
    );//endget,注意形式是get( new Father() { 方法 } );
}
  却可以看到有一个new Father() !是错了吗?再来看一下生成的文件:

             java内部类详解_第1张图片

有四个?!  Outer$1.class是什么?!
我们来看一下:

java内部类详解_第2张图片

很明显有一个Outer$1类继承了Father.被实例化的不是Father而是它的子类!

但我们知道JAVA类名字不能以数字开头,所以很明显这就是get方法中被传入的匿名类,命名规则就是  Outer$数字 作为名字。默认是继承Father.  也就是说在new的时候用的哪个类的名字,这个匿名内部类就是继承哪个类,并且持有父类的指针。但并不能访问父类的私有成员,因为只是继承关系。

       类有继承关系,接口有实现关系,所以接口也是可以有匿名内部类。写图形界面的时候的事件监听器的注册就是匿名内部类的形式,只不过不是类而是接口而已。匿名内部类大多作为实参传给函数。一个常见的例子:

firstButton.addActionListener(new ActionListener() {  
            @Override  
            public void actionPerformed(ActionEvent e) {  
                getTxtValue().setText("事件触发!");  
            }  
        });
  其中ActionListener是一个接口,匿名内部类被回调成为接口类型对象注册监听器,是多态的一种体现。





 

你可能感兴趣的:(java,内部类,匿名内部类)