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;
        }
    }

猜你喜欢

转载自blog.csdn.net/hfut_why/article/details/82725362
今日推荐