类和接口
笔记:
class and interface:
1、使得类和成员的可访问性最小化
设计良好的模块就会隐藏所有的实现细节,把它的API与它的实现清晰隔离开来,然后模块只通过它们的API进行通信,一个木块不需要知道其他木块的内部工作情况,这个概念被称为封装。
封装可以有效降低系统模块之间的耦合,使得各个模块可以独立地开发、测试等,加快开发速度,减轻维护负担,也提高了模块的重用性。
java提供了许多机制来协助封装:访问控制机制。包、访问修饰符。
尽可能使每个类或者成员不被外界访问
实例域决不能是公有的
2、在公有类中使用访问方法而非公有域
3、使可变性最小化
使类成为不可变,需要遵循下面五条规则:
1、不要提供任何会修改对象状态的方法
2、保证类不会被扩展
3、使所有的域都是final的
4、使所有的域都是私有的
4、确保对于任何可变组件的互斥访问
不可变对象本质上是线程安全的,它们不要求同步
不可变类真正唯一的缺点是,对于每个不同的值都需要一个单独的对象。
为了确保类的不可变性,类绝对不允许自身被子类化。除了使类变成为final的这种方法之外,还有一种更加灵活的方法可以做到这一点。私有构造+静态工厂。
坚决不要为每个get方法编写一个响应的set方法。除非有很好的理由要让类成为可变的类,否则就应该是不可变的。除非有令人信服的理由要使域变成是非final的,否则要使每个域都是final的。
3、符合优先于继承
继承是实现代码重用的有力手段,但它并非永远是完成这项工作的最佳工具。
与方法调用不同的是,继承打破了封装性。
继承容易因为父类的改变受到影响,复合(不扩展现有类,在新类中增加一个私有域,引用现有类的一个实例)可以避免一些。心累中的每个实例方法都可以调用被包含的现有类实例中对应的方法,并返回它的结果。这被称为转发,新类中的方法被称为转发方法
包装类几乎没有什么缺点。需要注意的一点是,包装类不适合用在回调框架中。
只有当子类真正是超类的子类型时,才适合用继承。换句话来说,对于两个类A和B,只有当两者之间确实存在“is-a”关系的时候,类B才应该扩展类A
4、要么为继承而设计,并提供文档说明,要么就禁止继承
为了允许继承类还必须遵守一些其他约束。
构造器决不能调用可被覆盖的方法,无论是clone还是readObject都不可以调用可覆盖的方法,不管是以直接还是间接的,因为clone和readObject在行为上非常类似于构造器。
对于那些并非为了安全地进行子类化而设计和编写文档的类,要禁止子类化
5、接口优于抽象类
接口与抽象类的区别:抽象类云溪包含某些方法的实现,而接口不允许;为了实现由抽象类定义的类型,类必须成为抽象类的子类
现有的类可以很容易被更新,以实现新的接口
接口是定义mixin的理想选择
接口允许我们构造非层次结构的类型框架
抽象类定义多个实现的类型与使用接口相比有一个明显的优势:抽象类的演变比接口的演变要容易得多
6、接口只用于定义类型
常量接口是不良用法
7、类层次优先于标签类
标签类过于冗长,容易出错,并且效率低下。
子类型化。
将标签类转变成为类层次,首先为标签类中每个方法都定义一个包含抽象方法的抽象类,这个方法的行为都依赖标签值。如果还有其他的方法其行为不依赖于标签的值,就把这样的方法放在这个类中。同样的,如果所有的方法都用到了某些数据域,就应该把它们放在这个类中。
接下来,为每种原始标签类都定义根类的具体子类,同时在每个子类中还包括针对根类中每个抽象方法的相对应实现。
8、用函数对象表示策略
策略模式
9、优先考虑静态成员类
嵌套类是指被定义在另一个类内部的类,嵌套类存在的目的应该是为它的外围类提供服务。如果嵌套类将来可能用于其他的某个环境中,它就应该是顶层类。
静态成员类是最简单的一种嵌套类。最好把它看做是普通的类,只是碰巧被声明在一个类的内部而已。常用用法是作为辅助类
非静态成员类的每个实例都隐含着与外围类的一个外围实例相关联。一般很少使用enclosingInstance.new MemberClass(args)来手工建立这种联系,常用用法是定义一个适配器,允许外部类的实例被看做是另一个不相关的实例。例如iterator。
如果声明成员类不要求访问外围实例,就要始终把static修饰符放在它的声明中,使它成为静态成员类。
匿名类一般用作动态创建函数对象
有关代码:
package chapter3; /** * @author zhen * @Date 2018/9/29 15:48 */ public class Circle extends IFigure { double radius; Circle(double radius) { this.radius = radius; } double area() { return Math.PI * (radius * radius); } }
package chapter3; /** * @author zhen * @Date 2018/9/30 15:02 */ public interface Comparator<T> { public int compare(T t1, T t2); }
package chapter3; /** * @author zhen * @Date 2018/9/29 11:40 */ public class Complex { private final double re; private final double im; public Complex(double re, double im) { this.re = re; this.im = im; } public double realPart() { return re; } public double imaginaryPart () { return im; } public Complex add(Complex c) { return new Complex(re + c.re, im + c.im); } public Complex multiply(Complex c) { return new Complex(re * c.re - im * c.im, re * c.im + im * c.re); } public Complex divide(Complex c) { double tmp = c.re * c.re + c.im * c.im; return new Complex((re * c.re + im * c.im)/ tmp, (im * c.re - re * im) / tmp); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Complex)){ return false; } Complex c = (Complex) o; return Double.compare(re, c.re) == 0 && Double.compare(im, c.im) == 0; } @Override public int hashCode() { int result = 17 + hashDouble(re); result = 31 * result + hashDouble(im); return result; } private int hashDouble(double val) { long longBits = Double.doubleToLongBits(re); return (int)(longBits ^ (longBits >>> 32)); } }
package chapter3; /** * @author zhen * @Date 2018/9/29 15:24 */ public class Figure { enum Shape { RECTANGLE, CIRCLE }; // Tag field - the shape of this figure final Shape shape; // these fields are used only if shape is RECTANGLE double length; double width; // this field is used only if shape is CIRCLE double radius; Figure(double radius) { shape = Shape.CIRCLE; this.radius = radius; } Figure(double length, double width) { shape = Shape.RECTANGLE; this.length = length; this.width = width; } double area() { switch (shape) { case CIRCLE: return Math.PI *(radius * radius); case RECTANGLE: return length * width; default: throw new AssertionError(); } } }
package chapter3; import java.util.Collection; import java.util.Iterator; import java.util.Set; /** * @author zhen * @Date 2018/9/29 14:17 */ public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public int size() { return s.size(); } public boolean isEmpty() { return s.isEmpty(); } public boolean contains(Object o) { return s.contains(o); } public Iterator<E> iterator() { return s.iterator(); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } public boolean add(E e) { return s.add(e); } public boolean remove(Object o) { return s.remove(o); } public boolean containsAll(Collection<?> c) { return s.containsAll(c); } public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } public boolean retainAll(Collection<?> c) { return s.retainAll(c); } public boolean removeAll(Collection<?> c) { return s.removeAll(c); } public void clear() { s.clear(); } @Override public boolean equals(Object o) { return s.equals(o); } @Override public int hashCode() { return s.hashCode(); } @Override public String toString() { return s.toString(); } }
package chapter3; import java.io.Serializable; /** * @author zhen * @Date 2018/9/30 15:08 */ public class Host { private static class StrLenCmp implements Comparator<String>, Serializable { public int compare(String t1, String t2) { return t1.length() - t2.length(); } } }
package chapter3; /** * @author zhen * @Date 2018/9/29 15:42 */ public abstract class IFigure { abstract double area() ; }
package chapter3; import java.util.Collection; import java.util.HashSet; /** * @author zhen * @Date 2018/9/29 13:57 */ public class InstrumentedHashSet<E> extends HashSet<E> { private int addCount = 0; public InstrumentedHashSet() { } public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap, loadFactor); } @Override public boolean add(E e) { addCount ++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); //这里出现问题,因为addAll父类中是调用add底层实现的,所以count数量会不准 //继承容易出现问题的额原因是因为父类的方法是不确定的实现 } public int getAddCount() { return addCount; } }
package chapter3; import java.util.Collection; import java.util.Set; /** * @author zhen * @Date 2018/9/29 14:16 */ public class InstrumentedSet<E> extends ForwardingSet<E> { private int addCount = 0; public InstrumentedSet(Set<E> s) { super(s); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } }
package chapter3; import java.util.AbstractList; import java.util.List; import java.util.Map; /** * @author zhen * @Date 2018/9/29 14:53 */ public class NoName { static List<Integer> intArrayAsList(final int[] a) { if (a == null) { throw new NullPointerException(); } return new AbstractList<Integer>() { @Override public Integer get(int i) { return a[i]; } @Override public int size() { return a.length; } @Override public Integer set(int i, Integer val) { int oldVal = a[i]; a[i] = val; return oldVal; } }; } public static abstract class AbstractMapEntry<K, V> implements Map.Entry<K, V> { public abstract K getKey(); public abstract V getValue(); public V setValue(V value) { throw new UnsupportedOperationException(); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Map.Entry)) { return false; } Map.Entry<?, ?> arg = (Map.Entry) o; return equals(getKey(), arg.getKey()) && equals(getValue(), arg.getValue()); } private static boolean equals(Object o1, Object o2) { return o1 == null ? o2 == null : o1.equals(o2); } @Override public int hashCode() { return hashCode(getKey()) ^ hashCode(getValue()); } private static int hashCode(Object obj) { return obj == null ? 0 : obj.hashCode(); } } }
package chapter3; /** * @author zhen * @Date 2018/9/29 15:47 */ public class Rectangle extends IFigure { double length; double width; public Rectangle(double length, double width) { this.length = length; this.width = width; } double area() { return length * width; } }
package chapter3; /** * @author zhen * @Date 2018/9/29 15:58 */ public class StringLengthComparator implements Comparator<String> { private StringLengthComparator() {} public static final StringLengthComparator INSTANCE = new StringLengthComparator(); public int compare(String s1, String s2) { return s1.length() - s2.length(); } }

浙公网安备 33010602011771号