高级开发起码得会些高级技巧吧?那这些高级技巧从哪里取得呢? 第一种方式肯定是读书,什么?你没那么多时间? 幸好,我这里忙你开启了速读模式,跟着我一起学习《高效Java》系列。 咱们第一站就来到了:静态工厂方法1。什么是静态工厂方法?静态工厂方法是一种创建对象的方式。这里的静态工厂方法,并不是设计模式中的工厂模式。静态工厂方法仅仅是类的一个普通的静态方法,它的最终效果等同于构造器。 说了这么多,给你举个例子就明白了。IntegerintegerInteger。valueOf(1);BooleanaBooleanBoolean。valueOf(true);CalendarcalendarCalendar。getInstance(); 上面的例子中valueOf和getInstance方法就被称为静态工厂方法。2。静态工厂方法优势 那么为什么鼓励用静态工厂方法来创造对象,而不是鼓励使用构造器呢? 原因有如下几点:静态工厂方法拥有名称,而构造器没有不必在每次调用静态工厂方法时都创建一个对象可以返回当前类的任何子类型对象减少使用者出错的概率 下面我们来逐一了解这些优点: 2。1静态工厂方法拥有名称,而构造器没有 因为构造器的本身并没有确切的描述被返回的对象,而静态工厂方法因为有方法名,所以他能够更为清楚的描述将被返回的对象。尤其是拥有多个不同参数的构造方法,在选择构造方法的时候,会让人有些迷惑,而静态工厂方法则更加清楚明了。Date类Datedate0newDate();Datedate1newDate(2022L);Datedate2newDate(2022);Datedate3newDate(2022,3,20);Datedate4newDate(2022,3,20,18,30,59);LocalDate类publicstaticLocalDatenow(){}publicstaticLocalDateofEpochDay(longepochDay){}publicstaticLocalDateof(intyear,Monthmonth,intdayOfMonth){} 看下这么多不同参数的构造方法,如果不去了解Date,懵不懵?再看看Java8中的LocalDate类。 2。2不必在每次调用静态工厂方法时都创建一个对象 构造器每次调用的时候都会创建一个新的对象,而使用静态工厂方法则可以不必每次都创建新的对象,我们可以提前创建好对象或重用已有的对象,以达到提升性能的目的。 来我给你们举个例子: 1、Integer类中的valueOf方法,当数值在128127之间时,是不会创建新的Integer类的,而是从缓存中取出。publicstaticIntegervalueOf(inti){if(iIntegerCache。lowiIntegerCache。high)returnIntegerCache。cache〔i(IntegerCache。low)〕;returnnewInteger(i);} 2、Boolean类中的valueOf方法,直接取出提前创建好的静态常量返回,也没有创建新的对象。publicfinalclassBoolean{publicstaticfinalBooleanTRUEnewBoolean(true);publicstaticfinalBooleanFALSEnewBoolean(false);publicstaticBooleanvalueOf(booleanb){return(b?TRUE:FALSE);}} 2。3可以返回原类型的任何子类型对象 这里牵涉到最基础的多态:向上转型:多态本身就是向上转型过的过程使用格式:父类类型变量名new子类类型(); 还有就是设计模式六大原则中的里氏替换原则:任何使用父类的地方都能替换成子类来使用。publicclassTest{静态工厂方法,返回Test的子类型T1publicstaticTestvalueOf(){returnnewT1();}privatestaticclassT1extendsTest{}} 虽然可以这样用,但是不建议这样使用,因为这样不利于解耦,父类最好不要依赖于子类。 推荐的做法是:像Collections类一样,它像一个工具类,它提供了许多静态工厂方法,你去看会发现静态工厂方法返回的并不是确定的类型,而是List接口的一些子类,这些子类被作为私有类定义在Collections中,我们无法直接构造这些类,但却可以通过静态工厂方法使用它。 这样做的目的是精减API的数量,对客户端来说也是一种减压。我们有时不必知道返回的类是什么,但我们可以像我们熟知的接口一样使用它。SingletonList是私有的,实现List接口的类publicstaticTListTsingletonList(To){returnnewSingletonList(o);}EmptyList是私有的,实现List接口的类publicstaticfinalTListTemptyList(){return(ListT)EMPTYLIST;} 2。4减少使用者出错的概率 先看下例子:classRun{publicstaticfinalintRUNNING1;publicstaticfinalintSTOP2;publicRun(intstate){this。}publicvoidprocess(){ifRUNNINGSTOP}} 上面例子中,我只想对RUNNINGSTOP两种状态处理,但我却无法控制使用者的行为,比如他可以这样调用:newRun(4) 这种情况怎么办呢?classRun{publicstaticfinalintRUNNING1;publicstaticfinalintSTOP2;私有构造方法外部无法调用privateRun(intstate){this。}publicstaticRunrunning(){returnnewRun(RUNNING);}publicstaticRunstop(){returnnewRun(STOP);}publicvoidprocess(){ifRUNNINGSTOP}} 经过这样改造后,我们严格控制了取值范围,使用者出错的机会就大大减少了。3。总结 作为类的提供者,我们要尽量确保自身性能好,具有灵活性,让使用者使用起来更容易,更不容易出错。 恰恰静态工厂方法可以让我们做到这些,所有建议创建对象的时候优先考虑使用静态工厂方法。 作者:非常王不二 链接:https:juejin。cnpost7077750408667463717