标签:
常用的场景是,查询时,有多个参数。因此构建查询参数对象时,考虑使用Builder模式。
public class QueryBuilder {
    //查询的每个参数,不需要set方法
    private  String userName;
    private String mobile;
    private int cityId;
    private int pageNum;
    private int pageSize;
    //提供一个Builder实例
    public static Builder newBuilder(){
        return new Builder();
    }
    //共有的public 静态static内部类
    public static class Builder{
        private  String userName;
        private String mobile;
        private int cityId;
        private int pageNum;
        private int pageSize;
        //每个方法都是公有的 
        public Builder withUserName(String userName){
            this.userName = userName;
            return this;
        }
        public Builder withMobile(String mobile){
            this.mobile = mobile;
            return this;
        }
        public Builder withCityId(int cityId){
            this.cityId = cityId;
            return this;
        }
        public Builder withPageNum(int pageNum){
            this.pageNum = pageNum;
            return this;
        }
        public Builder withPageSize(int pageSize){
            this.pageSize = pageSize;
            return this;
        }
        //最后提供一个build方法,返回查询类
        public QueryBuilder build(){
            return new QueryBuilder(this);
        }
    }
    //查询类构造方法私有,接收一个Builder参数
    private QueryBuilder(Builder builder){
        userName = builder.userName;
        mobile = builder.mobile;
        cityId = builder.cityId;
        pageNum = builder.pageNum;
        pageSize = builder.pageSize;
        //可以根据需要提供一个boolean hasQuery字段,用于判断是否有查询条件
        //没有查询条件时,返回所有值
        /*hasQuery = StringUtils.isNotEmpty(userName)
                || StringUtils.isNotEmpty(mobile)
                || cityId > 0;
       */
    }
}
    public String getUserName() {
        return userName;
    }
    public String getMobile() {
        return mobile;
    }
    public int getCityId() {
        return cityId;
    }
    public int getPageNum() {
        return pageNum;
    }
    public int getPageSize() {
        return pageSize;
    }
    public boolean isHasQuery() {
        return hasQuery;
    }
//使用
QueryBuilder.Builder builder = QueryBuilder.newBuilder();
QueryBuilder query = builder.withUserName("name1").withMobile("13456463216")
                            .withCityId(1).withPageNum(0).withPageSize(10)
                            .build();这里主要写一下Java的Sigleton模式吧,下文讨论的内容引入了其他博文 
http://blog.csdn.net/cnyyx/article/details/7482735 
http://my.oschina.net/alexgaoyh/blog/261106?fromerr=FT8qyEHA
public class Singleton {
    //私有化构造器,防止外部new Singleton()
    private Singleton(){}
    private static final Singleton instance = new Singleton();
    public static Singleton getInstance(){
        return instance;
    }
}这种方法在类加载的时候就会创建一个Singleton对象,不管该资源是否被请求,占用Jvm内存。
public class Singleton {
    private Singleton(){}
    private static Singleton instance;
    public static synchronized Singleton getInstance(){
        if(null == instance){  //@1
            instance = new Singleton(); //@2
        }
        return instance;
    }
}该方法加载了同步锁,可以防止多线程在执行getInstance方法得到2个对象,如果不加synchronized关键字,考虑线程A、B 
     A执行 @1 还未执行 @2 
     B执行 @1 还未执行 @2 
     将会得到2个对象 
     缺点:只有在第一次调用的时候才需要同步,一旦instance部位null了,系统依旧花费同步锁开销,有点得不偿失
    private Singleton(){}
    private static Singleton instance;
    public static Singleton getInstance(){
        if(null == instance){  //@1
            synchronized (Singleton.class){ //@2
                instance = new Singleton(); //@3
            }
        }
        return instance;
    }这种写法减少了锁开销,但是在如下情况,却创建了2个对象: 
     a:线程1执行到1挂起,线程1认为singleton为null 
     b:线程2执行到1挂起,线程2认为singleton为null 
     c:线程1被唤醒执行synchronized块代码,走完创建了一个对象 
     d:线程2被唤醒执行synchronized块代码,走完创建了另一个对象 
     所以看出这种写法,并不完美。
    private Singleton(){}
    private static Singleton instance;
    public static Singleton getInstance(){
        if(null == instance){  //@1
            synchronized (Singleton.class){//@2
                if(null == instance){//@3
                    instance = new Singleton();//@4
                }
            }
        }
        return instance;
    }在同步锁代码块内部,再判断一次对象是否为null,为null才创建对象。这种写法已经接近完美: 
     a:线程1执行到1,已经进入synchronized的时候,线程挂起,线程1占有Singleton.class资源锁; 
     b:线程2执行到1,当它准备synchronized块时,因为Singleton.class被占用,线程2阻塞; 
     c:线程1被唤醒,判断出对象为null,执行完创建一个对象 
     d:线程2被唤醒,判断出对象不为null,不执行创建语句 
     如此分析,发现似乎没问题。 
     但是实际上并不能保证它在单处理器或多处理器上正确运行; 
     问题就出现在singleton = new Singleton()这一行代码。它可以简单的分成如下三个步骤: 
     mem= singleton();//1 
     instance = mem;//2 
     ctorSingleton(instance);//3 
     这行代码先在内存开辟空间,赋给singleton的引用,然后执行new 初始化数据,但是注意初始化是要消耗时间。如果此时线程3在执行步骤1的时候,发现singleton 为非null,就直接返回,那么线程3返回的其实是一个没构造完成的对象。 
     我们期望1,2,3 按照反序执行,但是实际jvm内存模型,并没有明确的有序指定。 
     这归咎于java的平台的内存模型允许“无序写入”。
    private Singleton(){}
    private static volatile Singleton instance;
    public static Singleton getInstance(){
        if(null == instance){  //@1
            synchronized (Singleton.class){//@2
                if(null == instance){//@3
                    instance = new Singleton();//@4
                }
            }
        }
        return instance;
    }Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。 
 但是5的写法,虽然理论上似乎可以解决无序写入问题。实际上并非如此。
        private Singleton(){}
    private static class InstanceHolder{
        private static final Singleton instance = new Singleton();
    }
    public static Singleton getInstance(){
        return InstanceHolder.instance;
    }JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次, 
