• Java编程思想学习笔记_3(继承,内部类)


    一、继承与清理

      如果某个类需要去清理自身的资源,那么必须用心为其创建回收垃圾的方法,而如果此类有导出的子类,那么必须在导出类中覆盖回收的方法,当覆盖被继承类的回收垃圾的方法的时候,需要注意销毁的顺序应该和初始化的顺序相反。对于字段来说,意味着与声明的顺序相反。应该先对导出类进行清理,然后才是基类。这是因为导出类的清理可能会调用基类的某些方法,所以需要使基类的构件仍起作用而不应过早的销毁他们。

      如果需要去销毁被多个成员对象共享的变量的时候,这种情况会变得很复杂。这种情况下,可以使用引用计数法来跟综访问着共享对象的代码数量,代码如下:

    import static net.mindview.util.Print.*;
    class Shared {
        private int refcount=0; //标识引用该变量的个数
        private static long counter=0; 
        private final long id=counter++; //标识Shared变量
        public Shared() {
            print("Creating "+this);
        }
        public void addRef() {
            refcount++;
        }
        protected void dispose() {
            if(--refcount==0) {
                print("Disposing "+this);
            }
        }
        public String toString() {
            return "Shared"+id;
        }
     }
    class Composing {
        private Shared shared;
        private static long counter=0;
        private final long id=counter++;
        public Composing(Shared shared) {
            print("Creating "+this);
            this.shared=shared;
            this.shared.addRef();
        }
        protected void dispose() {
            print("disposing "+this);
            shared.dispose();
        }
        public String toString() {
            return "Composing"+id;
        }
    }
    public class ReferenceCounting {
    
        public static void main(String[] args) {
            Shared shared=new Shared();
            Composing[] composing={new Composing(shared),new Composing(shared),
                    new Composing(shared),new Composing(shared)};
            for(Composing c:composing) {
                c.dispose();
            }
        }
    
    }

    二、构造器内部的多态方法的行为

      如果调用构造器内部的一个动态绑定的方法的时候,就需要用到那个方法被覆盖后的定义,动态绑定的方法调用导出类的方法,此时导出类成员变量还未被初始化,可能会产生错误。

    public class Test {
        public static void main(String[] args) {
            new NewSon().print();
        }
    }
    abstract class Father {
        String fs="Dad!";
        public Father() {
            print();
        }
        public abstract void print();
    }
    class NewSon extends Father {
        int i=4;
        String ss="son!";
        public void print() {
            System.out.println("Son.."+i);
    //        System.out.println(ss.toUpperCase());  error
        }
    }

      小细节:如果一个类实现了一个接口,同时继承了另外一个类,如果被继承的类有和接口中同样方法签名的方法,那么子类可以不用提供对于方法的实现。父类继承过来的方法相当于在子类中实现了接口。

    interface Eat {
        public void eat();
    }
    class Dog {
        public void eat() {
            
        }
    }
    public class BadDog extends Dog implements Eat {}

    、内部类的一些细节

      1.如果在内部类生成对外部类的引用,可以通过外部类的名字加上.this,这样产生的引用会自动具有正确的开销.但是.this只能在外部类内部和内部类使用,其他类里不能使用.

      2.在匿名内部类中,如果基类需要一个有参数的构造器,也可以传递参数给基类的构造器,代码如下:

    class Wrapping {
        private int i;
        public Wrapping(int x) {
            i=x;
        }
        public int value() {
            return i;
        }
    }
    class Parcel8 {
        public Wrapping wrapping(int x)/*传入基类构造器*/ {
            return new Wrapping(x) {
                public int value() {
                    return 47*super.value();
                }
            };
        }
    }

      3.接口中也可以声明内部类,接口中的内部类自动被声明为public 和 static的类型,甚至可以在内部类中实现外部接口.

    interface Dog {
        public void bark();
        class GoodDog implements Dog {
    
            @Override
            public void bark() {
                System.out.println("bark!");
            }
            
        }
    }

      4.在继承内部类的时候,指向外围类的秘密的引用必须也要被初始化,因此使用特殊的语法来明确说明这种关联:

    class WithInner {
        class Inner{
            int i=0;
            public Inner (int i) {
                this.i=i;
            }
        }
    }
    class InheritInner extends WithInner.Inner {
    
        public InheritInner(WithInner withInner, int i) {
            withInner.super(i);
        }
        
    }

      5.当继承外部类的时候。内部类并没有什么变化,两个内部类完全是独立的个体,各自在各自的命名空间内。

    四、为什么需要内部类

      1.每个内部类都能独立的继承自一个接口的实现,无论外部类继承了什么类对于内部类没有任何影响。而由于内部类也可以使用外部类的成员,因此,内部类有效的实现了“多重继承”。

    class GrandFather {
        protected int gf=3;
    }
    class Father extends GrandFather {
        protected int ft=2;
        class Son extends Father {
            protected int s=1;
            public void say() {
                System.out.println(gf+" "+ft+" "+s);
            }
        }
    }

      2.利用内部类实现命令模式。

      可以将命令模式中的命令类放入调用者的内部来实现命令模式,代码如下:

    public class Test4 {
        public static void main(String[] args) {
            GreenHouseControl gh=new GreenHouseControl();
            gh.new LightOn().execute();
            gh.new LightOff().execute();
            gh.new WaterOn().execute();
            gh.new WaterOff().execute();
        }
    }
    interface Command /*命令接口*/{
        public void execute();
    }
    class GreenHouseControl {
        private boolean light=false;
        class LightOn implements Command {
    
            @Override
            public void execute() {
                System.out.println("The light is on.");
                light=true;
            }
            
        }
        class LightOff implements Command {
            
            @Override
            public void execute() {
                System.out.println("The light is off.");
                light=false;
            }
            
        }
        private boolean water=false;
        class WaterOn implements Command {
    
            @Override
            public void execute() {
                System.out.println("The water is on");
                water=true;
            }
            
        }
        class WaterOff implements Command {
            
            @Override
            public void execute() {
                System.out.println("The water is off");
                water=false;
            }
            
        }
    }

      对于内部类的知识原理性整理可参见:http://www.cnblogs.com/hlhdidi/p/5575607.html     http://www.cnblogs.com/hlhdidi/articles/5575416.html

  • 相关阅读:
    票房和口碑称霸国庆档,用 Python 爬取猫眼评论区看看电影《我和我的家乡》到底有多牛
    用 Python 写个七夕表白神器
    3. GC复制算法
    一个粗糙的RPC框架设计思路
    503Service Unavailable
    centos 7.8下载地址
    海康摄像头SDK在Linux、windows下的兼容问题(二)已解决
    海康摄像头SDK在Linux、windows下的兼容问题
    二重指针
    【JavaScript 对象03】
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5691310.html
Copyright © 2020-2023  润新知