Java中不可或缺的59个小技巧,贼好用!(一)

简介: 《Effective JavaJava》名著,必读。如果能严格遵从本文的原则,以编写API的质量来苛求自己的代码,会大大提升编码素质。以下内容只记录了我自己整理的东西,还是建议读原文。为了聚焦知识点,一些说明故意忽略掉了。相当于是一篇摘要。

1、考虑用静态工厂方法替代构造函数

例子:

Integer.valueOf(“1”)、Boolean.valueOf(“true”)等。

优势:

  • 可读性高(方法名)
  • 性能(不一定创建对象)
  • 灵活性高

下面针对三个优势进行一些解读。

可读性高

new Point(x,y)和Point.at(x,y)、Point.origin()。构造函数只能看出两个参数,不知其意,后者更易理解。

性能

在某些情况下,可以事先进行实例化一些对象,调用时直接调用即可,不需要进行改变。比如,Boolean。

public final class Boolean implements Serializable, Comparable<Boolean> {
    // 预先设置两个对象
    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);
    public Boolean(boolean var1) {
        this.value = var1;
    }
    public Boolean(String var1) {
        this(parseBoolean(var1));
    }
    // 工厂方法
    public static Boolean valueOf(boolean var0) {
        return var0?TRUE:FALSE;    // 返回预先设置的对象,而不是创建对象
    }
    // 工厂方法
    public static Boolean valueOf(String var0) {
        return parseBoolean(var0)?TRUE:FALSE;
    }
    // ... other code
}

灵活性高

可根据具体情况,返回子类。相当于更强大的工厂。直接从父类获取到子类。尤其适用于工具类(提供各种API)。例子:Collections。

public class Collections {
    // 私有,典型工厂
    private Collections() {
    }
    public static final List EMPTY_LIST = new EmptyList<>();
    // 工厂方法
    public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
    }
    private static class EmptyList<E> extends AbstractList<E> implements RandomAccess, Serializable {
    // code
    }
    // 工厂方法
    public static <E> List<E> checkedList(List<E> list, Class<E> type) {
    // 根据具体情况,获取相应子类
        return (list instanceof RandomAccess ?
                new CheckedRandomAccessList<>(list, type) :
                new CheckedList<>(list, type));
    }
    // 子类1
    static class CheckedRandomAccessList<E> extends CheckedList<E> implements RandomAccess {
        CheckedRandomAccessList(List<E> list, Class<E> type) {
            super(list, type);
        }
        public List<E> subList(int fromIndex, int toIndex) {
            return new CheckedRandomAccessList<>(
                    list.subList(fromIndex, toIndex), type);
        }
    }
    // 子类2
    static class CheckedList<E> extends CheckedCollection<E> implements List<E> {
    // code
    }
}

2、多个构造函数时,考虑使用构造器

尤其在进行Android开发时,会碰到这种情况。通常是一个对象,具有多个成员变量可能需要初始化,常规方法,需要提供大量构造函数。例如:

// 非Android中的AlertDialog,便于说明问题,举个例子
public class AlertDialog {
    private int width;
    private int height;
    private String title;
    private String confirmText;
    private String denyText;
    private AlertDialog(){}
    public AlertDialog(int width, int height){    // 空白的警告框
         AlertDialog(width,height,null);
    }
    // 带标题的警告框
    public AlertDialog(int width, int height, String title){    // 带标题的警告框
        AlertDialog(width, height, title, "确定");
    }
    // 带标题的警告框,有确定按钮
    public AlertDialog(int width, int height, String title, String confirm){   
        AlertDialog(width, height, title, confirm, null);
    }
    // 带标题的警告框,有确定按钮,取消按钮
    public AlertDialog(int width, int height, String title, String confirm, String denyText){
        // set every thing.
    }
}

有多种样式的警告框,为了调用方便,必须提供多个构造函数。否则用户在调用时,只能使用完整构造函数,容易犯错且无法进行阅读。极不灵活。如果采用另外一种方式,则可以解决,但会花费很多经历处理并发的情况:

