Effective+Java中文版第二版---(创建和销毁对象总结)

  1. 考虑用静态方法代替构造器
    优点:
    便于理解,每个静态方法命名都是根据含义来的,而构造方法是跟类名相同,只有通过构造方法参数区别,每 个构造方法的作用
    不必每次创建实例,可以使用预先生成的实例,或者缓存的实例
    可以返回原返回类型的子类型
    构造参数化实例时,构造函数必须写上参数,如果参数比较多,久会很冗长,但是静态方法不同
    缺点:
    无公有构造方法,则不能被子类化(因祸得福,程序估计复合,而不是继承)

  2. 遇到多个构造器参数时建议使用构建器
    静态方法和构造器相同的缺点:不能很好的扩展到大量的可选参数
    那对于大量的可选参数的时候,如何构造实例呢,有以下3种方式
    设置多个构造器,参数由少变多,依次调用下个构造器(重叠构造器)
    可行,但是遇到大量参数时,代码不易写,阅读起来有难度,再则如果后期添加参数,则需要添加新的构造器, 以及遇到一大堆相同类型的参数时,构造实例时参数值传错,编译器不会报错,问题难找

    public class Human {
            private  Long id;
            private String name;
            private int age;
            private String city;
            private String address;
            private String email;
            private String phone;

            public Human(Long id) {
                this( id, null);
            }

            public Human(Long id, String name) {
                this( id,  name, 0);
            }

            public Human(Long id, String name, int age) {
                this( id,  name,  age,   null);
            }

            public Human(Long id, String name, int age, String city) {
                this( id,  name,  age,  city, null);
            }

            public Human(Long id, String name, int age, String city, String address) {
                this( id,  name,  age,  city,  address, null);
            }

            public Human(Long id, String name, int age, String city, String address, String email) {
               this( id,  name,  age,  city,  address,  email,null);
            }
            public Human(Long id, String name, int age, String city, String address, String email, String phone) {
                this.id = id;
                this.name = name;
                this.age = age;
                this.city = city;
                this.address = address;
                this.email = email;
                this.phone = phone;
            }
        }

使用默认无参构造器
创建实例后,在使用set方法设置value
构造过程可能处于不同状态, 可能导致javabeans不一致的状态,(A线程处理Human,设置参数时,B线程也在处理,获取参数,则B线程获取的数据会处问题)并且类不能校验正确性

public class Human {
                private  Long id;
                private String name;
                private int age;
                private String city;
                private String address;
                private String email;
                private String phone;

                public Long getId() {
                    return id;
                }

                public void setId(Long id) {
                    this.id = id;
                }

                public String getName() {
                    return name;
                }

                public void setName(String name) {
                    this.name = name;
                }

                public int getAge() {
                    return age;
                }

                public void setAge(int age) {
                    this.age = age;
                }

                public String getCity() {
                    return city;
                }

                public void setCity(String city) {
                    this.city = city;
                }

                public String getAddress() {
                    return address;
                }

                public void setAddress(String address) {
                    this.address = address;
                }

                public String getEmail() {
                    return email;
                }

                public void setEmail(String email) {
                    this.email = email;
                }

                public String getPhone() {
                    return phone;
                }

                public void setPhone(String phone) {
                    this.phone = phone;
                }
            }

