天天看点

黑马程序员——java基础----面向对象(三)内部类

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 内部类 1,什么叫内部类?

         顾名思义,内部类就是定义在一个类中的类。

2,为什么会有内部类?怎么来的?

         当我们进行java开发时,有时需要实现一个仅包含1-2个方法的接口。

例 : 在学习集合框架的时候,有一个迭代器(Iterator接口),它里面就有一个方法iterator(),是专门用来给Colleaction集合进行迭代的,查看其底层发现它是嵌入在集合接口内部的。

例 : 在我们学习GUI时,当一个display组件需要一个事件回调方法时,如:一个按钮的ActionListener时,也是用到了内部类。 那么,以上两个例子要说明什么呢?

        通过上面两个例子,我们会发现,如果我们不用内部类的方式来完成,而是使用普通类来实现这些操作,最终会得到很多仅在单个位置上使用的小型类,仅仅是为类一个小小的功能,就要创建一个类,是不是有点浪费呢? 所以为了解决这个问题就出现了内部类这个看上去很难懂的类。

当然,内部类还有很多理由值得我们来用, 

  理由(1)内部类可以直接访问外部类中的成员,包括私有。

  理由(2)内部类可以对同一个包中的其它类隐藏起来。

  理由(3)当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较方便。

3,内部类的访问规则

        (1)内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类引用,格式:外部类名.this。

        (2)外部类要访问内部类,必须要建立内部类对象。

代码:

//外部类
class Outer {
	//外部类私有成员变量
	private int x = 3;//Outer.this.x
     //内部类
	class Inner {
		//内部类成员
		int x = 4;//this.x
		//内部类成员方法
		void function() {
	                //内部类局部变量
			int x = 6;//x
			System.out.println("Inner :" + x);//6
			System.out.println("Inner :" + this.x);//4
			//内部类可以直接访问外部类成员,包括私有
			System.out.println("Inner :" +Outer.this. x);//3
		}
	}
    //外部类成员方法
	void method() {
       //创建内部类成员变量
       Inner in = new Inner();//外部类要访问内部类必须要创建内部类对象。
       //调用内部类成员方法
       in.function();
	}

}
//测试类
public class InnerDemo {
	public static void main(String[] args) {
		//创建外部类对象
		Outer out = new Outer();
		//调用外部类成员方法。
		out.method();
             //直接访问内部类中的成员方法
              Outer.Inner outin = new Outer().new Inner();
              outin.function(); 
	}
}
           

4,当内部类在成员位置上,并且被修饰符所修饰。

         比如:private:将内部类在外部类中进行封装。

                      static:内部类具备静态的特性。 当内部类被static修饰后,只能直接访问外部类的static成员。出现了访问权限。 代码:

//外部类
class Outer1
{  
   //私有静态成员变量
   private static int x= 3;
   //静态内部类1
    static class Inner1{
    	//静态内部类中的静态成员变量
	    static int x = 4;
	    //静态内部类中的静态成员方法
	     static void function(){
	    	 //非静态访问了静态
		     int x = 5;
		    //打印静态成员方法中的非静态变量 
		   System.out.println(x);
		   //打印静态内部类中静态成员变量
		   System.out.println(Inner1.x);
		   //打印外部类的静态成员变量
	           System.out.println(Outer1.x);
		   
	   }
   } 
    //静态内部类2
    static class Inner2{
    	//静态内部类的非静态成员方法
    	void function(){
                 //静态内部类访问外部类的静态成员变量
    		 System.out.println(Outer1.x);
    	}
    }
}
//测试类
public class InnerDemo2 {
	public static void main(String[] args) {
		//外部类访问静态内部类的静态方法
		Outer1.Inner1.function();
		//外部类访问静态内部类的非静态方法
                new Outer1.Inner2().function();
       
	}

}
           

注意:当内部类中定义了静态成员,该内部类必须是静态的。(因为静态只能访问静态)

            当外部类的静态方法访问内部类时,内部类必须是静态的(同上)

5,什么时候使用内部类?

            当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部类事物在使用外部类事物的内容。

6,当内部类定义在局部时

         (1)不可以被成员修饰符修饰。

         (2)可以直接访问外部类中的成员,因为还持有外部类的引用。但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

代码:

//外部类
class Outer2{
	int x = 3;//Outer2.this.x
	void method(final int a){
	      final int y = 4;
		//局部内部类
		class Inner{
		     void function(){
			//局部内部类访问局部变量时,该变量必须是final常量。
			System.out.println(y);
			System.out.println(a);
			System.out.println(x);//还持有外部类的引用
		     }
		}
		//外部类成员方法访问局部内部类的成员方法。
		new Inner().function();
	}
	
}
//测试类
public class InnerDemo3 {
	public static void main(String[] args) {
	   //调用方法	
	   new Outer2().method(7);
	}

}
           

7,匿名内部类

      (1)匿名内部类其实就是内部类的简写格式。

      (2)定义匿名内部类前提:内部类必须是继承一个类或者实现接口。

      (3)匿名内部类的格式:new 父类或者接口(){定义子类的内容}

      (4)匿名内部类是一个匿名子类对象,可以理解为带内容的对象。

      (5)匿名内部类中定义的方法最好不要超过三个。

代码:

//抽象类
abstract class AbsDemo{
        //抽象方法
	abstract void show();
}
//外部类
class Outer3{
	int x = 3;
	public void function(){
		//创建匿名内部类的对象
		AbsDemo d= new AbsDemo(){//父类引用指向子类对象
			void show(){
				System.out.println(x);
			}
		};
		//实现接口的子类对象调用复写父类的方法。
		d.show();
//-------------------------------------------------------------------		
		//通过匿名内部类的匿名子类对象来调用复写父类的方法。
		new AbsDemo(){//父类引用指向子类对象
			void show(){
				System.out.println(x);
			}
		}.show();	
	}
}
//测试类
public class InnerDemo4 {
      public static void main(String[] args) {
       //通过外部类匿名对象调用方法
        new Outer3().function();
}