栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

创建和销毁对象开发规范

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

创建和销毁对象开发规范

规范化代码

创建对象

构造方法创建对象

注意点 构造器创建对象

示例优点缺点 静态工厂方法创建对象

示例:优点缺点 总结创建对象方法 保证单例 Singleton

静态工厂方法创建单例对象

示例注意 枚举创建单例对象

示例注意 创建对象注意

不要创建不必要对象

示例注意 消除过期的对象引用

示例注意 销毁对象

避免使用销毁对象方法处理必须关闭的资源

示例原因 观 JAVA EFFECTIVE有感

创建对象 构造方法创建对象
@Setter
@Getter
public class Address {

    private String province;
    private String city;
    private String area;

    public static void main(String[] args) {
        Address address = new Address();
    }
注意点
    参数较少的情况下,使用构造方法较为清晰;参数多的构造方法,需要花费较多时间清楚参数含义;参数较多,使用无参构造方法,需要执行大量的set方法。每次调用构造方法,都会创建一个新对象。每次调用构造方法,返回当前类型对象,无法返回子类对象。
构造器创建对象 示例
public static void main(String[] args) {
    Address address = Address.builder().area("area").city("city").province("province").build();
}

// lombok的@Builder注解生成代码
public class Address {
    private String province;
    private String city;
    private String area;

    Address(final String province, final String city, final String area) {
        this.province = province;
        this.city = city;
        this.area = area;
    }

    public static Address.AddressBuilder builder() {
        return new Address.AddressBuilder();
    }

    public static class AddressBuilder {
        private String province;
        private String city;
        private String area;

        AddressBuilder() {
        }

        public Address.AddressBuilder province(final String province) {
            this.province = province;
            return this;
        }

        public Address.AddressBuilder city(final String city) {
            this.city = city;
            return this;
        }

        public Address.AddressBuilder area(final String area) {
            this.area = area;
            return this;
        }

        public Address build() {
            return new Address(this.province, this.city, this.area);
        }

        public String toString() {
            return "Address.AddressBuilder(province=" + this.province + ", city=" + this.city + ", area=" + this.area + ")";
        }
    }
}
优点
    链式编程,支持可变参数。可以使用Builder创建多个对象。
缺点

创建对象前,需要创建构造器

静态工厂方法创建对象 示例:
Collectors类中的静态方法
public static  Collector> toList() {
    return ......;
}

public static  Collector> toSet() {
    return ......;
}

public static Collector joining() {
    return ......;
}

public static Collector joining(CharSequence delimiter) {
    return joining(delimiter, "", "");
}

public static Collector joining(CharSequence delimiter, 
        CharSequence prefix, CharSequence suffix) {
    return new CollectorImpl<>(() -> new StringJoiner(delimiter, prefix, suffix),
                StringJoiner::add, StringJoiner::merge, StringJoiner::toString, CH_NOID);
}

Boolean类中的静态方法
public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}
优点
    静态工厂方法有名称,支持望名知意。如示例中的第一、二个静态方法。不会在每次调用后创建新对象。如示例中的第六个静态方法。可以返回指定类型的子类对象。如示例中的第一、二个静态方法。返回对象随着静态方法参数值变化而变化。如示例中的第五个静态方法。
缺点
    类中没有共有(public)/受保护(protected)的构造器,就不能被子类化。在项目中找到指定类型的静态工厂方法,有些困难。
总结创建对象方法

三种方法没有优劣之分,需要根据不同场景,选择创建对象方式。

保证单例 Singleton 静态工厂方法创建单例对象 示例
public final class Boolean implements java.io.Serializable, Comparable {
    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);
    
    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }
}
注意
    使用静态属性可以保证单例。由于用 构造方法创建对象都会创建一个新对象,因此使用private关键字修饰构造方法,在某种程度上可以保证单例。使用反射的方式,可以强行调用private的构造方法。针对这种情况,可以选择枚举保证单例。
枚举创建单例对象 示例
 public enum BooleanEnum {

    
    TRUE(Boolean.TRUE),
    
    
    FALSE(Boolean.FALSE),
    ;

    private Boolean value;

    BooleanEnum(Boolean value) {
        this.value = value;
    }

    public Boolean getValue() {
        return value;
    }

    public void setValue(Boolean value) {
        this.value = value;
    }
}
注意

实现单例的最佳方案。

创建对象注意 不要创建不必要对象 示例
// 错误示例
boolean flag = false;
if (flag) {
    return false;
} else {
    return true;
}

String s = new String("test");
// 正确示例
boolean flag = false;
return !flag;

String s = "test";
注意
    重复创建成本较高的对象,推荐缓存。举例:Pattern正则实例。优先使用基本数据类型而不是装箱基本类型。小对象的创建和回收成本不高,可以通过创建附加对象使程序逻辑清晰。除非对象是非常重量级的,否则不推荐使用 对象池 维护对象。举例:数据库连接池、线程池。
消除过期的对象引用 示例
public class Stack {

    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INIT_CAPACITY = 16;

    public Stack() {
        this.elements = new Object[DEFAULT_INIT_CAPACITY];
    }

    public void push(Object o) {
        resize();
        elements[size++] = o;
    }

    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        return elements[size--];
    }

    private void resize() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, size * 2 + 1);
        }
    }
}
注意
    示例中的代码没有明显错误。但是随着数组中元素增加,不释放,会逐渐导致性能降低,严重的情况下会导致OutOfMemoryError错误。修复问题不复杂,pop方法如下修改即可。
     public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        Object element = elements[size--];
        element = null;
        return element;
    }
    内存泄漏的可能原因:类自行管理内存、长时间不使用的缓存。
销毁对象 避免使用销毁对象方法

JVM中有一套成熟的垃圾处理机制,强行使用自定义销毁对象方法,可能出现未知的异常情况;如果自行本人开发实力比开发JVM虚拟机的大牛强,推荐自定义研发一套JVM机制。

处理必须关闭的资源

推荐使用try-with-resource。

示例
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(path))){
    return bufferedReader.readLine();
} catch (IOException e) {
    e.printStackTrace();
}
原因

相对于 try-finally处理更加优雅,finally中执行close方法可能抛出异常。

观 JAVA EFFECTIVE有感
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/782408.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号