2_Java对象的故事

使用Java中的对象就涉及到几个方面:对象的初始化与清理、访问权限控制。想要“偷懒”就开始琢磨类的复用、变着魔法的多态、更自由的接口和藏起来的内部类。下面的思维导图大概只有我自己知道是啥了,书里面讲的很细致,连着把自己看激动后再看懵了,再到“哦,如此甚好”

在这里插入图片描述

在这里插入图片描述

以下是一些小记录。

初始化和清理

Java的初始化和创建捆绑再一起。

构造器与类同名

说到构造器与类同名这个事情,就会涉及到程序中的命名问题。任何程序设计语言都具备的一项重要特性就是对名字的运用。当创建一个对象时,也就给此对象分配到的存储空间取名字。方法就是给某个动作取的名字。
将人类语言中存在细微差别的概念“映射”到程序设计语言中时,相同的词可以表达多种不同的而含义,像C语言要求未每个方法都提供一个独一无二的标识符。由此带来的问题的解决方法就是重载。 区分重载的标准是 独一无二的**参数类型**列表

this关键字

为了维护发送消息给对象的思路,内部的操作

class Banana { void peel(int i) { /* */} }
public class BananaPeel {
	public static void main(String[] args) {
		Banana a = new Banana();
		Banana b = new Banana();
		a.peel(1);    
		b.peel(2);
	}
}

编译器偷偷摸摸把a.peel(1)b.peel(2)的调用变成了Banana.peel(a, 1)Banana.peel(b, 2)
而this关键字能够知道调用者是谁!

终结处理和垃圾回收

finalize是用来解决“意外的”内存分配,实际测试的时候貌似调用System.gc()的时候并有没有调用。
finalize()一个有趣的用法:对象终结条件的验证。

访问权限控制

记住这一句好有道理的话:在任何相互关系中,具有关系所设计的各方都遵守的边界是十分重要的事情。访问控制让类的使用者更容易看到什么是重要的东西。

复用类

三种方式:组合、继承、代理。根据场景荤素搭配,好吃不贵。

多态

【#1 协变返回类型的实例】总是有些看上去不可思议却又理所当然的存在。
协变返回类型:在导出类中被“覆盖”的方法可以返回对应基类方法返回类型的导出类型。
好绕口,上代码:

class Grain {
    @Override
    public String toString() {
        return "Grain";
    }
}
class Wheat extends Grain {
    @Override
    public String toString() {
        return "Wheat";
    }
}

class Mill {
    Grain process() {
        return new Grain();
    }
}
class WheatMill extends Mill {
    Wheat process() {
        return new Wheat();
    }
}

public class CovariantReturn {
    public static void main(String[] args){
        Mill m = new Mill();
        Grain g = m.process();
        System.out.println(g);
        m = new WheatMill();
        g = m.process();
        System.out.println(g);
    }
}

// output
Grain
Wheat

在这里插入图片描述

接口

核心大概就是:任何抽象性都应该是应真正的需求而产生的,优先选择类而不是接口。

【#1 接口的实现类向上转型实例】。
可以向上转型为多种类型的示例:

interface CanFight() { void fight(); }
interface CanSwim() { void swim(); }
interface CanFly() { void fly(); }
class ActionCharacter {
	public void fight() {}
}
class Hero extends ActionCharacter 
				  implements CanFight,CanSwim,CanFly {
	public void swim() {}
	public void fly() {}
}
public class Adventure {
	public static void t(CanFight x) { x.fight(); }
	public static void u(CanSwim x) { x.swim(); }
	public static void v(CanFly x) { x.fly(); }
	public static void w(ActionCharacter x) { x.fight(); }
	public static void main(String[] args) {
		Hero h = new Hero();
		t(h);   u(h);  v(h);  w(h);
	}
}

【#2 组合接口时的名称冲突示例】可以选择的时候不要作死就可以啦

interface I1 { void f(); }
interface I2 { int f(int i); }
interface I3 { int f(); }
class C { public int f() { return 0; } }