Builder模式,在要构造多个构造方法的类中,创造一个静态构建类,然后将要动态设置参数的属性,放进这个构建类种,然后通过javabeans或则静态方法,创建构建类,再设置属性值,即让原有类不直接生成实例


        public class Human {
        private  Long id;
        private String name;
        private int age;
        private String city;
        private String address;
        private String email;
        private String phone;

        public Human(Builder builder) {
            this.id = builder.getId();
            this.name = builder.getName();
            this.age = builder.getAge();
            this.city = builder.getCity();
            this.address = builder.getAddress();
            this.email = builder.getEmail();
            this.phone = builder.getPhone();
        }

        public static  class Builder{
            private  Long id;
            private String name;
            private int age;
            private String city;
            private String address;
            private String email;
            private String phone;

            public Long getId() {
                return id;
            }

            public void setId(Long id) {
                this.id = id;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            public int getAge() {
                return age;
            }

            public void setAge(int age) {
                this.age = age;
            }

            public String getCity() {
                return city;
            }

            public void setCity(String city) {
                this.city = city;
            }

            public String getAddress() {
                return address;
            }

            public void setAddress(String address) {
                this.address = address;
            }

            public String getEmail() {
                return email;
            }

            public void setEmail(String email) {
                this.email = email;
            }

            public String getPhone() {
                return phone;
            }

            public void setPhone(String phone) {
                this.phone = phone;
            }

            public Human build(){
                return new Human(this);
            }

        }

    }
  1. 使用私有构造方法或枚举创建单例属性
    jdk1.5前 私有构造方法,要导出一个公有的静态属性

        public class Human {
    
            public static final Human human = new Human();
    
            private Human(){ }
    
        }
        public class Human {
    
        private  static final Human human = new Human();
    
        private Human(){ }
    
        public Human getInstance(){
            return human;
        }
    
    }

    上面2种方法,都可以创建单例对象,但是享有特权的客服端,如果使用反射的方式,调用私有构造器,创建实例,则便不是单列对象,所以要防止2次创建实例,给予提示,并抛出异常;
    jdk1.5后,可采用枚举创建,那么对象只会是单例的

  2. 将不允许继承的类的构造方法,私有化
    有些类中,只包含静态方法和静态属性,其实可以直接类名调用,但是有些人懒用这些类,但其实这些类又有其存在的价值,比如java.util.Arrays,其实这样的类是不需要使用则创建实例,以及是不允许继承的,那么这样的类设置其构造器为私有的

  3. 避免创建不必要的对象
    大家都知道,创建对象时,栈和堆都将开辟新空间,如果不断的创建对象,则会导致堆或栈溢出,特别是在循环和迭代的情况下,所以在不需要创建对象的时候,就不需要,尽量可以是一次创建多次使用

  4. 消除过期的引用对象
    最典型得就是栈,大家都知道,栈是一个先进后出的数据格式,当压入一个数据后,再取出一个数据时,其实其数组长度没有变,取出的数据,则不会被垃圾回收站给回收了,因为此时数组还在引用,这样整个栈都取出后,数组也不会变,即引用的对象也一直存在,所以要在每次取出栈中数据的时候,elements[size] = null;清空数组当时的引用的数据值,使其回收

public class Stack {
            private Object[] elements;
            private int size = 0;
            private static final int DEFAULT_INITIAL_CAPACITY = 16;

            public Stack() {
                elements = new Object[DEFAULT_INITIAL_CAPACITY];
            }

            public void push(Object e) {
                ensureCapacity();
                elements[size++] = e;
            }

            public Object pop() {
                if (size == 0)
                    throw new EmptyStackException();
                Object result = elements[--size];
                elements[size] = null;//显式地清空引用
                return result;   
            }


            private void ensureCapacity() {
                if (elements.length == size)
                    elements = Arrays.copyOf( elements, 2 * size + 1 );
            }
        }
  1. 避免使用终结方法

    finalize()基本概念
    所谓的终结方法其实是指finalize()。终结方法finalizer通常是不可预测的,也是很危险的。一般情况下是不必要的。使用终结方法会导致行为不稳定,降低性能,以及可移植性问题。根据经验,应避免使用终结方法。
    finalize()的执行过程
    当对象不可达时,GC会判断该对象是否重写了finalize()方法,如没有重写则直接将其回收,否则,若对象未执行过finalize()方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize()方法。执行finalize()方法完后,GC会再次判断该对象是否可达,若不可达则进行回收。否则对象“复活”。
    finalize()的缺点
    在java中,当对象不可达时,垃圾回收会回收与之相关的存储控件,不需要专门做,但Java的垃圾回收机制只负责内存相关清理,其他连接资源,比如DB连接,文件流释放都需要手动完成,如果滥用finalize()方法来释放资源,有可能文件还会在打开状态(.Java语言规范不仅不能保证finalize()方法会被及时的执行,而且根本就不保证他们会执行),所以再次打开时可能会出错
    不同jvm虚拟机对finalize算法不同,在本地测试通过,在客户机上根本无法运行,也是有可能的
    性能问题,某测试数据:创建和销毁一个简单对象的时间大约为5.6ns。增加一个finalize()使时间增加到了2400ns。换句话说,用终结方法创建和销毁对象慢了大约430倍。
    finalize()的优点
    1.当对象的所有者忘记调用之前建议的显示终止方法时,finalize()可以充当安全网,safety net。虽然这种做并不能保证finalize()会被及时的调用,但是在客户端无法通过调用显示的finalize()来正确结束操作的情况下(希望这种情形尽可能的少发生),迟一点释放关键资源总比永远不释放要好。如果正考虑编写这样的安全网终结方法,就要考虑清楚这种额外的保护是否值得付出额外的代价。
    显示finalize()模式的实例中所示的四个类FileInputStream,FileOutputStream,Timer和Connection,都具有终结方法。当他们的显示的终止方法未能被调用的情况下,这些finalize()充当了安全网。
    2.finalize()的第二种合理用于与对象的本地对等体native peer有关。本地对等体是一个本地对象native object,普通对象通过本地方法native method委托给一个本地对象。因为本地对等体不是一个普通对象,所以垃圾回收器不会知道它。当它的Java对等体被回收的时候,它不会被回收。在本地对等体并不拥有关键资源的前提下(注是否因为关键资源可被本地其他进程使用),finalize()正是执行任务的最合适的工具。如果本地对等体用于必须被及时终止的资源, 那么该类就应该具有一个显示的终止方法,如前所述。终止方法应该完成所有必要的工作以便释放关键的资源。终止方法可以使本地方法或者也可以调用本地方法。
    五、使用finalize()的建议
    尽量少用finalize,最好由系统管理,我们可以定义其他的方法来释放非内存资源。
    除非是作为安全网或者是为了终止非关键的本地资源,否则请不要使用终结方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值