// 非Android中的AlertDialog,便于说明问题,举个例子
public class AlertDialog {
    private int width;
    private int height;
    private String title;
    private String confirmText;
    private String denyText;
    public AlertDialog(){}// 空白的构造函数
    public void setWidth(int width){
        this.width = width;
    }
    // 其他set方法
}

调用时,通过调用各个参数的set方法进行设置。问题来了:

  1. 并发
  2. 无法进行参数校验。例如,只创建了对象,设置了标题,却没有尺寸,相当于创建了一个没有尺寸的警告框。

在Android中,大量的控件都使用了构造器Builder。

// 非Android中的AlertDialog,便于说明问题,举个例子
public class AlertDialog {
    private int width;
    private int height;
    private String title;
    private String confirmText;
    private String denyText;
    // private
    private AlertDialog(){}
    // Builder中使用
    protected AlertDialog(Builder b){
        width = b.width;
        height = b.height;
        // .....
        if(width==0||height==0) throws new Exception("size must be set");
    }
    // 构造器
    public static class Builder {
        private int width;
        private int height;
        private String title;
        private String confirmText;
        private String denyText;
        // 注意:返回的Builder。
        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }
        // 其他set...
        public AlertDialog build(){
            return AlertDialog(this);
        }
    }
}

于是,可以根据相应需求,进行相应设置,并在AlertDialog真正构造时,进行参数校验。就像这样:

new AlertDialog.Builder().setTitle("提示").build();

上述例子,会成功抛出异常。

相关文章
|
安全 Java API
Java中不可或缺的59个小技巧,贼好用!(三)
《Effective JavaJava》名著,必读。如果能严格遵从本文的原则,以编写API的质量来苛求自己的代码,会大大提升编码素质。 以下内容只记录了我自己整理的东西,还是建议读原文。为了聚焦知识点,一些说明故意忽略掉了。相当于是一篇摘要。
157 0
|
设计模式 缓存 IDE
Java中不可或缺的59个小技巧,贼好用!(二)
《Effective JavaJava》名著,必读。如果能严格遵从本文的原则,以编写API的质量来苛求自己的代码,会大大提升编码素质。 以下内容只记录了我自己整理的东西,还是建议读原文。为了聚焦知识点,一些说明故意忽略掉了。相当于是一篇摘要。
213 0
|
缓存 IDE 安全
Java中不可或缺的59个小技巧,贼好用!
Java中不可或缺的59个小技巧,贼好用!
137 0
|
缓存 IDE 安全
读完 Effective Java,我整理这 59 条技巧!
如果能严格遵从本文的原则,以编写API的质量来苛求自己的代码,会大大提升编码素质。 以下内容只记录了我自己整理的东西,还是建议读原文。为了聚焦知识点,一些说明故意忽略掉了。相当于是一篇摘要。
|
3天前
|
安全 Java 调度
Java线程:深入理解与实战应用
Java线程:深入理解与实战应用
22 0
|
1天前
|
消息中间件 缓存 NoSQL
Java多线程实战-CompletableFuture异步编程优化查询接口响应速度
Java多线程实战-CompletableFuture异步编程优化查询接口响应速度
|
1天前
|
数据采集 存储 Java
高德地图爬虫实践:Java多线程并发处理策略
高德地图爬虫实践:Java多线程并发处理策略
|
2天前
|
缓存 Java
【Java基础】简说多线程(上)
【Java基础】简说多线程(上)
6 0
|
2天前
|
并行计算 算法 安全
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
|
3天前
|
安全 Java 编译器
是时候来唠一唠synchronized关键字了,Java多线程的必问考点!
本文简要介绍了Java中的`synchronized`关键字,它是用于保证多线程环境下的同步,解决原子性、可见性和顺序性问题。从JDK1.6开始,synchronized进行了优化,性能得到提升,现在仍可在项目中使用。synchronized有三种用法:修饰实例方法、静态方法和代码块。文章还讨论了synchronized修饰代码块的锁对象、静态与非静态方法调用的互斥性,以及构造方法不能被同步修饰。此外,通过反汇编展示了`synchronized`在方法和代码块上的底层实现,涉及ObjectMonitor和monitorenter/monitorexit指令。
16 0