一、安卓上的类型安全枚举

public class Machine {    public static final int STOPPED = 10;    public static final int INITIALIZING = 20;    public static final int STARTING = 30;    public static final int RUNNING = 40;    public static final int STOPPING = 50;    public static final int CRASHED = 60;    private int mState;    public Machine() {        mState = STOPPED;    }    public int getState() {        return mState;    }    public void setState(int state) {        mState = state;    }}

问题:虽然这些常量是期望的,但是没有方法保证setState()方法接收其他的值。如果
要在设置方法中添加检查,那么一旦得到的是非预期值,开发者就需要处理错误。开发者所需要的是在编译时检查非法赋值。类型安全的枚举解决了这个问题,如下所示:

public class Machine {    public enum State {        STOPPED, INITIALIZING, STARTING, RUNNING, STOPPING, CRASHED    }    private State mState;    public Machine() {        mState = State.STOPPED;    }    public State getState() {        return mState;    }    public void setState(State state) {        mState = state;    }}

注意在声明不同类型安全值的地方新加的内部枚举类。这在编译时就会解决非法赋值的问题,所以代码更不容易出错。
Android早期的版本中不建议使用枚举类型,因为和使用整型常量相比,这种设计带来的内存和性能损失更大。如今有了更强的JIT编译器以及一个不断改进的Dalvik虚拟机,开发者不必再担心这个问题,放心大胆地使用类型安全枚举即可。

二、增强for循环

void loopOne(String[] names){    int size = names.length;    for(int i=0;i names){    for(String name:names){        printName(name);    }  }void loopFour(Collection names){    Iterator iterator = names.iterator();    while(iterator.hasNext()){        printName(iterator.next());    }}// 不要在ArrayList上使用增强版的for循环void loopFive(ArrayList names){    int size = names.size();    for(int i=0;i

如果只是读取元素的话,可以放心地对数组使用增强版 for 循环。对 Collection 对象来说,增强版 for 循环和使用迭代器遍历元素有着相同的性能。 ArrayList 对象应避免使用增强版 for 循环。
如果不仅需要遍历元素,而且需要元素的位置,就一定要使用数组或者 ArrayList ,因为所有其他 Collection 类在这些情况下会更慢。
一般情况下,如果在读取元素几乎不变的数据集时对性能要求很高,建议使用常规数组。

三、队列、同步和锁

1. 更智能的队列

LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue();

上面的一行代码能提供阻塞队列,甚至能提供额外的线程安全操作。java.util.concurrent包含许多可选的队列以及并发映射类,所以,一般情况下,建议使用它们。

2.更智能的锁

Java提供的 synchronized 关键字允许开发者创建线程安全的方法和代码块。synchronized关键字易于使用,也很容易滥用,对性能造成负面影响。当需要区分读数据和写数据时,synchronized 关键字并不是最有效的。幸好,java.util.concurrent.locks包中的工具类对这种情况提供了很好的支持。

public class ReadWriteLockDemo(){    private final ReentrantReadWriteLock mLock;    private String mName;    private int mAge;    private String mAddress;    public ReadWriteLockDemo(){        mLock = new ReentrantReadWriteLock();    }    public void setPersonData(String name, int age, String address){        ReentrantReadWriteLock.WriteLock writeLock = mLock.writeLock();        try{            writeLock.lock();            mName = name;            mAge = age;            mAddress = address;        }finally{            writeLock.unlock();        }    }    public String getName() {        ReentrantReadWriteLock.ReadLock readLock = mLock.readLock();        try {            readLock.lock();            return mName;        } finally {            readLock.unlock();        }    }// 重复代码不再赘述}

上面的代码展示了在什么地方使用 ReentrantReadWriteLock ,它允许多个并发线程对数据进行只读访问,并确保同一时间只有一个线程写入相同的数据。
在代码中使用 synchronized 关键字仍然是处理锁问题的有效方法,但无论何种情况下,都要考虑 ReentrantReadWriteLock 是否是更有效的解决方案。

四、管理和分配内存

1. 应尽可能避免在循环中分配对象

2. 有时候无法避免在循环中创建对象,所以还需要采用某种方法处理这种情况。本书的解决方案是使用一个静态工厂方法按需分配对象,Joshua Bloch在《Effective Java中文版》一书的第一条中详细地描述了该方法。

public final class Pair{    public int firstValue;    public int secondValue;    //引用对象池中的另一个对象    private Pair next;    //同步锁    private static final Object sPoolSync = new Object();    //对象池中第一个可用对象    private static Pair sPool;    private static int sPoolSize = 0;    private static final int MAX_POOL_SIZE = 50;    /**    * 只能用obtain()方法获取对象    */    private Pair() { }    /**    * 返回回收的对象或者当对象池为空时创建一个新对象    */    public static Pair obtain(){        synchronized(sPoolSync){            if(sPool != null){                Pair m = sPool;                sPool.next = m.next;                m.next = null;                sPoolSize --;                return m;            }        }        return new Pair();    }    /**    * 回收该对象。调用该方法后需要释放所有对该实例的引用    */    public void recycle(){        synchronized(sPoolSync){            if(sPoolSize < MAX_POOL_SIZE){                next = sPool;                sPool = this;                sPoolSize++;            }        }    }}

注意,本例增加了多个字段,有静态的也有非静态的。可使用这些字段实现传统的 Pair 对象链表。通过使用私有构造函数来防止在类外面创建对象,只能通过 obtain 方法创建该类的对象。 obtain 方法首先会检查对象池中是否包含任何存在的对象,并删除列表中的第一个元素然后返回它。如果对象池为空, obtain 方法会创建一个新的对象。要把对象重新放回池中,需要在使用完该对象时,对它调用 recycle 方法。这时,不能再有对该对象的引用。
另外,由于 obtain 和 recycle 是线程安全的,可以在多个并发线程中安全地使用这两个方法。唯一的缺点是,必须记住要手动调用 recycle 方法,不过这是一个很小的代价。

更多相关文章

  1. Android httpClient Get&Post方法
  2. Android 给textview添加下划线的一种方法(可复用)
  3. Android中两种实现倒计时的方法
  4. Android获取系统内核版本的方法
  5. Android Studio执行Java类的main方法及解决方法
  6. Android 延迟执行方法
  7. Android ExecutorService线程池

随机推荐

  1. Android(安卓)如何创建组合控件
  2. Android网络编程 HttpUrlConnection Http
  3. Android面试之---谈谈你对Android(安卓)N
  4. 【android】喜马拉雅FM sdk使用
  5. Android(安卓)Lint使用分析
  6. [置顶] Android学习之扩展android的权限
  7. Ubuntu下搭建Android开发环境
  8. 提高数倍工作效率的Android(安卓)Studio
  9. Android启动画面的实现方法
  10. 破解Xamarin