Android开发Android知识Java学习笔记

《Effective Java》笔记(上)

2016-11-03  本文已影响1785人  OCNYang

《Effective Java》笔记(上)

对象的创建与销毁

```java
    private static volatile RestAdapter sRestAdapter = null;
    public static RestAdapter provideRestAdapter() {
        if (sRestAdapter == null) {
            synchronized (RestProvider.class) {
                if (sRestAdapter == null) {
                    sRestAdapter = new RestAdapter();
                }
            }
        }

        return sRestAdapter;
    }
```

DCL可能会失效,因为指令重排可能导致同步解除后,对象初始化不完全就被其他线程获取;使用volatile关键字修饰对象,或者使用static SingletonHolder来避免该问题(后者JLS推荐);

Object的方法

尽管Object不是抽象类,但是其定义的非final方法设计的时候都是希望被重写的,finalize除外。

Classes and Interfaces

Generics

  ```java
    // Uses raw type (List) - fails at runtime!
    public static void main(String[] args) {
      List<String> strings = new ArrayList<String>();
      unsafeAdd(strings, new Integer(42));
      String s = strings.get(0); // Compiler-generated cast
    }

    private static void unsafeAdd(List list, Object o) {
      list.add(o);
    }
  ```
  不会报编译错误,但会给一个编译警告:`Test.java:10: warning: unchecked call to add(E) in raw type List list.add(o);`,而运行时则会发生错误。
+  但如果使用`List<Object>`,即`unsageAdd`参数改为`List<Object> list, Object o`,则会报编译错误:`Test.java:5: unsafeAdd(List<Object>,Object) cannot be applied to (List<String>,Integer) unsafeAdd(strings, new Integer(42));`  
+  因为`List<String>`是`List`的子类,但却不是`List<Object>`的子类。  
+  并不是说这个场景应该使用`List<Object>`,这个场景应该使用`List<String>`,这里只是为了说明`List`和`List<Object>`是有区别的。
  ```java
    void func(List<?> list) {
      ...
    }

    func(new List<Object>());
    func(new List<Integer>());
    func(new List<String>());
  ```
+  持有`List<?>`的引用后,并不能向其中加入任何元素,读取出来的元素也是`Object`类型,而不会被自动强转为任何类型。
+  如果`List<?>`的行为不能满足需求,可以考虑使用模板方法,或者`List<E extends XXX>`(bounded wildcard types)
```java
  // Legitimate use of raw type - instanceof operator
  if (o instanceof Set) { // Raw type
    Set<?> m = (Set<?>) o; // Wildcard type
    ...
  }
```
  // Fails at runtime!
  Object[] objectArray = new Long[1];
  objectArray[0] = "I don't fit in"; // Throws ArrayStoreException

  // Won't compile!
  List<Object> ol = new ArrayList<Long>(); // Incompatible types
  ol.add("I don't fit in");
  // Generic method
  public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
      Set<E> result = new HashSet<>(s1);
      result.addAll(s2);
      return result;
  }
  // Using a recursive type bound to express mutual comparability
  public static <T extends Comparable<T>> T max(List<T> list) {...}
  public class Stack<E> {
      public Stack();
      public void push(E e);
      public E pop();
      public boolean isEmpty();

      public void pushAll(Iterable<E> src);
      public void popAll(Collection<E> dst);
  }

  Stack<Number> numberStack = new Stack<Number>();
  Iterable<Integer> integers = ... ;
  numberStack.pushAll(integers);

  Stack<Number> numberStack = new Stack<Number>();
  Collection<Object> objects = ... ;
  numberStack.popAll(objects);

pushAll和popAll的调用均无法通过编译,因为尽管IntegerNumber的子类,但Iterable<Integer>不是Iterable<Number>的子类,这是由泛型的invariant特性导致的,所以Iterable<Integer>不能传入接受Iterable<Number>参数的函数,popAll的使用同理

  public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2);

  Set<Integer> integers = ... ;
  Set<Double> doubles = ... ;
  //Set<Number> numbers = union(integers, doubles); //compile error
  Set<Number> numbers = Union.<Number>union(integers, doubles);  //compile pass
  // Typesafe heterogeneous container pattern - API
  public class Favorites {
      public <T> void putFavorite(Class<T> type, T instance);
      public <T> T getFavorite(Class<T> type);
  }
  // Typesafe heterogeneous container pattern - implementation
  public class Favorites {
      private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();

      public <T> void putFavorite(Class<T> type, T instance) {
          if (type == null)
          throw new NullPointerException("Type is null");
          favorites.put(type, instance);
      }

      public <T> T getFavorite(Class<T> type) {
          return type.cast(favorites.get(type));
      }
  }
```java
  // Achieving runtime type safety with a dynamic cast
  public <T> void putFavorite(Class<T> type, T instance) {
      favorites.put(type, type.cast(instance));
  }
```
这样做的效果是使得想要破坏类型安全性的put使用者产生异常,而使用get的使用者则不会因为恶意put使用者产生异常。这种做法也被`java.util.Collections`包中的一些方法使用,例如命名为checkedSet, checkedList, checkedMap的类。
+  这个容器内不能放入non-reifiable的类型,例如`List<String>`,因为`List<String>.class`是有语法错误的,`List<String>`, `List<Integer>`都只有同一个class对象:`List.class`;另外`String[].class`是合法的。
  // Use of asSubclass to safely cast to a bounded type token
  static Annotation getAnnotation(AnnotatedElement element, String annotationTypeName) {
      Class<?> annotationType = null; // Unbounded type token
      try {
          annotationType = Class.forName(annotationTypeName);
      } catch (Exception ex) {
          throw new IllegalArgumentException(ex);
      }
      return element.getAnnotation(annotationType.asSubclass(Annotation.class));
  }

摘录来源:https://notes.piasy.com/Android-Java/EffectiveJava.html

上一篇 下一篇

猜你喜欢

热点阅读