方法设计原则

import java.util.*;
public class MethodDesign {
	
	private Date startday;
	public MethodDesign() { }
	public MethodDesign(Date startday) {
		if(startday == null) 
			throw new IllegalArgumentException("startday can not be null");
		//保护性拷贝
		this.startday = new Date(startday.getTime());
	}
	
	public Date getStartday() {
		//保护性拷贝
		return new Date(this.startday.getTime());
	}
	
	@SuppressWarnings("unused") private void sort(long[] arr, int offset, int length) {
		assert arr != null;
		assert offset >= 0 && offset <= arr.length;
		assert length >= 0 && length <= arr.length - offset;
	}
	//overload重载方法的选择是在编译时决定的
	public String classify(Set<?> s) {
		return "Set";
	}
	public String classify(List<?> lst) {
		return "List";
	}
	public String classify(Collection<?> c) {
		return "Unknown Collection";
	}
	
	public static void main(String[] args) {
		
		MethodDesign md = new MethodDesign();
		Collection<?>[] collections = {
			new HashSet<String>(),
			new ArrayList<Integer>(),
			new HashMap<String, String>().values()
		};
		for (Collection<?> c : collections)
			System.out.println(md.classify(c));
		
		Wine[] wines = {
				new Wine(), new SparklingWine(), new Champagne()
		};
		for (Wine wine : wines)
			System.out.println(wine.name());
		
		List<Integer> list = new ArrayList<Integer>();
		for (int i = -3; i < 3; i++) {
			list.add(i);
		}
		for (int i = 0; i < 3; i++) {
			//删除Integer元素
			list.remove(Integer.valueOf(i));
			//按下标删除
			//list.remove(i);
		}
		System.out.println(list);
	}
}
//override覆盖方法的选择是运行时决定的
class Wine {
	String name() { return "wine"; }
}
class SparklingWine extends Wine {
	@Override String name() { return "sparkling wine"; }
}
class Champagne extends SparklingWine {
	@Override String name() { return "champagne"; }
}

输出为:

Unknown Collection
Unknown Collection
Unknown Collection
wine
sparkling wine
champagne
[-3, -2, -1]

 

 

 * 检查方法参数的有效性:
   绝大多数方法和构造器对传递给他们的参数值都会有些限制。
   应该在文档中清楚地指明这些限制,并且在方法的开头检查参数,以强加这些限制。
   如果传递了无效的参数给方法,那么它很快就会失败,并清晰地抛出适当的异常。
   通常为:IllegalArgumentException、IndexOutOfBoundsException 或者 NullPointerException。


   对于非public的方法,通常应该使用断言(assertion)来检查它们的参数。
   断言是在声称被断言的条件将会为真,断言如果失败将会抛出AssertionError。
   不同于一般的有效性检查,如果它们没有起到作用,本质上也不会有成本开销。
*************************************************************************
 * 必要时进行保护性拷贝:
   为了避免实例的内部信息受到攻击,对于构造器的每个可变参数进行保护性拷贝是必要的。
   保护性拷贝是在检查参数的有效性之前进行的,并且有效性检查是针对拷贝之后的对象,而不是针对

   传递进来的原始对象。


   对于参数类型可以被不信任方子类化的参数,不要使用clone方法进行保护性拷贝。
   public访问方法提供了对可变内部成员的访问,为了防御攻击,需要使它返回可变内部域的保护性拷贝。
*************************************************************************
 * 谨慎设计方法的签名:
   谨慎地选择方法的名称:方法的名称应该始终遵循标准的命名习惯。
   首要目标是选择易于理解的,并且与包中其他名称风格一致的名称。
   其次应该选择与大众认可的名称相一致的名称。


   不要过于追求提供便利的方法:每个方法都应该尽其所能。方法太多会使类难以学习、使用、测试

   和维护。


   避免过长的参数列表:目标是四个参数或者更少。相同类型的长参数序列格外有害。
   有三种方法缩短过长的参数:
   第一种是把方法分解成多个方法,每个方法只需要这些参数的一个子集。
   第二种方法是创建辅助类,用来保存参数的分组。这些辅助类一般为静态成员类。
   第三种方法结合前两种,从对象构建到方法调用都采用Builder模式。

   对于参数类型要优先使用接口而不是类。
   对于boolean参数,要优先使用两个元素的枚举类型。
*************************************************************************
 * 慎用重载:要调用哪个重载方法,是在编译时做出决定的。
   java对于重载(overload)方法的选择是静态的(编译时决定)。
   而对覆盖(override)方法的选择是动态的(运行时决定),选择的依据是被调用方法所在对象的运行时

   类型。
   对于API的用户来说,如果一组给定的参数,根本不知道哪个重载方法会被调用;那么使用这样的API

   可能导致错误。

   安全而保守的策略:永远不要导出两个具有相同参数数目的重载方法。如果方法使用可变参数

  (varargs),保守的策略是根本不要重载它。

   java1.5引入泛型和自动装箱后,破坏List的重载方法remove(int)和remove(E)。要删除Integer类型的数据,

   参数必须为remove(Integer.valueOf(i))。remove(int)会按下标删除。
*************************************************************************
 * 慎用可变参数(varargs):

   java1.5增加可变参数的方法。可变参数方法接受零个或多个指定类型的参数。
   可变参数的机制通过预先创建一个数组,数组的大小为在调用位置所传递的参数数量,然后将参数值传到

   给数组中,最后将数组传给方法。
   可变参数方法的每次调用都会导致一次数组分配和初始化。
*************************************************************************
 * 返回零长度的数组或者集合而不是null:
   对于不返回任何元素的调用,每次都返回同一个零长度数组是有可能的,因为零长度数组是不可变的,

   而不可变对象有可能被自由地共享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值