Effective Java2 摘要

第1条:

第29条:优先考虑类型安全的异构容器

当一个容器(如Map)实现多种类型的key时,可以使用 Class<T>来作为key

    Map<Class<?>,Object> map = new HashMap<>();
    
    public <T> void putV(Class<T> type, T v){
        map.put(type,v);
    }
    
    public <T> T getV(Class<T> type){
        return  type.cast(map.get(type));
    }

这种方式有两种局限性:
第一种,原生态形式使用Class对象,可以通过检查, 例如List<String> 和 List<Char> 的原生态Class对象是 List.class
解决方案,在put时检查值是否是真的type所对应的实例

  public <T> void putV(Class<T> type, T v){
        map.put(type,type.cast(v));
  }

第二种,有些类型不可以具体化,比如List<String>没有对应的Class对象,只有原生态形式擦除了类型 List.class

第30条,用枚举代替int常量

用int类型列举的方式叫做int枚举模式,存在诸多不足,比如可以任意赋值没有任何检查.同样的还有String枚举模式
枚举提供编译时的类型安全
枚举可以重新排列或修改,不用重新编译客户端代码
枚举可以添加方法和域,并实现任意接口

第31条,用实例域代替序数

枚举默认和一个单独的int值关联,所有默认枚举有个ordinal方法,返回枚举常量在类型中的数字位置

public enum Ensemble{
      SOLO,DUET
      
    public int getPosition(){
          return ordinal()+1000;
    }
}

但是如果调整位置,就会导致使用ordinal相关的方法被破坏,这种情况可以通过添加域来保存相关信息

public enum Ensemble{
      SOLO(1),DUET(2)
      
    private final int position;
    Ensemble(int position){this.position = position}
    public int getPosition(){
          return position;
    }
}

第32条,用EnumSet 代替位域

枚举类型用在集合中时,允许联合使用,int枚举模式如下

public class Text{
    public static final int STYLE_BOLD = 1<<0; //1
    public static final int STYLE_ITALIC = 1 <<1;

    public void applyStyles(int styles){...}

}

//使用
text.applyStyles(STYLE_BOLD|STYLE_ITALIC)

这种可以 使用EnumSet

public class Text{
    
    public enum Style{ BOLD,ITALIC }

    public void applyStyles(Set<Style> styles){...}

}

//使用
text.applyStyles(EnumSet.of(Style.BOLD,Style.ITALIC))

第33条,用 EnumMap代替序数索引

用枚举索引作为数组下标,隐藏这很多问题,这种情况可以用EnumMap来实现

public class Herb{
    public enum Type{  ANNUAL,PERENNIAL,BIENNIAL}

    private final String name;
    private final Type type;

    Herb(String name,Type type){
        this.name = name;
        this.type = type;
    }
}

Map<Herb.Type,Set<Herb>> herbsByType = new EnumMap<Herb.Type,Set<Herb>>(Herb.Type.class);
for(Herb.Type t: Herb.Type.values())
    herbsByType.put(t,new HashSet<Herb>());
for(Herb h:garden)
    herbsByType.get(h.type).add(h);

第34条,用接口模拟可伸缩枚举

枚举在这中语言特性下,是不可以继承扩展的,但有一种方式可以利用接口

public interface Operation{
    double apply(double x,double y);
}

public enum BasicOperation implements Operation{
    PLUS("+"){
        public double apply(double x,double y){return x + y;}
    }
   MINUS("-"){
        public double apply(double x,double y){return x - y;}
    }
   TIMES("*"){
        public double apply(double x,double y){return x * y;}
    }
   DIVIDE("/"){
        public double apply(double x,double y){return x / y;}
    }
    private final String symbol;
    BaseOperation(String symbol){this.symbol = symbol;}
}

public enum ExtendedOperation implements Operation{
    EXP("^"){
        public double apply(double x,double y){return Math.pow(x,y);}
    } 
    private final String symbol;
    ExtendedOperation (String symbol){this.symbol = symbol;}
}

第35条,注解优先于命名

第36条,坚持使用Override注解

第37条,用标记接口定义类型

比如Serializable接口表明此类可以被序列化

第38条,检查参数的有效性