并且会保证把赋值给instance的内存初始化完毕,这样我们就不用担心上面的问题(方法4)。此外该方法也只会在第一次调用的时候使用互斥机制,这样就解决了低效问题(方法2)。 
     最后instance是在第一次加载InstanceHolder类时被创建的,而InstanceHolder类则在调用getInstance方法的时候才会被加载,因此也实现了惰性加载。
public enum A{
        INSTANCE;
        public void invoke(){...}
}有时候可能需要编写只包含静态方法和静态域的类,如工具类。最好给其提供一个私有构造器,否则编译器会为其生成一个默认的无参构造函数。
public class MobileUtils {
    private MobileUtils(){}
    /**
     * 隐藏手机号中间4位
     * @param mobile
     * @return String 隐藏手机号中间4位之后的手机号
     */
    public static String hideMobile(String mobile) {
        if (StringUtils.isEmpty(mobile)) {
            return StringUtils.EMPTY;
        }
        if (mobile.length() < 8) {
            return StringUtils.EMPTY;
        }
        return mobile.substring(0, 3) + "****" + mobile.substring(7);
    }
} 对于同时提供了构造器和静态工厂方法,通常使用静态工程方法而不是构造器,以避免
 创建不必要的对象,比如Boolean.valueOf(String)比new Boolean(String)要好,构造器每次
 被调用时都要创建一个新的对象,静态工厂方法则没有这种要求,也不会这样做
 下面是Boolean的部分源码,查看其valueOf方法
     public static final Boolean TRUE = new Boolean(true);
     public static final Boolean FALSE = new Boolean(false);
     public static Boolean valueOf(String s) {
        return toBoolean(s) ? TRUE : FALSE;
     }
     private static boolean toBoolean(String name) {
        return ((name != null) && name.equalsIgnoreCase("true"));
     }这里只能说学习,主要看的是ArrayList吧,对不用的对象是如何处理的。
protected void removeRange(int fromIndex, int toIndex) {
         modCount++;
         int numMoved = size - toIndex;
         System.arraycopy(elementData, toIndex, elementData, fromIndex,
         numMoved);
         // clear to let GC do its work 就是这里!
         int newSize = size - (toIndex-fromIndex);
         for (int i = newSize; i < size; i++) {
         elementData[i] = null;
         }
         size = newSize;
     }
     public static native void arraycopy(Object src,  int  srcPos,
        Object dest, int destPos,int length);简单总结一下: 
1、是否是同一个对象的引用 
2、类型转换 
3、域的比较,在比较时,优先比较区分度大的域 
注意:这里有个坑:equals方法的参数是Object,而不是自己定义的类。否则直接变成代码重载,而不是重写了!! 
@Override的作用也可以看到了 书中36条:坚持使用Override注解
@Override
public boolean equals(Object anObject) {
        if (this == anObject) {//是否是同一个对象的引用
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;//转换为该对象类型
            int n = value.length;  //管家field的值比较,先比较区分度比较大的!
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }主要考虑Java 深拷贝和浅拷贝
浅拷贝(浅复制、浅克隆):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。
深拷贝(深复制、深克隆):被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,
而不再是原有的那些被引用的对象。
换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。
clone基本类型 深拷贝
clone对象类型 浅拷贝,重写clone方法,将对象引入一一clone,即可实现深拷贝
    // 改为深复制:
    Student2 student = (Student2) super.clone();
    // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
    student.setTeacher((Teacher) student.getTeacher().clone());
serialization序列化 深拷贝
类的比较,主要有两种方法,一种是类实现Comparable接口,重写compareTo方法;另外一种是在集合比较的时候,新建一个Comparator,重写compare方法。与书中hashCode讲解有点关系的部分是:hashCode影响:HashSet、HashMap、HashTable 
compareTo影响:TreeSet、TreeMap、Collections、Arrays。
自我感觉关于整数比较时,尽量直接<>直接比较,通过减法有可能溢出! 
另外,有点不太相关的内容,在比较时,返回-1、0、1表示大小关系,其实只要返回一个符号(正负)就行,看到了Long的signum方法
public static int signum(long i) {
        return (int) ((i >> 63) | (-i >>> 63));
    }直接通过移位,不需要比较操作符,一句话搞定!吊吊的!Long的rotate和reverse也很吊!
标签:
原文地址:http://blog.csdn.net/bupt09211303/article/details/51603747