zoukankan      html  css  js  c++  java
  • java编程思想第四版第十章总结

    1. 内部类的特性

    • 他允许你把一些逻辑相关的类组织在一起。

    2. 使用.this

    • 如果你需要在内部类中堆外部类进行应用,可以使用外部类的名字后面加.this。下面展示了如何使用 .this
      package net.mindview.innerclasses;
      
      public class DotThis {
          void f(){
              System.out.println("DotThis.f()");
          }
          
          public class Inner {
              public DotThis outer() {
                  System.out.println(DotThis.this);
                  return DotThis.this;
              }
          }
          
          public Inner inner(){
              return new Inner();
          }
          
          public static void main(String[] args) {
              DotThis dt = new DotThis();
              DotThis.Inner di = dt.inner();
              di.outer().f();
          }
      
      }

     3.使用.new

    • 如果想要创建某个外部类的内部类,可以使用外部类对象.new 内部类:
    • 如果想new一个内部类, 不能使用外部类.new 内部类。必须使用外部类的对象来创建内部类的对象。    用法如下:
      package net.mindview.innerclasses;
      
      public class DotNew {
          
          public class Inner {
              
          }
          public static void main(String[] args) {
              DotNew dn = new DotNew();
              DotNew.Inner di = dn.new Inner();
          }
      }

    4. 方法的内部类

    • 这里只说两点:
      • 方法的内部类有效作用域是在方法内,方法外部可以调用
      • 方法的内部类,并不是说方法被调用的时候才创建了,实际上,这个类和其他类没有什么不同,他们在使用之前,已经经过编译了.
        package net.mindview.innerclasses;
        
        /**
         * 方法内部类的作用域就在方法内,方法外不可以访问.
         * @author samsung
         *
         */
        public class Parcel5 {
            public Destination destination(String s){
                //在方法里定义了一个内部类
                class PDestination implements Destination{
                    private String label;
                    public PDestination(String label){
                        System.out.println(this);
                        this.label = label;
                    }
                    @Override
                    public String readLabel() {
                        return label;
                    }
                }
                
                return new PDestination(s);
            }
            public static void main(String[] args) {
                Parcel5 p = new Parcel5();
                System.out.println(p.destination("上海").readLabel());
                System.out.println(p.destination("北京").readLabel());
            }
        
            /**
             * 注意:PDestination定义在方法里面,并不是说只有调用方法的时候,这个类才被创建.
             * 实际上,这个类和其他类一样,已经经过编译了.
             */
        }

    5. 定义在作用域内的内部类, 此作用域在方法的内部.

    • 定义在方法作用域内部的类, 只在作用域内部有效
    package net.mindview.innerclasses;
    
    public class Parcel6 {
        private void internalTracking(boolean b){
            if(b){
                class TrackingSlip{
                    private String id;
                    TrackingSlip(String s){
                        id = s;
                    } 
                    
                    String getSlip(){
                        return id;
                    }
                }
                
                TrackingSlip ts = new TrackingSlip("100");
                String s = ts.getSlip();
            }
            //作用域外不可使用
            //TrackingSlip ts = new TrackingSlip("100");
        }
        
        public void track(){
            internalTracking(true);
        }
        
        public static void main(String[] args) {
            Parcel6 p = new Parcel6();
            p.track();
        }
    }

    6.匿名内部类

    • 默认构造器匿名内部类
      package net.mindview.innerclasses;
      
      public class Parcel7 {
          public Contents contents(){
              //定义了一个匿名内部类.将返回值和创建类放在了一起
              return new Contents(){
                  private int i = 11;
                  @Override
                  public int value() {
                      return i;
                  }
              };
          }
          public static void main(String[] args) {
              Parcel7 p = new Parcel7();
              Contents c = p.contents();
              System.out.println(c.value());
      
          }
      
      }
    • 代参数构造器的匿名内部类
      package net.mindview.innerclasses;
      
      public class Wrapping {
          
          private int i;
          public Wrapping(int x){
              this.i = x;
          }
          public int value(){
              return i;
          }
      }
      package net.mindview.innerclasses;
      
      public class Parcel8 {
          public Wrapping wrapping(int x){
              return new Wrapping(x){
                  @Override
                  public int value(){
                      return super.value()*47;
                  }
              };
          }
          
          public static void main(String[] args) {
              Parcel8 p = new Parcel8();
              Wrapping w = p.wrapping(20);
              System.out.println(w.value());
          }
      
      }

      这里需要注意的是, 虽然Wrapping是一个导出类, 却依然被当成了一个接口来使用.

    • 匿名内部类中使用外部对象, 这外部的这个对象必须是final的
      package net.mindview.innerclasses;
      
      public class Parcel9 {
          public Destination destination(final String x){
              final String m = null;
              //匿名内部类
              return new Destination(){
                  //在内部类中使用到了外部的对象
                  private String label = m;
                  private String abc = x;
                  @Override
                  public String readLabel() {
                      return label;
                  }
              };
          }
          public static void main(String[] args) {
              Parcel9 p = new Parcel9();
              System.out.println(p.destination("20").readLabel());
          }
          
          /**
           * 定义一个匿名内部类, 如果希望在匿名内部类中使用外部的对象, 
           * 那么编译器要求外部类的这个参数必须是final的. 如果你没有将这个类定义为final
           * 编译器会报错
           */
      
      }
    • 在匿名内部类中使用类似构造器的行为. 我们知道匿名内部类没有类名, 因此他不可能有命名构造器. 但通过实例初始化可,就鞥够达到为匿名内部类创建一个构造器的效果
      package net.mindview.innerclasses;
      
      abstract class Base{
          public Base(int i){
              System.out.println("Base构造器, i=" + i);
          }
          
          public abstract void f();
      }
      public class AnonymousConstructor {
          /**
           * 此处的i不要求是final的,因为这个i只是传递给了匿名
           * 变量的构造器,并没有在匿名内部类内部使用.
           */
          public static Base getBase(int i){
              return new Base(i){
                  {
                      System.out.println("这里可以类似构造器进行初始化");
                  }
                  @Override
                  public void f() {
                      System.out.println("匿名函数f()");
                  }
                  
              };
          }
          public static void main(String[] args) {
              AnonymousConstructor amc = new AnonymousConstructor();
              amc.getBase(100).f();
          }
      
      }

     7. 再谈工厂设计模式.

      再上一章中说了工厂设计模式. 本书中的案例是对象工厂设计模式. 来看看是怎么写的

    package net.mindview.innerclasses.factory.MethodFactory;
    /**
     * 服务类
     */
    interface Service{
        void method1();
        void method2();
    }
    
    /**
     * 工厂类
     */
    interface ServiceFactory {
        Service getService();
    }
    
    class Implementation1 implements Service{
    
        @Override
        public void method1() {
            System.out.println("Implementation1 method1");
        }
    
        @Override
        public void method2() {
            System.out.println("Implementation1 method1");
        }
        
    }
    
    class Implementation2 implements Service{
    
        @Override
        public void method1() {
            System.out.println("Implementation2 method1");
        }
    
        @Override
        public void method2() {
            System.out.println("Implementation2 method1");
        }
        
    }
    
    class ImplementationFactory1 implements ServiceFactory{
        @Override
        public Service getService() {
            // TODO Auto-generated method stub
            return new Implementation1();
        }
    }
    
    class ImplementationFactory2 implements ServiceFactory{
        @Override
        public Service getService() {
            // TODO Auto-generated method stub
            return new Implementation2();
        }
    }
    
    public class Factories {
        public static void serviceSustomer(ServiceFactory factory){
            factory.getService().method1();
            factory.getService().method2();
        }
        public static void main(String[] args) {
            serviceSustomer(new ImplementationFactory1());
            serviceSustomer(new ImplementationFactory2());
        }
    
    }

      我们还可以将这种方式以内部类的方式来实现

    package net.mindview.innerclasses.factory.methodFactoryInnerClass;
    /**
     * 服务类
     */
    interface Service{
        void method1();
        void method2();
    }
    
    /**
     * 工厂类
     */
    interface ServiceFactory {
        Service getService();
    }
    
    /**
     * 每一种服务,提供一种工厂. 这种工厂专门创建这种服务.
     */
    class Implementation1 implements Service{
        private Implementation1(){}
        @Override
        public void method1() {
            System.out.println("Implementation1 method1");
        }
    
        @Override
        public void method2() {
            System.out.println("Implementation1 method1");
        }
        
        //让工厂在内部实现
        public static ServiceFactory factory = new ServiceFactory(){
            @Override
            public Service getService() {
                return new Implementation1();
            }
            
        };
        
    }
    
    class Implementation2 implements Service{
    
        @Override
        public void method1() {
            System.out.println("Implementation2 method1");
        }
    
        @Override
        public void method2() {
            System.out.println("Implementation2 method1");
        }
    
        //让工厂在内部实现
        public static ServiceFactory factory = new ServiceFactory(){
            @Override
            public Service getService() {
                return new Implementation2();
            }
            
        };
        
    }
    
    public class Factories {
        public static void serviceSustomer(ServiceFactory factory){
            factory.getService().method1();
            factory.getService().method2();
        }
        public static void main(String[] args) {
            serviceSustomer(Implementation1.factory);
            serviceSustomer(Implementation2.factory);
        }
    }

      我的理解是: 第一种工厂的含义是: 我现在需要一种服务, 然后我找到对应的工厂, 为我提供服务. 工厂再去找对应这种服务的实体.

      而第二种方式呢, 我现在需要服务. 直接就去找这种服务对应的工厂就可以了. 也就是工厂内置了. 就像大公司下有多个子公司, 每个子公司都有自己的工厂.我要那种类型的东西,他就自己给生产了

    8. 嵌套类

      如果内部类对象预期外围类对象之间不需要有联系, 那么可以将内部类声明为static的。这种累通常称为嵌套类。要想理解static定义的内部类的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建他的外围类对象。然而,当内部类是static的时候, 就不是这样了。嵌套类意味着:

    1. 要创建嵌套类的对象, 并不需要外围类的对象。
    2. 不能从嵌套类的对象中访问非静态的对象
    3. 普通的内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以有这些东西
      package net.mindview.innerclasses;
      
      public class Parcel11 {
          //ParcelContent被定义为static的,所以是一个嵌套类
          private static class ParcelContent implements Contents {
              int i = 11;
              @Override
              public int value() {
                  return i;
              }
          }
          
          //ParcelDestination 是一个嵌套类. 被定义为static的.所以,它内部可以的有static的成员和方法
          private static class ParcelDestination implements Destination {
              private String label;
              private ParcelDestination(String label){
                  this.label = label;
              }
              @Override
              public String readLabel() {
                  return label;
              }
              
              public static void f(){
                  System.out.println(AnotherLabel.x);
                  //b()方法是访问不到的
                  //AnotherLabel.b();
              }
              static int x = 10;
              //他是嵌套在嵌套类内部的嵌套类.
              static class AnotherLabel{
                  //内部定义了两个和外部一样的成员方法, 竟然不冲突
                  public static void f(){
                      System.out.println("这时静态类的静态方法");
                  }
                  static int x = 10;
                  //嵌套类中的非静态方法不能被外部访问到. 所以这个方法没有任何意义
                  public void b(){
                      System.out.println("这时静态类中的静态方法b()");
                  }
              }
          }
          
          public static Contents getContents(){
              return new ParcelContent();
          }
          
          public static Destination getDestination(String s){
              return new ParcelDestination(s);
          }
          
          public static void main(String[] args) {
              System.out.println(getContents().value());
              System.out.println(getDestination("北京").readLabel());
              
              //嵌套类中,不能访问非静态方法
              //ParcelDestination.readLabel();
              //但是可以方法静态方法
              ParcelDestination.f();
              
              //嵌套类的使用方式是,类似于静态方法. 将其作为静态方法来使用.
              ParcelDestination.AnotherLabel.x=1;
              System.out.println(ParcelDestination.AnotherLabel.x);
              
              ParcelDestination.AnotherLabel.f();
              //下面这样写是不对的
              //ParcelDestination.AnotherLabel.b();
          }
      
      }

      观看上面说的文字,会有些难以理解,所以, 将这段代码敲一遍,就理解什么意思了。动手很重要啊

    9. 接口内部的类

    • 首先,接口里不能放置任何代码, 但是嵌套类可以.
    • 你放到接口中的任何类都自动式public static的.
    • 你可以在内部类中实现外围类的接口. 示例如下:
      package net.mindview.innerclasses;
      /**
       * 定义在接口内部的类
       */
      public interface ClassInInterface {
          void howdy();
          //这里static必须是显示标记出来的,否则这个类将不能运行
          static class Test implements ClassInInterface {
      
              @Override
              public void howdy() {
                  System.out.println("Howdy!");
              }
      
              public static void main(String[] args) {
                  Test t = new Test();
                  t.howdy();
              }
          }
      }

      注意, 如果想运行main方法, 这里的嵌套类必须是static的.

    • 如果想创建某些公共代码, 使得他们可以被某个接口的所有实现类所共用, 那么使用接口内部的嵌套类会显得很方便.
    • 例如: 我们可以在每个类中写一个mian方法用来测试这个类, 这样做有一个缺点, 那就是要写好多遍,而且, 必须通过编译器的编译, 我们可以使用嵌套类改善
      package net.mindview.innerclasses;
      
      public class TestBed {
          public void f(){
              System.out.println("f()");
          }
          
          static class Testers{
              public static void main(String[] args) {
                  TestBed t = new TestBedTest();
                  t.f();
              }
          }
      }

      再说的白话一点,就是在接口中定义一个这样的嵌套类. 然后定义mian方法, 在main方法中使用嵌套类. 当有一个新的对象继承了这个类的时候, 就在这个类中的main方法进行测试就好了. 这样的好处是, 当我打包发布到正式环境的时候, 我想删除所有的main方法,因为他们的存在也会被编译器编译, 降低效率. 如果只有一个接口的嵌套类中定义的main方法,那么删起来就方便很多了。不明白的话,在看下面这个例子,就懂了

      package net.mindview.innerclasses;
      /**
       * 定义在接口内部的类
       */
      public interface ClassInInterface {
          void howdy();
          //这里static必须是显示标记出来的,否则这个类将不能运行
          static class Test implements ClassInInterface {
      
              @Override
              public void howdy() {
                  System.out.println("Howdy!");
              }
      
              public static void main(String[] args) {
                  //测试第一个实现了接口的类
                  ClassInInterface t = new Test();
                  t.howdy();
                  //测试第二个实现了接口的类
                  ClassInInterface t1 = new ClassInInterfaceTest();
                  t1.howdy();
              }
          }
      }
      package net.mindview.innerclasses;
      
      public class ClassInInterfaceTest implements ClassInInterface{
      
          @Override
          public void howdy() {
              System.out.println("hhhh");
          }
      }
    • 接口中嵌套类如何创建实例化对象。 参考习题20
      package net.mindview.innerclasses.test20;
      interface InnerInInterface{
          static class Inner{
              public Inner(){
                  System.out.println("嵌套类构造方法");
              }
          }
      }
      
      public class Test20 {
          public static void main(String[] args) {
              //直接使用  new 外围类.嵌套类
              InnerInInterface.Inner inner = new InnerInInterface.Inner();
          }
      }

    10. 从多层嵌套类中访问外部类的成员

      注意下面这个例子是如何创建内部类的。

    package net.mindview.innerclasses;
    /**
     * 多层嵌套类访问外部成员
     */
    
    class A{
        private void f(){};
        class B{
            private void b(){};
            class C {
                void c(){
                    f();
                    b();
                };
            }
        }
    }
    public class MutliNestingAccess {
    
        public static void main(String[] args) {
            A a = new A();
            A.B b = a.new B();
            A.B.C c = b.new C();
            c.c();
        }
    
    }

    iooo

  • 相关阅读:
    基本目标与达成方法
    终于搞定在VS2010中将CString转换为const char*
    【HBase学习之一】HBase简介
    Origin2017画分组柱状图
    映射是什么?函数是什么?映射与函数的关系?
    PPT一次性禁用所有动画效果
    跨模态检索技术调研
    卷积核与特征提取
    深入理解卷积层,全连接层的作用意义
    cbow 与 skip-gram的比较
  • 原文地址:https://www.cnblogs.com/ITPower/p/8567231.html
Copyright © 2011-2022 走看看