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

转载于:https://www.cnblogs.com/hlhdidi/p/5691310.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值