1. 程式人生 > >Java物件學習之建立物件——使用靜態工廠方法代替構造器優點(二)

Java物件學習之建立物件——使用靜態工廠方法代替構造器優點(二)

最近學習Android知識,發現Java好多的基礎知識運用的真的很一般,所以決定在重新梳理一下,現在Kotlin也來了,在Android之路上,留給我看Java的時間不多了。

      靜態我們就來簡單介紹一下,使用靜態工廠方法建立物件相較於構造器建立的物件的優缺點。主要概括如下:

優點:

  • 靜態工廠方法有名稱,可以明確的建立對應功能和屬性的Java物件
  • 靜態工廠方法可以預構建Java物件,實現在必要的情況下建立儘量少的物件例項
  • 靜態工廠方法可以獲取預構建Java物件的任何子類物件
  • 靜態工廠方法在構建引數化例項的時候,程式碼更簡潔

缺點:

  • Java類如果沒有公有的或者受保護的構建器,就不能被子類化
  • 靜態工廠方法和一般靜態方法沒有任何區別

靜態工廠方法與構造器建立Java物件的對比已經介紹完了,下面就來針對優點當中的第二條結合程式碼說明一下。

 

1,靜態工廠方法建立物件優點二

 

首先我們來看一下Java jdk中的一個關於Boolean類的原始碼示例:

 

Boolean例項有:

/**
 * The {@code Boolean} object corresponding to the primitive
 * value {@code true}.
 */
public static final Boolean TRUE = new Boolean(true);

/**
 * The {@code Boolean} object corresponding to the primitive
 * value {@code false}.
 */
public static final Boolean FALSE = new Boolean(false);

 

其中的靜態工廠方法部分有:

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

public static Boolean valueOf(String s) {
    return parseBoolean(s) ? TRUE : FALSE;
}

也就是Boolean類出來不建立物件,只有兩個常量物件,你來根據需求取就可以了。有效的減少系統因為建立物件帶來的開銷。此外,通過這種方式,我們直接可以使用“==”運算子代替equals運算子。可以極大的提示系統性能(這裡必須要強調一下,自定義的物件必須重寫toString()方法,否則equals返回的是“==”運算的結果

)。下面我們就拿String類來看一下String類中的equals原始碼:

 /**
     *      * Compares this string to the specified object.  The result is {@code
     *      * true} if and only if the argument is not {@code null} and is a {@code
     *      * String} object that represents the same sequence of characters as this
     *      * object.
     *      *
     *      * @param  anObject
     *      *         The object to compare this {@code String} against
     *      *
     *      * @return  {@code true} if the given object represents a {@code String}
     *      *          equivalent to this string, {@code false} otherwise
     *      *
     *      * @see  #compareTo(String)
     *      * @see  #equalsIgnoreCase(String)
     *      
     */

    public boolean equals(Object anObject) {
       if (this == anObject) {
           return true;
       }
       if (anObject instanceof String) {
           String anotherString = (String) anObject;
           int n = value.length;
           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;
   }

 

從上面不難看出,這種方式是通過一個一個字元來比較兩個字串實現的,如果通過“==”來替代這種方式,那必然會大大的提示效能。而我們通過這種靜態工廠的方法構建的物件就可以通過這種方式來比較兩個物件的內容是否一樣。

所以,這裡面有兩個點:

  • 可以減少建立相同內容物件的個數,減少資源開銷
  • 可以通過“==”代替eqauls提示效能

 

附:效能測試程式碼

  public static void main(String[] args) {

        Class c=StringBuffer.class;

        int num=9000000;
        //equals 方式
        long start1 = System.currentTimeMillis();
        for (long i = 0; i < num; i++) {
            boolean b=c.getName().equals(String.class.getName());
        }
        long end1 = System.currentTimeMillis();

        System.out.println("eqauls方式耗時:"+(end1-start1)+"\t");
        System.out.println("eqauls方式運算次數:"+c.getName().length()*num+"\t");

        //==方式
        long start2 = System.currentTimeMillis();

        for (long i = 0; i < num; i++) {
            boolean b=(c==String.class);
        }
        long end2 = System.currentTimeMillis();

        System.out.println("==方式耗時:"+(end2-start2));
        System.out.println("==方式運算次數:"+num+"\t");

        System.out.println("\n\n"+"注:這裡的字串只有:"+c.getName().length()+"個字元");

    }
}

測試結果:

 

附:Boolean 類原始碼:

public class Test {

