内部类

一、创建内部类

public class Test {
    //第一个内部类
    class Destination{
        private int i = 11;
        public int value(){return i;}
    }
    //第二个内部类
    class Parcel{
        private String label;
        //构造方法
        Parcel(String whereTo){
            label = whereTo;
        }
    }
}
Test.java

二、内部类的作用(一)——自动拥有外围类所有成员的访问权限

public class Test {
    private Object[] items;

    class Destination{
        private int i = 11;
        public int value(){return i;}
        //内部类可以直接调用外部类的成员变量(无视修饰符)
        public Object current(){
            return items[i];
        }
    }
       ...
}
Test.java

所以内部类(非static类时)自动拥有对其外围类所有成员的访问权限。
原理:当某个外部类对象创建一个内部类对象的时候,内部类对象会秘密捕获指向外部类的引用,然后访问外部类,就是通过这个引用选择外部成员。

三、内部类的作用(二)——获取对外部类对象的引用.this/.new

使用.this的作用

public class Test {
    
    class Destination{
        //获取引用之后,可调用其方法
        Destination(){
            Test.this.take();
        }
        //内部类获取外部类的引用
        public Test getTest(){
            return Test.this;
        }

    }
    
    public void take(){
        
    }
}
Test.java

使用.new的作用

public class NestingInterfaces {

    public static void main (String args[]){
        Test test = new Test();
        //通过.new方法 创建Test的内部类
        Test.Destination dest = test.new Destination();
    }

}
NestingInterfaces

注:但是如果你使用的是嵌套类(内部类设为static)就不需要对外部类对象的引用   例:DotNew.Inner do = new DotNew.Inner();

四、内部类与向上转型

当将内部类向上转型为其基类,尤其是转型为一个接口的时候。内部类能够使某个接口的实现完全不可见,并且不可用。(隐藏实现细节)

示例:

//接口类
public interface Contents{
   int value();
}
//实现类
class Pacel {
  //创建内部类继承接口
  private class PContents implemetns Contents{
    private int i = 11;
    public int value(){
      return i;
    }
  }
  //获取内部类并向上转型
  public Contents getContent(){
    return new PContents;
  }
}
//运行类
class Test{
  public static void main(String args[]){
    //创建类
    Pacel p = new Pacel();
    Contents content = p.getContene();
    //这样就封装了接口的实现。
  }
}
View Code

五、在方法和作用域内的内部类

举例:

//接口类
public interface Destination{
  String readLabel();
}

//实现类
class Parcel1{
  //方法
  public Destination getDestination(String label){
    //在方法内创建内部类,继承接口
    class PDestination implements Destination{
       public String readLabel(){
          return label;
       }
    }
    //内部类向上转型返回Destination
    reuturn new PDestionation;
  } 
}
View Code

作用:1.实现了某类型的接口,于是可以创建并返回其引用

2.解决一个复杂的问题,创建一个辅助类,但又不想这个类被公共使用。

六、匿名类

举例:(使用默认构造器生成Contents)

public interface Contents{
  public int value();
}

public class Parcel{
  public Contents contents(){
    //创建内部类
    return new Contents(){
       private int i=11;
       
       public int value(){
         return i;
       }
    }
  }
  //实现
  public static void main(String[] args){
    Parcel parcel = new Parcel;
    Contents content = parcel.contents();
  } 
}
View Code

解析:新建接口对象,并重写接口的方法

使用有参数的构造器:

//初始类
public class Wrappping {
  private int i;
  public Wrapping (int x){
     i = x;
  }

  public int value(){
    return i;
  } 
}

class Parcel3{
  public Wrapping getWrapping(int x){
    //调用父类的构造方法
    return new Wrapping(x){
      //重写父类的value()方法
      public int value(){
        //调用父类的value()方法
        return super.value()*24;
      }
    };
  }
}
View Code

解析:新建类对象,调用新对象的构造器,并重写方法,调用其父类的构造方法(被当做了一个公共的接口)

细节

