23.  类结构层次优于标签类

  有时你会碰到一个类,它的实例有一个或多个风格,并且包含一个tag属性表示实例的风格。例如,如下面的类表示一个圆或者矩形:

public class Figure {/*** 标签: circle表示圆 rectangle表示矩形*/private String tag;private double length;private double width;private double radis;public Figure(double radis) {super();this.radis = radis;}public Figure(double length, double width) {super();this.length = length;this.width = width;}public double area() {// 返回圆的面积if ("circle".equals(tag)) {return Math.PI * radis * radis;}if ("rectangle".equals(tag)) {return length * width;}return 0;}

  这样的类有很多缺点,代码可读性查,将来增加一个三角形又得重写计算面积的方式,而且需要增加三角形属性。

解决办法,用类层次结构代替:

package cn.qlq;public abstract class Figure {abstract double area();
}class Circle extends Figure {private double radis;@Overridedouble area() {return Math.PI * radis * radis;}}class Rectangle extends Figure {private double length;private double width;@Overridedouble area() {return length * width;}}

24.  支持使用静态成员类而不是非静态类

  有四种嵌套类:静态成员类、非静态成员类、匿名内部类和局部类。

  静态成员类是最简单的嵌套类。最好把它看做是一个普通的类,恰好在另一个类中声明,并且可以访问宿主类的成员,甚至是那些被声明为私有类的成员。其一个主要用途是作为公共帮助类,例如Calculator可以使用Calculator.Operation.PLUS。

  在语法上,静态成员和非静态成员类之间的唯一区别是静态成员类在其宿主类中用static修饰。

  如果声明了一个不需要访问宿主实例的成员类,不如用static修饰使之成为静态成员类。

25.  将源文件限制为单个顶级类

  虽然Java编译器允许在单个Java文件中定义多个顶级类,只需要文件名与public修饰的类一致即可,但是不建议这么做。

26.  不要使用原始类型

  也就是泛型尽量指明类型,虽然存在泛型擦除,但是至少编译期间会减少一些潜在的错误。比如你很容易将BigInteger和BigDecimal存入同一个集合。

比如下面就是正确的用法:(右边直接用<>即可,编译器会自动推断出正确的实际类型参数,不写<>会编译警告)

Map<String, Object> result = new HashMap<>();

泛型的术语如下:

27.  消除非检查警告

  尽可能的消除每一个未经检查的警告。

  如果不能消除警告,但你确保证明引发警告的代码是类型安全的,那么只能用@SuppressWarnings("unused")来消除警告(注意使用注解压制警告的时候写明原因)。

  总之,未经检查的警告是重要的,在运行时可能会出现ClassCaseException异常。

比如:

List<String> list = new ArrayList();

  会有一个警告:ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized

写成下面这样则不会出现警告,虽然右边只是一个<>符号,并没有指定真正的实际类型参数,但编译器会根据前面的自动推断。

List<String> list = new ArrayList<>();

28.  列表优于数组

  列表与数组在两方面不同。

  首先,数组是斜变的,也就是如果Sub是Super的子类,则数组类型Sub[]是Super[]的子类型;集合是不变的,对于任何两种不同的类型Tyepe1和Type2,List<Type1>既不是List<Type2>的子类型也不是父类型。

也就是说:如下编译不通过

        // 正确编译Object[] objects = new Long[11];

如下会报编译错误:

        // 编译不通过List<Object> lists = new ArrayList<Long>();

  第二个差异就是数组被具体化了,也就是数组在运行时知道并强制执行它们的元素类型。如果尝试将String放入一个Long型数组是做不到的,但是通过集合不指定具体的实际类型却可以做到。

  由于上面的差异,数组和泛型不能很好的结合在一起。例如,创建泛型类型的数组,参数化类型的数组以及类型参数的数组都是非法的。因此,这些数组创建表达式都不合法:

        new List<E>();new List<String>();new E<String>();

补充:Java语言并不支持列表,所以一些泛型类型(如ArrayList)必须在数组上实现,其他的泛型类型,比如HashMap是为了提高性能而实现的。

29.  优先考虑泛型

  泛型类型比需要在客户端代码中强制转换的类型更安全,更易于使用。当你设计新的类型时,确保它们可以在没有这种强制转换的情况下使用。这通常意味着使类型泛型化。

  如果有任何现有的类型应该是泛型化但实际上却不是,考虑把它们泛型化。这使得这些类型的新用户的使用更容易,而不会破坏现有的客户端。

  

30.  优先使用泛型方法

  泛型类和泛型方法需要选择的时候优先使用泛型方法。

31.  使用限定通配符来增加API的灵活性(重要)

  参数化类型是不变的。比如List<String> 你就只能存放String类型的数据。

  相对于提供的不可变的类型,有时候使用限定通配符可以获得更高的灵活性。

  在API中使用通配符类型很棘手,但使得API更加灵活。一条基本的原则就是producer-extends,consumer-super(PECS)。还需要记住,所有Comparable和Comparator都是消费者。如果一个输入参数同时是生产者和消费者那么考虑使用精确类型。

如下:

package cn.qlq;import java.util.ArrayList;
import java.util.List;public class Client {public static void main(String[] args) {List<Integer> set1 = new ArrayList<>();set1.add(1);List<Float> set2 = new ArrayList<>();set2.add(1F);List<Number> unionMember = unionMember(set1, set2);System.out.println(unionMember);}private static <E> List<E> unionMember(List<? extends E> set1, List<? extends E> set2) {List<E> result = new ArrayList<>();result.addAll(set1);result.addAll(set2);return result;}}

