《编程思想》9.内部类

一.创建内部类
(1)内部类了解外围类,并能与之通信
(2)创建内部类方式:把类的定义置于外围类的里面

public class Parcel1 {
	
	//内部类1
	class Contents{
		private int i = 11 ;
		public int value(){
			return i ;
		}
	}
	
	//内部类2
	class Destination{
		private String label ;
		Destination(String whereTo){
			label = whereTo;
		}
		String readLabel(){
			return label ;
		}
	}
	
	public void ship(String dest){
		//创建内部类
		Contents c = new Contents();
		Destination d = new Destination(dest);
		System.out.println(d.readLabel());
	}
	
	public static void main(String[] args) {
		 Parcel1 p = new Parcel1();
		 p.ship("Tasmaia");
	}

}

二.链接到外部类
1.当生成一个内部类的对象时,此对象与制造它的外围对象之间就有了一种联系,所以能访问其外围对象的所有成员,而不需要任何条件。内部类还拥有其外围类所有元素的访问权。

2.内部类自动拥有对其外围所有成员的访问权。

public class Sequence {
	private Object[] items ;
	private int next = 0 ;
	public Sequence(int size){
		items = new Object[size];
	}
	public void add(Object x){
		if(next < items.length){
			items[next++] = x ;
		}
	}
	
	//内部类
	private class SequenceSelector implements Selector{
        private int i = 0 ; 
		public boolean end() { 
			//调用外部类的方法  items为private
			return i == items.length;
		} 
		public Object current() { 
			return items[i];
		} 
		public void next() {  
			if(i < items.length)
				i ++ ;
		} 
	}
	
	public Selector selector(){
		//生成内部类对象
		return new SequenceSelector();
	}
	public static void main(String[] args) {
		 //...
	}

}

三.使用.this与.new

public class MainJava { 
	 void f(){
		 System.out.println("DotThis.f()");
	 }
	 public class Inner{
		 public MainJava outer(){
		    //内部类生成对外部类对象的引用
			 return MainJava.this; //MainJava 为外部类
		 }
	 }
	 public Inner inner(){
		 return new Inner();
	 }
	 public static void main(String[] args) {  
		 MainJava dt = new MainJava();
		 MainJava.Inner dti = dt.inner();
		 dti.outer().f();
	 } 
}


//创建内部类对象
public class DotNew{
  public class Inner{};
  public static void main(String[] args){
    DotNew dn = new DotNew(); //生成外部类对象
    DotNew.Inner dni = dn.new Inner(); //生成内部类对象
   }
 }

要想直接创建内部类的对象,你不能按照你想象的方式,去引用外部类的名字DotNew,而是必须使用外部类的对象来创建改内部类对象。
拥有外部类对象之前是不可能创建内部类对象的。

4.内部类与向上转型
(1)当将内部类向上转型为基类,尤其是转型为一个接口的时候,内部类就有了用武之地。

5.在方法和作用域内的内部类
可以在一个方法里面或者在任意的作用域内定义内部类。

6.匿名内部类
(1)不使用匿名内部类

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

(2)使用匿名内部类

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

(3)在接口上使用匿名内部类


interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现

最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

(4)Thread类的匿名内部类实现


public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}

(5).匿名内部类只能使用一次,它通常用来简化代码编写

(6).但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

9.为什么需要内部类
(1)使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

(2)内部类使得多重继承的解决方案变得完整

//即必须在一个类中以某种方式实现两个接口。由于接口的灵活性,可以使用单一类或内部类
interface A{}

interface B{}

class X implements A,B{}

class Y implements A {
    B makeB(){
      return new B(){};
     }
  }

public class MultiInterfaces{
   static void takesA(A a){}
   static void takesB(B b){}
   public static void main(String[] args){
      X x = new X();
      Y y = new Y();
      takesA(x);
      takesA(y);
      takesB(x);
   }
 }
//如果拥有的是抽象的类或具体的类,而不是接口,那就只能使用内部类才能实现多重继承
class D {}

abstract class E {
  abstract void A();
}

class Z extends D {
   E makeE(){
       //匿名内部类 
	   return new E() {
       void A() { 
				
			}};
   };
  }
  }

public class MultiImplementation{
    static void takesD(D d){}
    static void takesE(E e){}
    public static void main(String[] args){
        Z z = new Z();
        takesD(z);
        takesE(z.makeE());
      }
   }

猜你喜欢

转载自blog.csdn.net/weixin_42763504/article/details/86665903