<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Scott@JAVA

    Java, 一杯濃濃的咖啡伴你到深夜

    《Effective Java》Chapter 4

    Chapter 4: Classes and Interfaces

    Item 12: Minimize the accessibility of classes and members

    The rule of thumb is that you should make each class or member as inaccessible as possible.

    For members (fields, methods, nested classes, and nested interfaces) there are four possible access levels, listed here in order of increasing accessibility:
       ? private— The member is accessible only inside the top-level class where it is declared.
       ? package-private— The member is accessible from any class in the package where it is declared. Technically known as default access, this is the access level you get if no access modifier is specified.
       ? protected— The member is accessible from subclasses of the class where it is declared (subject to a few restrictions [JLS, 6.6.2]) and from any class in the package where it is declared.
       ? public— The member is accessible from anywhere.

    It is nearly always wrong to have public static final array field.
    //Potential security hole!
    public static final Type[] VALUES =  };

    The public array should be replaced by a private array and a public immutable list:

    private static final Type[] PRIVATE_VALUES =  };
    public static final List VALUES =
        Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

    Alternatively, if you require compile-time type safety and are willing to tolerate a performance loss, you can replace the public array field with a public method that returns a copy of a private array:

    private static final Type[] PRIVATE_VALUES =  };
    public static final Type[] values() {
        
    return (Type[]) PRIVATE_VALUES.clone();
    }


    Item 13: Favor immutability
    The Java platform libraries contain many immutable classes, including String, the primitive wrapper classes, and BigInteger and BigDecimal.

    a) Don't provide any methods that modify the object (known as mutators).
    b) Ensure that no methods may be overridden.
    c) Make all fields final.
    d) Make all fields private.
    e) Ensure exclusive access to any mutable components.
    Immutable objects are inherently thread-safe; they require no synchronization.
    The only real disadvantage of immutable classes is that they require a separate object for each distinct value.
    This approach works fine if you can accurately predict which complex multistage operations clients will want to perform on your immutable class. If not, then your best bet is to provide a public mutable companion class. The main example of this approach in the Java platform libraries is the String class, whose mutable companion is StringBuffer.

    Item 14: Favor composition over inheritance
    Unlike method invocation, inheritance breaks encapsulation.

    // Broken - Inappropriate use of inheritance!
    public class InstrumentedHashSet extends HashSet {
        
    // The number of attempted element insertions
        private int addCount = 0;

        
    public InstrumentedHashSet() {
        }


        
    public InstrumentedHashSet(Collection c) {
            
    super(c);
        }


        
    public InstrumentedHashSet(int initCap, float loadFactor) {
            
    super(initCap, loadFactor);
        }


        
    public boolean add(Object o) {
            addCount
    ++;
            
    return super.add(o);
        }


        
    public boolean addAll(Collection c) {
            addCount 
    += c.size();
            
    return super.addAll(c);
        }


        
    public int getAddCount() {
            
    return addCount;
        }

    }

    This class looks reasonable, but it doesn't work. Suppose we create an instance and add three elements using the addAll method:

    InstrumentedHashSet s = new InstrumentedHashSet();
    s.addAll(Arrays.asList(
    new String[] {"Snap","Crackle","Pop"}));

    Internally, HashSet's addAll method is implemented on top of its add method, although HashSet, quite reasonably, does not document this implementation detail.

    Here's a replacement for InstrumentedHashSet that uses the composition/forwarding approach:

    // Wrapper class - uses composition in place of inheritance
    public class InstrumentedSet implements Set {
        
    private final Set s;

        
    private int addCount = 0;

        
    public InstrumentedSet(Set s) {
            
    this.s = s;
        }


        
    public boolean add(Object o) {
            addCount
    ++;
            
    return s.add(o);
        }


        
    public boolean addAll(Collection c) {
            addCount 
    += c.size();
            
    return s.addAll(c);
        }


        
    public int getAddCount() {
            
    return addCount;
        }


        
    // Forwarding methods
        public void clear() {
            s.clear();
        }


        
    public boolean contains(Object o) {
            
    return s.contains(o);
        }


        
    public boolean isEmpty() {
            
    return s.isEmpty();
        }


        
    public int size() {
            
    return s.size();
        }


        
    public Iterator iterator() {
            
    return s.iterator();
        }


        
    public boolean remove(Object o) {
            
    return s.remove(o);
        }


        
    public boolean containsAll(Collection c) {
            
    return s.containsAll(c);
        }


        
    public boolean removeAll(Collection c) {
            
    return s.removeAll(c);
        }


        
    public boolean retainAll(Collection c) {
            
    return s.retainAll(c);
        }


        
    public Object[] toArray() {
            
    return s.toArray();
        }


        
    public Object[] toArray(Object[] a) {
            
    return s.toArray(a);
        }


        
    public boolean equals(Object o) {
            
    return s.equals(o);
        }


        
    public int hashCode() {
            
    return s.hashCode();
        }


        
    public String toString() {
            
    return s.toString();
        }

    }

    Inheritance is appropriate only in circumstances where the subclass really is a subtype of the superclass. In other words, a class B should extend a class only A if an “is-a” relationship exists between the two classes.

    Item 15: Design and document for inheritance or else prohibit it
    The class must document precisely the effects of overriding any method.
    Constructors must not invoke overridable methods, directly or indirectly.

    public class Super {
        
    // Broken - constructor invokes overridable method
        public Super() {
            m();
        }


        
    public void m() {
        }

    }

    Here's a subclass that overrides m, which is erroneously invoked by Super's sole constructor:

    final class Sub extends Super {
        
    private final Date date; // Blank final, set by constructor

        Sub() 
    {
            date 
    = new Date();
        }


        
    // Overrides Super.m, invoked by the constructor Super()
        public void m() {
            System.out.println(date);
        }


        
    public static void main(String[] args) {
            Sub s 
    = new Sub();
            s.m();
        }

    }

    It prints out null the first time because the method m is invoked by the constructor Super() before the constructor Sub() has
    a chance to initialize the date field.

    If you do decide to implement Cloneable or Serializable in a class designed for inheritance, you should be aware that because the clone and readObject methods behave a lot like constructors, a similar restriction applies: Neither clone nor readObject may invoke an overridable method, directly or indirectly.

    Item 16: Prefer interfaces to abstract classes
    Existing classes can be easily retrofitted to implement a new interface.
    Interfaces are ideal for defining mixins. (eg. Comparable)
    Interfaces allow the construction of nonhierarchical type frameworks.
    Interfaces enable safe, powerful functionality enhancements via the wrapper class idiom.

    Using abstract classes to define types that permit multiple implementations has one great advantage over using interfaces: It is far easier to evolve an abstract class than it is to evolve an interface.

    Item 17: Use interfaces only to define types
    When a class implements an interface, the interface serves as a type that can be used to refer to instances of the class.
    The constant interface pattern is a poor use of interface, use constant utility class instead. (public static final fileds)

    Item 18: Favor static member classes over nonstatic
    There are four kinds of nested classes: static member classes, nonstatic member classes, anonymous classes, and local classes. All but the first kind are known as inner classes.

    One common use of a nonstatic member class is to define an Adapter that allows an instance of the outer class to be viewed as an instance of some unrelated class. It is possible, although rare, to establish the association manually using the expression enclosingInstance.new MemberClass(args).

    // Typical use of a nonstatic member class
    public class MySet extends AbstractSet {
         
    // Bulk of the class omitted

        
    public Iterator iterator() {
            
    return new MyIterator();
        }

        
        
    private class MyIterator implements Iterator {
            
        }

    }

    If you declare a member class that does not require access to an enclosing instance, remember to put the static modifier in the declaration. If you omit the static modifier, each instance will contain an extraneous reference to the enclosing object. Maintaining this reference costs time and space with no corresponding benefits.

    One common use of a static member class is as a public auxiliary class, useful only in conjunction with its outer class.

    // Typical use of a public static member class
    public class Calculator {
        
    public static abstract class Operation {
            
    private final String name;

            Operation(String name) 
    {
                
    this.name = name;
            }


            
    public String toString() {
                
    return this.name;
            }


            
    // Perform arithmetic op represented by this constant
            abstract double eval(double x, double y);

            
    // Doubly nested anonymous classes
            public static final Operation PLUS = new Operation("+"{
                
    double eval(double x, double y) {
                    
    return x + y;
                }

            }
    ;

            
    public static final Operation MINUS = new Operation("-"{
                
    double eval(double x, double y) {
                    
    return x - y;
                }

            }
    ;

            
    public static final Operation TIMES = new Operation("*"{
                
    double eval(double x, double y) {
                    
    return x * y;
                }

            }
    ;

            
    public static final Operation DIVIDE = new Operation("/"{
                
    double eval(double x, double y) {
                    
    return x / y;
                }

            }
    ;
        }


        
    // Return the results of the specified calculation
        public double calculate(double x, Operation op, double y) {
            
    return op.eval(x, y);
        }

    }


    One common use of an anonymous class is to create a function object, such as a Comparator instance. Another common use of an anonymous class is to create a process object, such as a Thread, Runnable, or TimerTask instance.

    // Typical use of an anonymous class
    Arrays.sort(args, new Comparator() {
        
    public int compare(Object o1, Object o2) {
            
    return ((String)o1).length() - ((String)o2).length();
        }

    }
    );


    Local classes are probably the least frequently used of the four kinds of nested classes. A local class may be declared anywhere that a local variable may be declared and obeys the same scoping rules.

    posted on 2005-12-18 00:24 Scott@JAVA 閱讀(521) 評論(0)  編輯  收藏 所屬分類: Effective Java

    主站蜘蛛池模板: 亚洲精品无码久久不卡| 国产男女猛烈无遮挡免费视频| 亚洲午夜久久久影院| 男人免费视频一区二区在线观看| 扒开双腿猛进入爽爽免费视频 | 免费无码H肉动漫在线观看麻豆| 亚洲中文字幕久久精品无码APP| 一边摸一边桶一边脱免费视频| 男人的天堂亚洲一区二区三区| 亚洲欧美综合精品成人导航| 在线观看免费a∨网站| 最新亚洲人成网站在线观看| 免费一级大黄特色大片| 人人公开免费超级碰碰碰视频| 久久亚洲精品无码观看不卡| 国产在线观a免费观看| 337p日本欧洲亚洲大胆色噜噜 | 亚洲成a人片在线观| 好爽又高潮了毛片免费下载| 国产精品亚洲综合天堂夜夜| 亚洲人成网站在线观看青青| 在线看片免费人成视频福利| 亚洲高清免费在线观看| 最近2019中文字幕mv免费看| 极品美女一级毛片免费| 国产成A人亚洲精V品无码性色| 久草视频免费在线观看| jzzijzzij在线观看亚洲熟妇| 伊人久久综在合线亚洲91| 最近中文字幕完整版免费高清| 欧洲 亚洲 国产图片综合| 亚洲 国产 图片| 9277手机在线视频观看免费| 亚洲欧美乱色情图片| 亚洲精品乱码久久久久久自慰| 91av视频免费在线观看| 亚洲av无码片vr一区二区三区| 亚洲妇熟XXXX妇色黄| 在线免费视频一区二区| 国产综合免费精品久久久| 亚洲AV无码成人专区|