  上面的unionMember方法的参数声明,两个参数set1和set2都是E的生产者所以PCES告诉我们应该用extends。

  请注意:返回类型仍然是E,不要使用限定通配符作为返回类型。

32.  合理地结合泛型和可变参数

  一般不要同时使用可变的泛型参数。

33.  优先考虑类型安全的异构容器

  

转载于:https://www.cnblogs.com/qlqwjy/p/11049475.html

Effective.Java第23-33条(泛型相关)相关推荐

  1. Effective Java读书笔记七:泛型(部分章节需要重读)

    第23条:请不要在新代码中使用原生态类型 从java1.5发行版本开始,Java就提供了一种安全的替代方法,称作无限制的通配符类型,如果要使用范型,但是确定或者不关心实际的参数类型,就可以用一个问号代 ...

  2. 《Effective Java》——学习笔记(泛型枚举和注解)

    泛型 第23条:请不要在新代码中使用原生态类型 如果使用原生态类型,就失掉了泛型在安全性和表述性方面的所有优势,比如不应该使用像List这样的原生态类型,而应该使用如List<Object> ...

  3. 《Effective Java》读书笔记 - 5.泛型

    Chapter 5 Generics Item 23: Don't use raw types in new code 虽然你可以把一个List<String>传给一个List类型(raw ...

  4. php早午晚问候语,美好的午安问候语短信汇总33条

    美好的午安问候语短信汇总33条 你今天穿的好少,多穿点衣服吧,你手冻的好红,把手套给你带.午安!以下是小编收集整理的美好的午安问候语33条,欢迎阅读,希望大家能够喜欢. 1.成功的竞争者,总是在思考中 ...

  5. 读完《Effective Java》后,总结了 50 条开发技巧

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | Dong GuoChao 来源 | https ...

  6. 读完 Effective Java,我整理了 59 条技巧!(含pdf)

    点击⬆️方"逆锋起笔",公众号回复 编程资源领取大佬们推荐的学习资料 上一篇:CTO 写低级 Bug,致公司 70 GB 数据泄露! 作者:Dong GuoChao 链接:http ...

  7. Effective Java(第3版) 90条经验法则

    目录 第2章 创建和销毁对象 第1条:用静态工厂方法替代构造器 第2条:遇到多个构造器参数时要考虑使用构建器 例子 使用 第3条:用私有构造器或者枚举类型强化Singleton属性 例子 使用 第4条 ...

  8. 【读书笔记】《Effective Java》第二章 第2条:遇到多个构造器参数时要考虑使用Builder

    一.前言 <Effective Java>读书笔记系列 第二章 第1条:创建和销毁对象 第二章 第2条:遇到多个构造器参数时要考虑使用Builder 二.介绍 我们开发中偶尔会遇到一些需要 ...

  9. 第 3 次读 Effective Java,这 58 个技巧最值!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:Dong GuoChao <Effective ...

最新文章

  1. python 斐波那契数列
  2. stm32for循环几个机械周期_波浪理论之五:循环周期理论
  3. ffmpeg提取音频播放器总结
  4. vue v-for循环动态获取_快速、简洁讲明Vue中vfor循环key的作用
  5. 全系标配!Redmi K40系列锁定三星E4材质OLED屏幕
  6. 95-30-060-java.util-HashSet
  7. 申请google Map api key for android
  8. 作为外包,你有过不甘吗?| 畅言
  9. 机器视觉:远心光学探秘
  10. OpenGL学习笔记_图形渲染管线及典型渲染流程(绘制一个三角形)
  11. esp8266教程 零基础入门学用物联网 基础知识篇(1)
  12. 计算机cpu尺寸,英特尔CPU型号尺寸.doc
  13. 互联网周刊_11年第15期(115网盘下载)
  14. 工业数字相机的应用及基础知识
  15. 实现一个简单的记事本APP
  16. 人工智能机器人技术概述
  17. 一文搞懂候选码、主码、全码、外码、主属性、主键、主关键字、非主属性清晰总结
  18. 数据分析实习-业务题准备
  19. 2015-2016-1 学期《软件工程》第4次作业
  20. 100天精通Andriod逆向——第3天:真机环境配置

热门文章

  1. 全面理解 ASP.NET Core 依赖注入
  2. app启动调用的api
  3. javascript笔记——点击按钮(或超链接)如何跳转到另外一个页面并执行目标页面的js函数...
  4. MySQL中的配置参数interactive_timeout和wait_timeout
  5. Unix 时间表示方式与windows时间表示方式相互转换的解决办法
  6. [导入]JavaScript 滑动条效果
  7. 【密码学02】密码系统原理及数学背景
  8. 对等网不要求文件服务器,对等网文件共享技术研究与应用
  9. linux修改文件权限属性,如何修改Linux文件的属性与权限
  10. leetcode算法题--在排序数组中查找数字 I