标签 程序员 下的文章

Effective Java阅读笔记-item18

Dreamhead把他用大把银子买来的“Effective Java”借给我阅读,我真是很感动亚,我只能用行动来感谢Dreamhead了。^_^

18、优先考虑静态成员类(static member class)
在C++的应用中我们很少使用嵌套类,我只在MFC和COM组件中遇到过这些,而且这些嵌套类被隐藏在应用背后,一般的应用中则很少使用。而在Java中嵌套类的应用还是要比在C++中多些。Java中嵌套类主要之功用就是辅助其outer class,为outer class提供服务。

嵌套类分类:
- static member class:
- nonstatic member class:
- anonymous class:
- local class

按照书中的方式我们根据各种类型嵌套类的用途来说:
* static member class
基本格式:
public class OuterClass{
    publc/private static class InnerClass{
        //…
    }
}

对于static型的member class:
多个outer class instance共享一个static member class,就是说static member class和outer类的一般静态成员地位是一样的, static member class可以访问outer class的所有成员,包括private的成员。

书中的例子:(两层嵌套,既使用了static member class又使用了anonymous classes)
//Calculator.java
public class Calculator {
   public static abstract class Operation {
      private final String name;
      Operation(String name)   { this.name = name; }
      public String toString() { return this.name; }
      // Perform arithmetic op represented by this constant
      abstract double eval(double x, double y);      
      // Doubly nested anonymous classes
      public static final Operation PLUS = new Operation("+") {
         double eval(double x, double y) { return x + y; }
      };      
   }
   // Return the results of the specified calculation
   public double calculate(double x, Operation op, double y) {
      return op.eval(x, y);
   }
}
//CalcTest.java
public class CalcTest {
    public static void main(String args[]) {
        double x = Double.parseDouble(args[0]);
        double y = Double.parseDouble(args[1]);
        operate(x, Calculator.Operation.PLUS, y);
    }
    static void operate(double x, Calculator.Operation op, double y) {
        Calculator c = new Calculator();
        System.out.println(x + " " + op + " " + y + " = " +
                           c.calculate(x, op, y));
    }
}
//command: java CalcTest 3 4
//output: 3.0 + 4.0 = 7.0

* nonstatic member class
基本格式:
public class OuterClass{
    publc/private class InnerClass{
        //…
    }
}

对于non-static型的member class:

每个outer class instance都要维护一个member class的实例,且这种关系在outer class被实例化后就不变了。nonstatic member class的实例是在其outer class实例化时才有意义的。

所以当嵌套类的实例可以不依赖于其outer class的实例而存在时。我们应该使用static member class。
nonstatic member classes 常被用來定义 Adapter ,允许我们将outer class的实例视为某些不相关的类的实例。
例如:像Set和List这样的集合接口的实现往往利用nonstatic member class来实现iterator

书中例子:
public MySet extends AbstractSet{
    //…
    private class MyIterator implements Iterator{//inner class or nested class
    
    }
    public Iterator iterator(){
        return new MyIterator();
    }
}

* anonymous classes(匿名类)

匿名类不是outer class的一个成员,它在使用处被同时声明和实例化。匿名类通常只是实现了其接口或超类中的方法。它们不会声明新方法。

匿名类的用途很广泛。
- 用来创建一个function object
如代码:
Collections.sort(list, new Comparator() {
    public int compare(Object o1, Object o2) {
      return ((String)o1).length() – ((String)o2).length();
    }
  }
);
像这样的匿名类可读性差,建议不要把匿名类写的很长。
这里我们假设匿名类的名字为$,这实际上的代码可能是像这样的:
class $ implements Comparator{
    public int compare(…){
        //implement the compare method
}
}
Collections.sort(list, new $());

- 创建process object,例如 Thread、Runnable 实例
- 给 static factory 方法使用,可以在 static factory method 返回一份 anonymous 的实例

* local class(局部类)
使用local class把握一个原则:local class与局部变量的使用(包括声明和scope)几乎一模一样。

Effective Java阅读笔记-item16

Dreamhead把他用大把银子买来的“Effective Java”借给我阅读,我真是很感动亚,我只能用行动来感谢Dreamhead了。^_^

16、接口优于抽象类
作者有一个观点就是:

* 接口是定义mixin(混合类型)的理想选择。

mixin的定义:一个类除了实现它的基本类型”primitive type”之外,还可以实现这个mixin类型,以表明它提供可供选择的行为,也就是说它允许将可选的功能混合到一个类的基本功能中。

作者举例Comparable就是一个mixin接口,这个接口提供的可选功能就是它的实例可以与其他的可相互比较的对象进行排序操作。

基于上面这一点,接口使得我们能够构造出非层次结构的类型框架。

什么是层次结构框架(class hierarchy)?
例如:Shape <– Rectangle <– Square这样一路继承下来,就是一个继承体系。

现在如果Shape假设并没有提供可比较的基本功能,而我们要在Square中实现可比较的功能,我们就可以在Square那加入一个旁支Comparable接口,让Square去实现它即可。

Shape <– Rectangle <– Square <– Square’s sub class
                            |
            Comparable <—–

上面蓝色部分就是一个class hierarchy,而Comparble恰恰就在这个class hierarchy上建立了一个非层次化的结构。

注:abstract class不能用来定义mixin,因为java不提供class的多重继承机制。

* abstract skeletal implementation class(抽象骨架实现类型)–结合抽象类和接口的优点,java中模拟多重继承

Interface缺点是无法拥有方法的实现。而抽象骨架实现的优点在于为抽象类提供实现上的帮助,也避免了抽象类作为类型定义时所特有的限制。

public abstract class AbstractMapEntry implements Map.Entry {
  // Primitives
  public abstract Object getKey();
  public abstract Object getValue();
  //  …
  // Implements the general contract of Map.Entry.equals
  public boolean equals(Object o) {
    if (o == this) return true;
    if (!o instanceOf Map.Entry))
      return false;
    Map.Entry arg = (Map.Entry) o;
   
    return eq(getKey(), arg.getKey()) &&
        eq(getValue(), arg.getValue());
  }
 
  // Since Object equals was overriden, we better override hashCode!
  public int hashCode() {
    return
      (getKey() == null ? 0: getKey().hashCode()) ^
      (getValue() == null ? 0: getValue().hashCode());
  }
}
书中提示:抽象骨架类专为继承而设计,所以要有详细的文档说明。

*抽象类的演化比接口的演化容易

我们举例说明这一点吧
Considering the following code:
//未演化前的代码:
public abstract class AbrBase{
    public void a();
    public void b();
};

public class Sub1 extends AbrBase{
    public void a(){
    }
    public void b(){
    }
};

public interface IBase{
    public void c();
    public void d();
};

public class Sub2 implements IBase{
    public void c(){
    }
    public void d(){
    }
};

//进化后代码
public abstract class AbrBase{
    public void a();
    public void b();
    public void e() {//为抽象类添加一新的具体的方法,注意抽象方法也不行
    }
};

public class Sub1 extends AbrBase{//在抽象类添加一具体方法后,子类可以不用改动
    public void a(){
    }
    public void b(){
    }
};

public interface IBase{
    public void c();
    public void d();
public void f(); //为接口添加一新的方法
};

public class Sub2 implements IBase{
    public void c(){
    }
    public void d(){
    }
    public void f(){ //子类必须修改实现新添加的方法,否则编译将不能通过
    }
};

解决办法:提供抽象骨架类
//进化之前代码
public interface IBase{
    public void c();
    public void d();
};

public abstract class AbrBase implements IBase{
    //primitives
    public void a();
    public void b();

    //implenments the method of IBase interface
    public void c(){
    }
    public void d(){
    }
};

public class Sub extends AbrBase{
    public void a(){
    }
    public void b(){
    }
//继承AbrBase对IBase的实现
};

进化后代码:
public interface IBase{
    public void c();
    public void d();
public void f(); //为接口添加一新的方法
};

public abstract class AbrBase implements IBase{
    //primitives
    public void a();
    public void b();

    //implenments the method of IBase interface
    public void c(){
    }
    public void d(){
    }
    public void f(){ //修改AbrBase以实现IBase新增加的method
    }
};
public class Sub extends AbrBase{//无需改变,继承超类对f()方法的实现
    public void a(){
    }
    public void b(){
    }
//继承AbrBase对IBase的实现
};
That’s all!^_^

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats