JAVA 枚举、泛型

一、枚举

枚举作用是限定某个类成员变量取值是某些固定值,如生活中交通灯抽象成类、颜色为成员变量,则该成员变量就应该有且只有红、黄、绿三个颜色。如果把一周这个事物抽象成类,Day为成员变量,那么成员也是有且只有周一到周日。无论是交通灯还是一周,用户对他们的实例的颜色和Day成员都不能随便赋值,只能赋予其合理合法的值。枚举就能够满足这个要求。

在JDK1.5以前,普通类通过修饰符的限定可以使其具有这样的功能,1.5以后JDK追加了枚举类。

下面是普通类方式来实现交通灯:

public abstract class Lamp {
	private int time;

	public int getTime() {
		return time;
	}

	private Lamp(int time) { // 私有其构造方法
		this.time = time;
	}

	public abstract Lamp nextLight();// 抽象方法 返回下一个交通灯

	public final static Lamp RED = new Lamp(30) {
		@Override
		public String toString() {
			return "红灯";
		}

		@Override
		public Lamp nextLight() {
			return GREEN;
		}
	};
	public final static Lamp GREEN = new Lamp(45) {
		@Override
		public String toString() {
			return "绿灯";
		}

		@Override
		public Lamp nextLight() {
			return YELLOW;
		}
	};
	public final static Lamp YELLOW = new Lamp(5) {
		@Override
		public String toString() {
			return "黄灯";
		}

		@Override
		public Lamp nextLight() {
			return RED;
		}
	};

}

测试:

public class MTest {
	public static void main(String[] args) {
		Lamp green=Lamp.GREEN;
		System.out.println(green+":"+green.getTime()+" 下一个-->"+green.nextLight());
		Lamp red=Lamp.RED;
		System.out.println(red+":"+red.getTime()+" 下一个-->"+red.nextLight());
		Lamp yellow=Lamp.YELLOW;
		System.out.println(yellow+":"+yellow.getTime()+" 下一个-->"+yellow.nextLight());
	}
}

结果:

绿灯:45 下一个-->黄灯
红灯:30 下一个-->绿灯
黄灯:5 下一个-->红灯


下面是Enum类方式:

public enum Lamp {
	RED(30) {
		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return "红灯";
		}

		@Override
		public Lamp nextLamp() {
			// TODO Auto-generated method stub
			return GREEN;
		}
	},
	GREEN(40) {
		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return "绿灯";
		}

		@Override
		public Lamp nextLamp() {
			// TODO Auto-generated method stub
			return YELLOW;
		}
	},
	YELLOW(5) {
		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return "黄灯";
		}

		@Override
		public Lamp nextLamp() {
			// TODO Auto-generated method stub
			return RED;
		}
	};
	private int time;

	public int getTime() {
		return time;
	}

	public abstract Lamp nextLamp();

	private Lamp(int time) {
		this.time = time;
	}

}

测试结果同样是:

绿灯:45 下一个-->黄灯
红灯:30 下一个-->绿灯
黄灯:5 下一个-->红灯

二、泛型

一个工厂可以生产冰箱和空调,使用一模一样的包装箱子。当空调和冰箱装进箱子后外观一模一样,别人也无法分辨里面装的到底是什么东西,假如客户本来想买空调使用其调节空气功能,结果到家打开盒子通上电发现是冰箱,没有调节空气的功能,客户疯了。但是如果厂家再生产包装箱时,包装箱都贴上冰箱和空调的标签,工人们装箱时只限定空调装进空调包装箱,冰箱装进冰箱箱子。装错了,流水线上的负责监督的领导就批评他扣他工资。这样就保证客户到手的东西一定是想要的,也一定有其对应的功能。

把上边的例子抽象到Java里,容器就是java里的容器类比如集合List,空调或冰箱就是要装进集合内的对象IceBox和Aircon,那么箱子的标签就是泛型,比如给装IceBox和Aircon的箱子打上标签就是List<IceBox>和List<Aircon> ,流水线上负责监督的领导就是Java编译器,他能够保证List<IceBox>和List<Aircon>引用的对象只能装入IceBox和Aircon。这样既能够保证调用者拿到标签上(泛型)上的东西也免去了类型转换这一过程。

如下:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<IceBox> list=new ArrayList<IceBox>();
		IceBox icebox1=new IceBox();
		IceBox icebox2=new IceBox();
		IceBox icebox3=new IceBox();
		IceBox icebox4=new IceBox();
		list.add(icebox1);
		list.add(icebox2);
		list.add(icebox3);
		list.add(icebox4);
	}

除了上面一种跟在容器后面作为“标签”的作用以外,还有另一种用法,一个类的成员变量的类型如果需求有多种,则该成员变量类型不固定,如果没有泛型就只能有多少种需求写多少种“可能”,泛型出现后可以跟在类后面作为不固定成员类的“通配符”

public class MTest {
	public static void main(String[] args) {
		List<String> strs = new ArrayList<String>();
		strs.add("aaa");
		strs.add("bbb");
		strs.add("ccc");
		printCollecrion(strs);
		List<Integer> nums = new ArrayList<Integer>();
		nums.add(1);
		nums.add(2);
		nums.add(3);
		printCollecrion(nums);
	}

	private static void printCollecrion(Collection<?> collection) {
		// TODO Auto-generated method stub
		for (Object iterable_element : collection) {
			System.out.println(iterable_element);
		}
	}
	
	
	/**
	 * @param collection
	 * 自定义泛型T 用以接收任意类型对象 
	 */
	private static <T> void printCollecrion1(Collection<T> collection) {
		// TODO Auto-generated method stub
		for (T t : collection) {
			System.out.println(t);
		}
	}
}

以上?表示代表任何类型,而T是自定义用以接收对象的类型,并且可以用对象。

泛型限定:

设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类

public class MTest {
	public static void main(String[] args) {
		List<Animal> list=new ArrayList<Animal>();
		printName(list);
		//错:The method printName(Collection<? extends Person>) in the type MTest is not applicable for the arguments (List<Animal>)
	}

	// 泛型限制该方法只能接受Person和其子类的集合参数
	public static void printName(Collection<? extends Person> collection) {

	}
}

class Person {

}

class Student extends Person {

}

class Teacher extends Person {

}

class Animal {

}

设置泛型对象的下限使用super,表示参数类型只能是该类型或该类型的父类:

public class MTest {
	public static void main(String[] args) {
		List<Student> list=new ArrayList<Student>();
		printName(list);
		//错:The method printName(Collection<? super Teacher>) in the type MTest is not applicable for the arguments (List<Student>)
	}

	// 泛型限制该方法只能接受Teacher和其父类的集合参数
	public static void printName(Collection<? super Teacher> collection) {

	}
}

class Person {

}

class Student extends Person {

}

class Teacher extends Person {

}

class Animal {

}

此外反省还允许嵌套使用,如用常见的Map取出的操作

public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("name", "zhangshan");
		map.put("age","15" );
		map.put("add", "beijing");
		Set<Map.Entry<String, String>> set=map.entrySet();
		for(Map.Entry<String, String> ob:set){
			System.out.println(ob.getKey());
			System.out.println(ob.getValue());
		}
		
		
	}


自定义泛型


下面是简单模拟(忽略存储结构和重复元素的问题)Map类MyMap 通过两个List存储Key和Value ,通过index建立联系。
class MyMap<K, V> {
	private K k;// 模拟key
	private V v;// 模拟value
	// 用list存储Key和Value
	List<K> klist = new ArrayList<K>();
	List<V> vlist = new ArrayList<V>();
	
	public <K, V> MyMap() {
		// TODO Auto-generated constructor stub
	}
	
	// 模拟put方法
	public void put(K k, V v) {
		klist.add(k);
		vlist.add(v);
	}

	// 模拟get方法 根据传入的key所在klist的index 获取在vlist的value
	public V get(K k) {

		for (int i = 0; i < klist.size(); i++) {
			if (klist.get(i).equals(k))
				return vlist.get(i);
		}
		return null;
	}
}

测试:

public class MyMapTest {
	public static void main(String[] args) {
		MyMap<String, String> map = new MyMap<String, String>();
		map.put("aaa", "你好");
		map.put("bbb", "黑马");
		map.put("ccc", "程序");
		map.put("ddd", "员");
		System.out.println(map.get("ccc"));
	}
}

打印结果:

程序

null



自定义泛型除了可以定义到类上,还可以定义到方法上,比如要写一个方法在任何类型数组,给定两个索引位置就能够交换,如下:

public class MTest {
	public static void main(String[] args) {
		Integer[] arr1 = { 1, 2, 3 };
		String[] arr2 = { "aaa", "bbb", "ccc" };
		swap(arr1, 0, 2);
		swap(arr2, 0, 2);
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toString(arr2));
	}

	public static <T> void swap(T[] arr, int index1, int index2) {
		T temp = arr[index1];
		arr[index1] = arr[index2];
		arr[index2] = temp;
	}
}
结果:

[3, 2, 1]
[ccc, bbb, aaa]


注意:上面用的是integer而不是int,因为泛型限定不能使用基本数据类型,如果使用int编译器不会通过。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值