    /*
 * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.lang;

    /**
     * The Boolean class wraps a value of the primitive type
     * {@code boolean} in an object. An object of type
     * {@code Boolean} contains a single field whose type is
     * {@code boolean}.
     * <p>
     * In addition, this class provides many methods for
     * converting a {@code boolean} to a {@code String} and a
     * {@code String} to a {@code boolean}, as well as other
     * constants and methods useful when dealing with a
     * {@code boolean}.
     *
     * @author  Arthur van Hoff
     * @since   JDK1.0
     */
    public final class Boolean implements java.io.Serializable,
            Comparable<Boolean>
    {
        /**
         * The {@code Boolean} object corresponding to the primitive
         * value {@code true}.
         */
        public static final Boolean TRUE = new Boolean(true);

        /**
         * The {@code Boolean} object corresponding to the primitive
         * value {@code false}.
         */
        public static final Boolean FALSE = new Boolean(false);

        /**
         * The Class object representing the primitive type boolean.
         *
         * @since   JDK1.1
         */
        @SuppressWarnings("unchecked")
        public static final Class<Boolean> TYPE = (Class<Boolean>) Class.getPrimitiveClass("boolean");

        /**
         * The value of the Boolean.
         *
         * @serial
         */
        private final boolean value;

        /** use serialVersionUID from JDK 1.0.2 for interoperability */
        private static final long serialVersionUID = -3665804199014368530L;

        /**
         * Allocates a {@code Boolean} object representing the
         * {@code value} argument.
         *
         * <p><b>Note: It is rarely appropriate to use this constructor.
         * Unless a <i>new</i> instance is required, the static factory
         * {@link #valueOf(boolean)} is generally a better choice. It is
         * likely to yield significantly better space and time performance.</b>
         *
         * @param   value   the value of the {@code Boolean}.
         */
        public Boolean(boolean value) {
            this.value = value;
        }

        /**
         * Allocates a {@code Boolean} object representing the value
         * {@code true} if the string argument is not {@code null}
         * and is equal, ignoring case, to the string {@code "true"}.
         * Otherwise, allocate a {@code Boolean} object representing the
         * value {@code false}. Examples:<p>
         * {@code new Boolean("True")} produces a {@code Boolean} object
         * that represents {@code true}.<br>
         * {@code new Boolean("yes")} produces a {@code Boolean} object
         * that represents {@code false}.
         *
         * @param   s   the string to be converted to a {@code Boolean}.
         */
        public Boolean(String s) {
            this(parseBoolean(s));
        }

        /**
         * Parses the string argument as a boolean.  The {@code boolean}
         * returned represents the value {@code true} if the string argument
         * is not {@code null} and is equal, ignoring case, to the string
         * {@code "true"}. <p>
         * Example: {@code Boolean.parseBoolean("True")} returns {@code true}.<br>
         * Example: {@code Boolean.parseBoolean("yes")} returns {@code false}.
         *
         * @param      s   the {@code String} containing the boolean
         *                 representation to be parsed
         * @return     the boolean represented by the string argument
         * @since 1.5
         */
        public static boolean parseBoolean(String s) {
            return ((s != null) && s.equalsIgnoreCase("true"));
        }

        /**
         * Returns the value of this {@code Boolean} object as a boolean
         * primitive.
         *
         * @return  the primitive {@code boolean} value of this object.
         */
        public boolean booleanValue() {
            return value;
        }

        /**
         * Returns a {@code Boolean} instance representing the specified
         * {@code boolean} value.  If the specified {@code boolean} value
         * is {@code true}, this method returns {@code Boolean.TRUE};
         * if it is {@code false}, this method returns {@code Boolean.FALSE}.
         * If a new {@code Boolean} instance is not required, this method
         * should generally be used in preference to the constructor
         * {@link #Boolean(boolean)}, as this method is likely to yield
         * significantly better space and time performance.
         *
         * @param  b a boolean value.
         * @return a {@code Boolean} instance representing {@code b}.
         * @since  1.4
         */
        public static Boolean valueOf(boolean b) {
            return (b ? TRUE : FALSE);
        }

        /**
         * Returns a {@code Boolean} with a value represented by the
         * specified string.  The {@code Boolean} returned represents a
         * true value if the string argument is not {@code null}
         * and is equal, ignoring case, to the string {@code "true"}.
         *
         * @param   s   a string.
         * @return  the {@code Boolean} value represented by the string.
         */
        public static Boolean valueOf(String s) {
            return parseBoolean(s) ? TRUE : FALSE;
        }

        /**
         * Returns a {@code String} object representing the specified
         * boolean.  If the specified boolean is {@code true}, then
         * the string {@code "true"} will be returned, otherwise the
         * string {@code "false"} will be returned.
         *
         * @param b the boolean to be converted
         * @return the string representation of the specified {@code boolean}
         * @since 1.4
         */
        public static String toString(boolean b) {
            return b ? "true" : "false";
        }

        /**
         * Returns a {@code String} object representing this Boolean's
         * value.  If this object represents the value {@code true},
         * a string equal to {@code "true"} is returned. Otherwise, a
         * string equal to {@code "false"} is returned.
         *
         * @return  a string representation of this object.
         */
        public String toString() {
            return value ? "true" : "false";
        }

        /**
         * Returns a hash code for this {@code Boolean} object.
         *
         * @return  the integer {@code 1231} if this object represents
         * {@code true}; returns the integer {@code 1237} if this
         * object represents {@code false}.
         */
        @Override
        public int hashCode() {
            return Boolean.hashCode(value);
        }

        /**
         * Returns a hash code for a {@code boolean} value; compatible with
         * {@code Boolean.hashCode()}.
         *
         * @param value the value to hash
         * @return a hash code value for a {@code boolean} value.
         * @since 1.8
         */
        public static int hashCode(boolean value) {
            return value ? 1231 : 1237;
        }

        /**
         * Returns {@code true} if and only if the argument is not
         * {@code null} and is a {@code Boolean} object that
         * represents the same {@code boolean} value as this object.
         *
         * @param   obj   the object to compare with.
         * @return  {@code true} if the Boolean objects represent the
         *          same value; {@code false} otherwise.
         */
        public boolean equals(Object obj) {
            if (obj instanceof Boolean) {
                return value == ((Boolean)obj).booleanValue();
            }
            return false;
        }

        /**
         * Returns {@code true} if and only if the system property
         * named by the argument exists and is equal to the string
         * {@code "true"}. (Beginning with version 1.0.2 of the
         * Java<small><sup>TM</sup></small> platform, the test of
         * this string is case insensitive.) A system property is accessible
         * through {@code getProperty}, a method defined by the
         * {@code System} class.
         * <p>
         * If there is no property with the specified name, or if the specified
         * name is empty or null, then {@code false} is returned.
         *
         * @param   name   the system property name.
         * @return  the {@code boolean} value of the system property.
         * @throws  SecurityException for the same reasons as
         *          {@link System#getProperty(String) System.getProperty}
         * @see     java.lang.System#getProperty(java.lang.String)
         * @see     java.lang.System#getProperty(java.lang.String, java.lang.String)
         */
        public static boolean getBoolean(String name) {
            boolean result = false;
            try {
                result = parseBoolean(System.getProperty(name));
            } catch (IllegalArgumentException | NullPointerException e) {
            }
            return result;
        }

        /**
         * Compares this {@code Boolean} instance with another.
         *
         * @param   b the {@code Boolean} instance to be compared
         * @return  zero if this object represents the same boolean value as the
         *          argument; a positive value if this object represents true
         *          and the argument represents false; and a negative value if
         *          this object represents false and the argument represents true
         * @throws  NullPointerException if the argument is {@code null}
         * @see     Comparable
         * @since  1.5
         */
        public int compareTo(Boolean b) {
            return compare(this.value, b.value);
        }

        /**
         * Compares two {@code boolean} values.
         * The value returned is identical to what would be returned by:
         * <pre>
         *    Boolean.valueOf(x).compareTo(Boolean.valueOf(y))
         * </pre>
         *
         * @param  x the first {@code boolean} to compare
         * @param  y the second {@code boolean} to compare
         * @return the value {@code 0} if {@code x == y};
         *         a value less than {@code 0} if {@code !x && y}; and
         *         a value greater than {@code 0} if {@code x && !y}
         * @since 1.7
         */
        public static int compare(boolean x, boolean y) {
            return (x == y) ? 0 : (x ? 1 : -1);
        }

        /**
         * Returns the result of applying the logical AND operator to the
         * specified {@code boolean} operands.
         *
         * @param a the first operand
         * @param b the second operand
         * @return the logical AND of {@code a} and {@code b}
         * @see java.util.function.BinaryOperator
         * @since 1.8
         */
        public static boolean logicalAnd(boolean a, boolean b) {
            return a && b;
        }

        /**
         * Returns the result of applying the logical OR operator to the
         * specified {@code boolean} operands.
         *
         * @param a the first operand
         * @param b the second operand
         * @return the logical OR of {@code a} and {@code b}
         * @see java.util.function.BinaryOperator
         * @since 1.8
         */
        public static boolean logicalOr(boolean a, boolean b) {
            return a || b;
        }

        /**
         * Returns the result of applying the logical XOR operator to the
         * specified {@code boolean} operands.
         *
         * @param a the first operand
         * @param b the second operand
         * @return  the logical XOR of {@code a} and {@code b}
         * @see java.util.function.BinaryOperator
         * @since 1.8
         */
        public static boolean logicalXor(boolean a, boolean b) {
            return a ^ b;
        }
    }