美文网首页
Effective Java理解(一)

Effective Java理解(一)

作者: minute_5 | 来源:发表于2019-07-23 17:12 被阅读0次

    静态工厂方法替换构造函数 - 何时替换

    1. 静态工厂方法含有名字,它能提供更加明确的信息
    2. 当创建对象的代价很大时,需要使用享元模式时
    3. 能返回其返回类型的任何子类型的对象(? extends T),比如java .util. collections
    4. 返回对象的类可以根据输入参数的不同而不同。
    5. 服务提供者框架中编写包含方法的类时,返回的对象的类不需要存在(这句话,单独拿在这儿来说,我是懵逼的),在书中用JDBC来说明了一下,但解释得十分笼统,这里重新释义一下服务提供者框架
      JDBC服务提供者框架关系图.jpg
      1. Class.forName("com.mysql.jdbc.Driver");这样一个语句会实例化一个Driver类(提供服务者实现类),并将这个类的实例注册到DriverManager(服务提供者注册类)。
      2. DriverManager.getConnection("jdbc:mysql://...","...","..."); 这里通过建立连接的URL等信息来获取数据库连接。DriverManager通过传进来的url信息判断出你是要获取那个服务提供者提供的服务。因为1中已经将提供服务者实现类注册到DriverManager了,DriverManager获取到这个服务提供者实现类对象之后,通过调用它的getService(mysql里面是connect方法)方法获取到服务具体实现类对象,返回的却是java.sql.Connection接口对象(因为服务具体实现类实现了Connection接口),这样把服务具体实现类对象隐藏了。提供了很好的扩展性。
      3. 在Java1.6的时候加入了java.util.ServiceLoader,可以通过这个类来实现服务提供者。
    静态工厂方法的常用名称:
    1. from —— A 类型转换方法,它接受单个参数并返回此类型的相应实例,例如:Date d = Date.from(instant);
    2. of —— 一个聚合方法,接受多个参数并返回该类型的实例,并把他们合并在一起,例如:Set faceCards = EnumSet.of(JACK, QUEEN, KING);
    3. valueOf —— from 和 to 更为详细的替代 方式,例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
    4. instancegetinstance —— 返回一个由其参数 (如果有的话) 描述的实例,但不能说它具有相同的值,例如:StackWalker luke = StackWalker.getInstance(options);
    5. createnewInstance —— 与 instance 或 getInstance 类似,除了该方法保证每个调用返回一个新的实例,例如:Object newArray = Array.newInstance(classObject, arrayLen);
    6. getType —— 与 getInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,例如:FileStore fs = Files.getFileStore(path);
    7. newType —— 与 newInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,例如:BufferedReader br = Files.newBufferedReader(path);
    8. type —— getType 和 newType 简洁的替代方式,例如:List litany = Collections.list(legacyLitany);
    • tips: 当构造函数的参数过多使用Builder

    依赖注入替换硬连接资源的方式

    如果一个类依赖于一个或多个底层资源,这些资源的行为会影响类的行为的时候,不要使用单例或静态的实用类来实现这个类,并且不让类直接创建这些资源。相反,将资源或工厂传递给构造方法(或静态工厂或 builder 模式)。这种称为依赖注入的实践将极大地增强类的灵活性、可重用性和可测试性。

    重写equals方法

    1. 自反性: 对于任何非空引用 x,x.equals(x) 必须返回 true。
    2. 对称性: 对于任何非空引用 x 和 y,如果且仅当 y.equals(x) 返回 true 时 x.equals(y) 必须返回 true。
    3. 传递性: 对于任何非空引用 x、y、z,如果 x.equals(y) 返回 true,y.equals(z) 返回 true,则 x.equals(z) 必须返回 true。
    4. 一致性对于任何非空引用 x 和 y,如果在 equals 比较中使用的信息没有修改,则 x.equals(y) 的多次调用必须始终返回 true 或始终返回 false。
    5. 对于任何非空引用 x,x.equals(null) 必须返回 false。
    6. 当重写 equals 方法时,同时也要重写 hashCode 方法。
    7. 不要让 equals 方法试图太聪明。如果只是简单地测试用于相等的属性。
    8. 在 equal 时方法声明中,不要将参数 Object 替换成其他类型。
    //正确示范
    @Override 
    public boolean equals(Object o) {
        if (!(o instanceof MyType))
            return false;
        MyType mt = (MyType) o;
        ...
    }
    

    实现Comparable接口

    1. 使用Arrays.sort来完成排序
    2. 无论何时实现具有合理排序的值类,都应该让该类实现 Comparable 接口。 比较 compareTo 方法的实现中的字段值时,请避免使用<>运算符。 相反,使用包装类中的静态 compare 方法或 Comparator 接口中的构建方法。
    // BROKEN difference-based comparator - violates transitivity!
    static Comparator<Object> hashCodeOrder = new Comparator<>() {
        public int compare(Object o1, Object o2) {
            return o1.hashCode() - o2.hashCode();
        }
    };
    /**
      *不要使用这种技术!它可能会导致整数最大长度溢出和 IEEE 754 浮点运算失真的危险[JLS 15.20.1,15.21.1]。 此外,由此
      *产生的方法不可能比使用上述技术编写的方法快得多。 使用静态 compare 方法:
    */
    
    // Comparator based on static compare method
    static Comparator<Object> hashCodeOrder = new Comparator<>() {
        public int compare(Object o1, Object o2) {
            return Integer.compare(o1.hashCode(), o2.hashCode());
        }
    };
      
    //或者使用 Comparator 的构建方法:
    // Comparator based on Comparator construction method
    static Comparator<Object> hashCodeOrder =
            Comparator.comparingInt(o -> o.hashCode());
    
    //java8 比较 正序
    someList.sort((Message m1, Message m2) -> m1.getSendDate().compareTo(m2.getSendDate()));
    
    参考:
    1. 《effective java》3rd -- Joshua Bloch
    2. JAVA 服务提供者框架介绍

    相关文章

      网友评论

          本文标题:Effective Java理解(一)

          本文链接:https://www.haomeiwen.com/subject/peualctx.html