zoukankan      html  css  js  c++  java
  • JAVA泛型(代码级解释)

    /**
     * Program  : LearnPattern.java
     * Author   : tanx
     * Create   : 2013-5-10 下午4:22:46
     *
     */
    package pattern;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 
     * @author tanx
     * @version 1.0.0
     * @2013-5-10 下午4:22:46
     */
    public class LearnPattern<K, V> {
    	// 推荐的命名约定是使用大写的单个字母名称作为类型参数。这与 C++ 约定有所不同(参阅 附录 A:与 C++
    	// 模板的比较),并反映了大多数泛型类将具有少量类型参数的假定。对于常见的泛型模式,推荐的名称是:
    	//
    	// K —— 键,比如映射的键。
    	// V —— 值,比如 List 和 Set 的内容,或者 Map 中的值。
    	// E —— 异常类。
    	// T —— 泛型
    
    	// Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,
    	// tanx:显示的约定,而不是存在于程序员的头脑中,注释里,编译器帮我们杜绝错误,而不是运行BUG
    
    	// 消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。
    	// 类型检查从执行时挪到了编译时,这会提高可靠性并加快开发速度
    
    	public void put(K key, V value) {//使用类定义的   相同的类型
    
    	}
    	public V get(K key) {//使用类定义的   相同的类型
    		return null;
    	}
    
    	//限定传入参数类型与返回类型相同,没在类定义泛型就要在方法名前加<T> ,T可以是其他字母
    	public <T> T addTest(T value) { 
    		return null;
    	}
    
    	public void testCase1() {
    		LearnPattern<Integer, String> bb = new LearnPattern<Integer, String>();
    		bb.put(1, "test"); // 一定传对参数
    		String test = bb.get(1); // 无需类型转换
    	}
    
    	public void testCase2() {
    		List<Integer> intList = new ArrayList<Integer>();
    		intList.add(2);
    		// List<Number> numberList = intList; // 无法转换 ,泛型不是协变的
    		// numberList.add(2.0); // 如果能转换,那么这个2.0就能加,但实际intList不能加2.0
    		List<?> numberList = intList; // 可以转成 ? 时常用于升级代码,消除转换警告,但请注意下面
    		// numberList.add(2);// ? 无法添加
    		System.out.println(numberList.get(0));// ? 能做查询
    		numberList.clear();// ? 能做删除
    	}
    
    	// 多个参数约束
    	public <T> T ifThenElse(boolean b, T first, T second) {
    		return b ? first : second;
    	}
    
    	public void testCase3() {
    		String s = ifThenElse(false, "a", "b");
    		Integer i = ifThenElse(false, new Integer(1), new Integer(2));
    		// 非法,不仅仅是口头约束,注释,或者直接运行时出错
    		// String s = ifThenElse(b, "pi", new Float(3.14));
    	}
    
    	// 限制类型 //明白无误告诉别人,这个类里面属性test只能为Number子类
    	public class testCase4<T extends Number> {
    		private T test;
    	}
    
    	interface Collection<V> {
    		boolean addAll(Collection<? extends V> c); // 不改变原来的语义,可添加集合及子类集合
    		boolean removeAll(Collection<?> c); // 删除混合的集合类
    	}
    
    	// class Enum<E extends Enum<E>>
    	// 类型参数 E 用于 Enum 的各种方法中,比如 compareTo() 或 getDeclaringClass()。
    	// 为了这些方法的类型安全,Enum 类必须在枚举的类上泛型化。
    	//
    	// Enum<E> 这个是它本身 , E extends Enum<E> 表示是它本身的子类型
    	// 因为枚举类实现了implements Comparable<E>  ,有如下方法:
    	// public final int compareTo(E o) {
    	// 		Enum other = (Enum)o;
    	// 		Enum self = this;
    	// 		if (self.getClass() != other.getClass() && // optimization
    	// 		self.getDeclaringClass() != other.getDeclaringClass())
    	// 		throw new ClassCastException();
    	// 		return self.ordinal - other.ordinal;
    	// }
    	
    	// public final Class<E> getDeclaringClass() {
    	// 		Class clazz = getClass();
    	// 		Class zuper = clazz.getSuperclass();
    	// 		return (zuper == Enum.class) ? clazz : zuper;
    	// }	
    	//API解释
    	//public final Class<E> getDeclaringClass()
    	//返回与此枚举常量的枚举类型相对应的 Class 对象。
    	//    当且仅当 e1.getDeclaringClass() == e2.getDeclaringClass() 时,
    	//    两个枚举常量 e1 和 e2 的枚举类型才相同。(由该方法返回的值不同于由 Object.getClass() 
    	//    方法返回的值,Object.getClass() 方法用于带有特定常量的类主体的枚举常量。)
    	//返回:
    	//与此枚举常量的枚举类型相对应的 Class 对象
    
    	// public native Class<? super T> getSuperclass(); //Class的本地方法,返回该类的父类型
    	public Class<? super Integer> testCase5() { // 返回Integer的父类类型
    		return null;
    	}
    	
    	//特殊效果演示
    	abstract class Foo <T extends Foo<T>>{
    		public abstract T subclassAwareDeepCopy();		
    	}
    
    	class Bar extends Foo<Bar> {
    	    public Bar subclassAwareDeepCopy() {
    	        Bar b = new Bar();
    	        // ...
    	        return b;
    	    }	    	   
    	}
    	
    	public class testCase5<T extends Number> {
    		Bar b = new Bar();
        	Foo<Bar> f = b; // 子类和父类相互赋值
        	Bar bb2 = b.subclassAwareDeepCopy();
        	Bar bb3 = f.subclassAwareDeepCopy(); // 父类直接返回子类的实例,而且不用Cast
        	
        	Bar1 b1 = new Bar1();
    		Foo1<Foo1> f1 = b1; // 子类和父类相互赋值
        	Bar1 b12 = b1.subclassAwareDeepCopy();
        	Bar1 b13 = (Bar1)f1.subclassAwareDeepCopy(); // 父类返回子类的实例,需要Cast
        	
        	Bar2 b2 = new Bar2();
        	Foo2 f2 = b2; // 子类和父类相互赋值
        	Bar2 b22 = b2.subclassAwareDeepCopy();
        	Bar2 b23 = (Bar2)f2.subclassAwareDeepCopy(); // 父类返回子类的实例,需要Cast
        	
    	}
    
    	//对比1  -----------------------------------------------------------------------
    	abstract class Foo1<T> {
    		public abstract T subclassAwareDeepCopy();		
    	}
    
    	//这里因为没有约束,所以我们可以随意填,你可能认为这填Bar1就不用转型了,
    	//但那只存在于我们脑海中,如果是给别人提供api接口,显然要用 <T extends Foo<T>>
    	class Bar1 extends Foo1<Foo1> {
    	    public Bar1 subclassAwareDeepCopy() {
    	        Bar1 b = new Bar1();
    	        // ...
    	        return b;
    	    }	    	   
    	}
    	
    	//对比2  -----------------------------------------------------------------------
    	abstract class Foo2 {
    		public abstract Foo2 subclassAwareDeepCopy();		
    	}
    
    	class Bar2 extends Foo2 {
    	    public Bar2 subclassAwareDeepCopy() {
    	        Bar2 b = new Bar2();
    	        // ...
    	        return b;
    	    }	    	   
    	}
    	
    
    }
    


  • 相关阅读:
    java主函数的含义
    this关键字简单应用
    如何将util.Date转化为sql.Date
    利用JavaScript来实现省份—市县的二级联动
    通过Ajax异步提交的方法实现从数据库获取省份和城市信息实现二级联动(xml方法)
    折半查找(java)(边学习边更新)
    第五章 上
    Jframe关闭窗口时的事件
    C#退出程序自动重新启动
    Extjs4.0 开发笔记与Easyui的整合
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3071885.html
Copyright © 2011-2022 走看看