①、如果定义了一个内部类,并需要调用外部定义的对象的时候,则编译器会将其引用参数为final。

②、匿名类不可能有命名构造器,所以说如何创造构造器的效果。

举例:

class Parcel{
  public Destination getDestination(final String dest,final float price){
    return new Destination(){
      private int cost;
      //在{}内根据传递而来的参数 初始化值。
      {
         cost = Math.round(price);
         if (cost>100){
          System.out.println("Nice");
         }
      }
      //直接获取方法的参数,初始化值
      private String label = dest;
      public String readLabel(){
         return dest;
      }
    }
  }
}
View Code

③、工厂方法 (略,以后有空再看)

七、嵌套类

定义:如果不需要内部对象与其外围类对象之间有联系,可以特地将内部类设置为static。

意义:①、不能从嵌套类中的对象访问非静态外部类的对象。(可以说,不含有外部类的指针了)

与普通内部类作对比:①、嵌套类可以有static数据和字段,二普通类不能有  ②、嵌套类还可以嵌套类,但是普通类不可以。

举例:

public class Parcel{
  protected static class ParcelDestional implements Destination{
    //静态数据
    private static String label = "fine";

    public String readLabel(){
      return labe;
    } 
    //静态方法
     public static void f(){
       System.out.println("asd");
     }
    //嵌套嵌套类
    static class H{
        
    }
  }
} 
View Code

(一)接口内部的类

解释:嵌套类可以作为接口的一部分,甚至可以在类内部实现外部接口。

举例:

public interface Pacel{
  void howdy(){
  }
  //在接口中创建嵌套类,并继承该接口,重写接口方法
  class Test implements Pacel{
     public void howdy(){
       System.out.println("asd");
     }
  }
}
View Code

八、为什么需要内部类

理由:一般来说内部类继承自某个类或者实现某个接口,内部类的代码操作用来创建它的外围类的对象。(将内部类的对象放置在外围类中)。

②、内个内部类都能独立的继承自一个(接口的)实现,无论外围类是否已经继承接口实现,对内部类都不影响。(不过能用外部类继承接口就用外部类)

③、可以使用外围类的private方法

其他特性:

①、内部类可以有多个实例,信息与其外围类对象信息对立。

②、在单个外围类中,可以让多个内部类实现统一接口,或继承同一类

③、创建内部类对象不依赖于外围类对象的创建。(指嵌套类)

九、闭包与回调

闭包:是个可调用对象,记录信息,这些信息来自创建它的作用域。(内部类就是面向对象的闭包:不仅包含外围类对象的信息,还有外围类的指针)

问题:有Callee继承自MyIncrement,但是还需要添加一个Increment接口中两个中含有相同的方法,且方法作用各不同,所以必须两个一起实现,就得用到内部类

/*前提条件*/
class MyIncrement {
  public void increment(){print("Other operation");}
  static void f(MyIncrement mi) {mi.increment()};
}

interface Increment{
  void increment();
}
前提条件
class Callee extends MyIncrement{
   private int i=0;
   public void increment(){
     ++i;
     System.out.println(i);
   }   

   //内部类
   private class Course implements Increment{
     public void increment(){
        Callee.this.increment();
     } 
   }
   //返回内部类
   public Increment getIncrement(){
     return new Course;  
   }
}

//统一类调用内部类的Increment的方法
class Calleer {
  private Increment in = null;
  public Caller (Increment increment){
    in = increment;
  }

  public void go (){
    in.increment();
  }
}


class Test{
  public static void main(String[] args){
    //调用自身的方法
    Callee c = new Callee();
    c.increment();
    //调用内部类的方法
    Calleer cc = new Calleer(c);
    cc.go();  
  }
}

作用:①、Closure实现了Incrementable,提供了一个返回Callee的钩子,无论谁获得Increment引用,都只能调用increment()。

②、Calleer对象可以使用Increment回调Callee对象。

原文地址:https://www.cnblogs.com/rookiechen/p/5443607.html