声明的方法,对应的参数要执行检查可以适当的抛出错误

第39条,必要时进行保护性拷贝

将参数复制到方法内的局部变量,再处理,避免方法执行后或过程中参数有修改.

第40条,谨慎设计方法签名

避免过长的参数列表,可采用:
分解方法,建辅助类保存多个参数,采用Builder模式三种方式

第41条,慎用重载

重载不同函数避免参数有继承关系,选择是由参数决定,没有根据具体对象

public void m(String str){}
public void m(CharSequence cs){}

CharSequence[] css =  {"str",new CharSequence()}
m(css[0]);//执行的是第二个方法
m(css[1]);//执行的是第二个方法

第42条,慎用可变参数

使用可变参数时注意参数可能为0个,所以要有显示的检查或者改为一个默认参数和可变参数两个参数

第43条,返回零长度的数组或者合集,而不是null

这样做避免调用方进行再次非空判断

第44条,为所有导出的API元素编写文档注释

使用标签
@param @return @throws

第45条,局部变量的作用域最小化

避免局部变量被其他代码错误使用

第46条,for-each循环优先于传统的for循环

比for循环有性能优势,数组边界值值计算一次.
但有些情况不可以使用:
1)删除元素,要用显示的迭代器
2)修改元素要索引下标
3)多个集合并行迭代,要用索引同步

第47条,了解和使用类库

1,随机 Random.nextInt(int maxValue)
常用工具库包名
java.util
java.util.concurrent
java.lang

第48条,精准的结果,避免使用float和double

这些事有损运算,精准的可以使用 BigDecimal

第49条,基本类型优先于装箱基本类型

二者区别:
1,基本类型只有值,二装箱基本类型则具有与它们的值不同的同一性,装箱的是对象.
2,装箱的值可以为null
3,基本类型更节省时间空间.

第50条,如果其他类型更合适,尽量避免使用字符串

第51条,当心字符串连接的性能

要多次字符串拼接时,可以使用StringBuilder替代String

第52条:通过接口引用对象

第53条,接口优先于反射机制

第54条,谨慎使用本地方法JNI

常用情形
1,访问特定于平台的机制,如注册表
2,访问遗留代码库
3,提升性能
缺点:
不安全,不利于阅读,可移植性差

第58条,对可恢复的情况使用受检查异常,对编程错误使用运行的异常

三种可抛出结构:
受检查的异常(checked exception)
运行时异常 (run-time exception)
错误(error)

第78条,考虑用序列化代理代替序列化实例

序列化增加出错和出现安全问题.
代理模式:
为可序列化的类设计一个私有的静态嵌套类,精确地标识外围类的实例的逻辑状态,这个嵌套类被称作序列化代理,它应该有一个单独的构造器,参数类型就是那个外围类,可以防止字节流攻击

public final class Period{
      private final Date start;
      private final Date end;

      public Period(Date start,Date end){
            this.start = new Date(start.getTime());
            this.end  = new Date(end.getTiem());
      }
      
private startic class SerializationProxy implements Serializable{
      private final Date start;
      private final Date end;

     SerializationProxy(Period p){
            this.start = p.start;
            this.end = p.end;
    }
    private startic final long serialVersionUID = ....;

    private Object readResolve(){
          return new Period(start,end)
    }
}
       
private Object writerReplace(){
        return new SerializationProxy(this);
}
privatevoid readObject(ObjectInputStream stream)throws InvalidObjectException{
        throw new InvalidObjectException("")
}

}

局限性:
不能与可以被客户端扩展的类兼容,也不能和包含循环的某些类兼容.
开销代价变大

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,852评论 6 13
  • 经典重读——亚马逊链接 笔记链接 导图: 笔记文本: Effective Java1 第2章 创建和销毁对象1.1...
    8c3c932b5ffd阅读 1,409评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 在2017年的10月13、14、15日,我们迎来了总行为我们举办的第二次培训。这次的培训有两个内容,一个是...
    Jessy_c886阅读 377评论 0 0
  • github地址就不用说了,用来做什么的也不说了,简书上有很多,本文只记录一下用来保存本地聊天IM的记录的一些使用...
    wingsrao阅读 2,125评论 1 5