黑马程序员技术交流社区
标题:
TreeSet放多种对象问题
[打印本页]
作者:
﹏゛心被伱牵
时间:
2012-10-24 08:11
标题:
TreeSet放多种对象问题
昨天写代码发现一个问题,就是使用泛型虽然给我们带来了很大的安全问题,但是用了泛型我们是不是只能放置着一种类型的对象了,如下
TreeMap<Worker, String> map=new TreeMap<Worker, String>();
map.put(new Worker("黄强", 24), "北京");
map.put(new Worker("小小", 21), "上海");
这是我们如果要放入其他对象,我们怎么办了,很纠结?
作者:
张忠豹
时间:
2012-10-24 12:08
本帖最后由 张忠豹 于 2012-10-24 12:12 编辑
张孝祥老师的java基础加强里面有讲到,这是我的代码笔记,希望对你有用……
package staticImport.cn.itcast.day2;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
public class GenericTest {
public static void main(String args[])throws Exception{
ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello heima");
ArrayList<Integer> list2 = new ArrayList<Integer>();
//两个集合都是泛型参数实例化,但是返回的class字节码还是一样的
System.out.println(list1.getClass()==list2.getClass());
/**往list2中添加字符串:list2.add("abc");
由于ArrayList的泛型参数是Integer,如果存放字符串类型,在编译的时候是会报错的
所以要使用泛型来实现。因为编译生成的字节码会去掉泛型的信息,只要跳过编译器,就可以往某
非泛型集合中添加其它类型的数据.*/
list2.getClass().getMethod("add", Object.class).invoke(list2, "abc");
System.out.println(list2.get(0));
/**通配符*/
printCollection(list1);
/**泛型----Map.key<key,value>*/
HashMap<String, Integer> map = new HashMap<String,Integer>();
map.put("zxx", 28);
map.put("bxd", 27);
map.put("yxf", 45);
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
for(Map.Entry<String, Integer> entry:entrySet){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
/**泛型的语法定义和类型的推断*/
// int x = add(3,3);//返回值为int类型
Object x1 = add(3.5,3);//T的取值是取得两个参数类型的交集
Object x2 = add(3.5,"abc");
/**交换数组中两个元素的位置*/
swap(new String[]{"abc","def","hij"},1,2);
//swap(new int[]{1,2,3,4,5},2,3);这条语句会报错,泛型的实际类型,只能是对象类型、引用类型,不能是基本类型
/**练习题*/
Object obj = "abc";
autoConvert(obj);
//2
// fillArray();
copy1(new Vector<String>(),new String[10]);
copy2(new Date[10],new String[10]);//类型推断为Object
// copy1(new Vector<Date>(),new String[10]);//此处报错:已经为Vector的泛型指定了date类型,说明T就是Date,
// 当类型参数被实例化之后,就具有传递性,T一定是Date
/**类上面加泛型*/
GenericDao<ReflectPoint> dao = new GenericDao<ReflectPoint>();
dao.add(new ReflectPoint(3,3));
ReflectPoint rp = dao.findById(1);
/** 通过反射获取泛型的实际类型参数*/
//Vector<Date> v1 = new Vector<Date>();这时通过V1对象是检查不出来Vector中泛型的类型的。只能通过方法
Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type type[] = applyMethod.getGenericParameterTypes();
ParameterizedType pType = (ParameterizedType)type[0];
System.out.println(pType.getRawType());
System.out.println(pType.getActualTypeArguments()[0]);
}
public static <T> void applyVector(Vector<Date> v1){
}
private static <T> T autoConvert(Object obj){
return (T)obj;
}
private static <T> void fillArray(T a[],T obj){
for(int i=0;i<a.length;i++){
a[i] = obj;
}
}
private static <T> void copy1(Collection<T> src,T a[]){
int len = src.size();
// for()
}
private static <T> void copy2(T src[],T dest[]){
}
private static <T>/*声明泛型类型,在后面就可以使用了*/ void swap(T[] array,int i,int j){
T temp ;
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
private static <T> T add(T t1,T t2){
return null;
}
/*
通配符可以作为一个引用型变量来引用一个类型,但是引用别人以后,你不能拿着它去调用一个与
参数有关系的方法,就是与类型有关的方法你不能去调用 ,例如:add(E e);但是你可以调用
size()方法,它与通配符引用的类型没有关系
*/
private static void printCollection(Collection<?> collection) {
for(Object obj:collection){
System.out.println(obj);
}
}
}
class ReflectPoint{
public ReflectPoint(int i, int j) {
this.x = i;
this.y = j;
}
private int x;
public int y;
}
连涉及到的笔记一块送到:
复制代码
作者:
张忠豹
时间:
2012-10-24 12:12
本帖最后由 张忠豹 于 2012-10-24 12:14 编辑
泛型的作用
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass( )方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用add方法即可。
系统,不让我从doc中赋值文字,郁闷!粘到上面是一堆代码……
作者:
范贞亮
时间:
2012-10-24 12:13
你可以使用多重包装了, 先把Object 对象放进ArrayList里面, 再把ArrayList 放进Map 对象里面 或者把Map里面放Map , 这样就解决了
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2