// 可以区分f的定义
class C2 implements I1,I2 {
	public void f() {}
	public int f(int) { return 1; }   // overload
}
class C3 extends C implements I2 {
	public int f(int i) { return 1; }   // overload
}
class C4 extends C implements I3 {
	public int f() { return 1; }   // 可以省略。因为从C中继承得到I3的实现
}
// 无法区分
class C5 extends C implements I1 {}   // 因为基类C中和I1中同名方法仅返回值不同,无法区分。
interface I4 extends I1,I3 {}   // 因为I1和I3中的方法只有返回值的不同,无法区分开来

内部类

【#1 由private内部类带来的对于private的新的认识】:把对象交给认识它的人去处理

public interface E {
    interface G {
        void f();
    }
    public interface H {
        void f();
    }
    void g();
}

class A {
    interface B {
        void f();
    }
    public class BImp implements B {
        public void f() {}
    }
    private class BImp2 implements B {
        public void f() {}
    }

    public interface C {
        void f();
    }
    class CImp implements C {
        public void f() {}
    }
    private class CImp2 implements C {
        public void f() {}
    }

    interface D {
        public void f();
    }
    private class DImp implements D {
        public void f() {
            System.out.println("DImp");
        }
    }
    public class DImp2 implements D {
        public void f() {}
    }

    public D getD() {
        return new DImp();
    }
    private D dRef;
    public void receiveD(D d) {
        dRef = d;
        dRef.f();
    }
}


public class NestingInterfaces {
    public class BImp implements A.B {
        public void f() {}
    }
    class CImp implements  A.C {
        public void f() {}
    }
    class EImp implements E {
        public void g() {}
    }
    class EGImp implements E.G {
        public void f() {}
    }
    class EImpl2 implements E {
        public void g() {}
        class EG implements E.G {
            public void f() {}
        }
    }

    public static void main(String[] args){
        A a = new A();
        a.getD().f();
        //a.receiveD(a.getD());
    }
}

【#2 匿名类带参构造函数示例】

public Contents contents(int arg) {
        return new Contents(arg) {
            private int i = 11;
            @Override
            public int value() {
                return i;
            }
        };
    }

【#3 匿名类的构造器示例】

public Contents contents() {
        return new Contents() {
            {
                System.out.println("initializer");
            }
            private int i = 11;
            @Override
            public int value() {
                return i;
            }
        };
    }

【#4 闭包示例】闭包是一个可调用的对象,包含创建它的作用域的信息。

class Callee1 implements Incrementable {
    private int i = 0;

    @Override
    public void increment() {
        i++;
        System.out.println(i);
    }
}

class MyIncrement {
    public void increment() {
        System.out.println("another operation.");
    }
    static void f(MyIncrement mi) {
        mi.increment();
    }
}

class Callee2 extends MyIncrement {
    private int i = 0;
    @Override
    public void increment() {
        super.increment();
        i++;
        System.out.println(i);
    }
    private class Closure implements Incrementable {
        @Override
        public void increment() {
            Callee2.this.increment();
        }
    }
    Incrementable getCallbackReference() {
        return new Closure();
    }
}

class Caller {
    private Incrementable callbackReference;
    Caller(Incrementable cbh) {
        callbackReference = cbh;
    }
    void go() {
        callbackReference.increment();
    }
}

public class Callbacks {
    public static void main(String[] args){
        Callee1 c1 = new Callee1();
        Callee2 c2 = new Callee2();
        MyIncrement.f(c2);
        Caller caller1 = new Caller(c1);
        Caller caller2 = new Caller(c2.getCallbackReference());
//        caller1.go();
//        caller1.go();
        caller2.go();
        caller2.go();
    }
}

感觉示例给的有点尴尬,Callee2直接implement Increment也是OK的,可能主要是为了演示钩子吧。

【#5 内部类的继承示例】

class WithInner {
	class Inner {}
}
public class InheritInner extends WithInner.Inner {
	InheritInner(WithInner wi) {
		wi.supper();
	}
	public static void main(String[] args) {
		WithInner wi = new WithInner();
		InheritInner ii = new InheritrInner(wi);
	}
}

总结

刚看的时候总觉得和C++虚函数丫啥的很像,轻松瞥了几眼。呜呼~仔细看完示例就会发现用法十分灵活而且很多,虽然目前还无法描述出来,至少会觉得,到目前为止,Java的这些特性都是依着一套准则来的。请继续吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值