zoukankan      html  css  js  c++  java
  • 如何避免创建不必要的对象

    本文涉及到的概念
     
    1.在保证程序清晰性和简洁性的基础下,重用具有相同功能的对象,避免创建新的对象
    2.适配器对象,adapter Object
    3.自动装箱,基本数据类型和装箱类型
     
     
    在保证程序清晰性和简洁性的基础下,重用具有相同功能的对象,避免创建新的对象
    当该对象的状态是不变化的,新创建的对象具有的功能与原来对象相同的,那么就避免创建新的对象,直接使用原来的对象。如果代码中发现这种情况,就做出调整,调整为使用一个对象,避免使用新的对象。
    例子:来自<<effective Java>>
    方法isBabyBoomer,用来检查一个Person实例,该实例是不是出生在婴儿期(1946年1月到1965年1月)。Person类的每个实例,每次调用该方法,都会创建相同的boomStart对象,boomEnd对象。一次调用,创建如下对象,一个Calendar,一个TimeZone,两个Date对象。当然,它们都是局部变量,每次方法调用完后,就被销毁。
    可以提高一下性能,修改为:
    因为boomStart和boomEnd在所有实例中功能相同,而且还没有被修改,那么,就可以提出来,让它成为静态变量。为所有实例共用。
    适配器对象,adapter Object
    上面Person提取的共用的对象,它们的状态在实例化后就不会被修改。而适配器对象,它的状态会被修改。
    调用Map实例的keySet方法,它每次返回的都是同一个对象。不同的线程,持有该Map对象,调用keySet方法,得到的都是同一个keySet对象。对该keySet对象的状态进行修改,要在多个线程中可见,就需要使用volatile来修饰。
    Map:
     
    public interface Map<K,V> {  
      // Views
     
      /**
      * Returns a {@link Set} view of the keys contained in this map.
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa. If the map is modified
      * while an iteration over the set is in progress (except through
      * the iterator's own <tt>remove</tt> operation), the results of
      * the iteration are undefined. The set supports element removal,
      * which removes the corresponding mapping from the map, via the
      * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
      * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
      * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
      * operations.
      *
      * @return a set view of the keys contained in this map
      */
      Set<K> keySet();
    ...
     }
     
    // Modification Operations
     
      /**
      * Associates the specified value with the specified key in this map
      * (optional operation). If the map previously contained a mapping for
      * the key, the old value is replaced by the specified value. (A map
      * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
      * if {@link #containsKey(Object) m.containsKey(k)} would return
      * <tt>true</tt>.)
      *
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with <tt>key</tt>, or
      * <tt>null</tt> if there was no mapping for <tt>key</tt>.
      * (A <tt>null</tt> return can also indicate that the map
      * previously associated <tt>null</tt> with <tt>key</tt>,
      * if the implementation supports <tt>null</tt> values.)
      * @throws UnsupportedOperationException if the <tt>put</tt> operation
      * is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
      * prevents it from being stored in this map
      * @throws NullPointerException if the specified key or value is null
      * and this map does not permit null keys or values
      * @throws IllegalArgumentException if some property of the specified key
      * or value prevents it from being stored in this map
      */
      V put(K key, V value);
     
    AbstractMap:
     
      // Views
     
      /**
      * Each of these fields are initialized to contain an instance of the
      * appropriate view the first time this view is requested. The views are
      * stateless, so there's no reason to create more than one of each.
      */
      transient volatile Set<K> keySet = null;
      transient volatile Collection<V> values = null;
     
     
    HashMap继承AbstractMap:
    entrySet不会被序列化
      // Views
      private transient Set<Map.Entry<K,V>> entrySet = null;
      /**
      * Returns a {@link Set} view of the keys contained in this map.
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa. If the map is modified
      * while an iteration over the set is in progress (except through
      * the iterator's own <tt>remove</tt> operation), the results of
      * the iteration are undefined. The set supports element removal,
      * which removes the corresponding mapping from the map, via the
      * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
      * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
      * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
      * operations.
      */
      public Set<K> keySet() {
      Set<K> ks = keySet;
      return (ks != null ? ks : (keySet = new KeySet()));
      }
      private final class KeySet extends AbstractSet<K> {
      public Iterator<K> iterator() {
      return newKeyIterator();
      }
      public int size() {
      return size;
      }
      public boolean contains(Object o) {
      return containsKey(o);
      }
      public boolean remove(Object o) {
      return HashMap.this.removeEntryForKey(o) != null;
      }
      public void clear() {
      HashMap.this.clear();
      }
      }
     
     
    验证程序:验证keySet方法返回的对象是不是同一个对象
     
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
     
     
    public class MapExample {
     
    public static void main(String[] args){
     
    Map<String,String> one = new HashMap<String,String>();
    one.put("Key1", "one");
    one.put("key2", "two");
     
     
    Set<String> keySet = one.keySet();
    Iterator<String> iterator = keySet.iterator();
    while(iterator.hasNext()){
     
    System.out.println(iterator.next());
     
    }
     
    one.put("Key3", "three");
    one.put("key4", "four");
    Set<String> keySet2 = one.keySet();
    if(keySet2 == keySet){
    System.out.println("They are same");
    }
     
    Iterator<String> iterator2 = keySet2.iterator();
    while(iterator2.hasNext()){
     
    System.out.println(iterator2.next());
    }
    }
     
    }
     
    输出结果:
    Key1
    key2
    They are same
    Key1
    key2
    Key3
    key4
     
     
    自动装箱,基本数据类型和装箱类型
     
    一个例子
     
    public class AutoBoxingExam {
     
    public static void main(String[] args){
     
    Long sum = 0l;
    for(long i = 0; i < Integer.MAX_VALUE; i++){
     
    sum = sum + i; 
    // sum is an Object, can not use +
    // so auto unboxing
    //sum.longValue() + i
    //then sum = new Long(sum.longValue()+i);
    //sum = new Long(sum.longValue()+i);
    }
    }
     
    }
     
    所以整个过程运行下来,在执行过程中,创建了多余的Integer.MAX_VALUE个Long对象。Integer的最大值是2的31次方,32位可以用来表达最大的数字是2的31次方,其中1位用来做符号位
     
    使用自动装箱时,要注意它有可能创建新的对象。
     
    引用:
     
     
  • 相关阅读:
    元素绑定与非元素绑定
    窗口之间的交互,windows和自定义的窗口集合
    e.which
    prop()和attr()
    web动画
    $.proxy()和$.makeArray()
    匿名自执行函数报错
    页面适配
    gulp
    伪元素和伪类
  • 原文地址:https://www.cnblogs.com/ttylinux/p/6507183.html
Copyright © 2011-2022 走看看