zoukankan      html  css  js  c++  java
  • 内部类

    一、创建内部类

    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对象。

  • 相关阅读:
    参考网站
    GridView手写事件,包括取主键、取值、更新、选择、删除
    jQuery通过滚轮滚动动态加载图片
    web前端开发人员和设计师必读文章推荐
    ASP.NET中常用代码
    构建高性能ASP.NET站点
    css实现类似相框的阴影div的shadow效果
    乐观复制算法8. 保证内容质量
    乐观复制算法附件C一致性模型
    乐观复制算法10.总结 附件A Happensbefore关系
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5443607.html
Copyright © 2011-2022 走看看