javaseday18(泛型 上下限 T 和?)

来源:互联网 发布:js判断鼠标事件 编辑:程序博客网 时间:2024/06/05 07:17

/*
 * 集合的一些技巧
 * 
 * 需要唯一吗?
 * 需要 set
 * 需要指定顺序
 * 需要 TreeSet
 * 不需要 HashSet
 * 但是想要一个和存储一致的顺序(有序) LinkedHashSet
 * 不需要 List
 * 需要频繁增删
 * 需要 LinkedList
 * 不需要 ArrayList
 * 
 * 如何记录每一个容器的结构和所属体系
 * 
 * 看名字 
 * 
 * List (有角标有序)
 * ArrayList
 * LinkedList
 * Set (唯一)
 * HashSet
 * TreeSet
 * 后缀名就是该集合所属的体系
 * 前缀名就是该集合的数据结构
 * 看到array 就要想到数组 就要想到查询快 有角标
 * 看到link 就要想到链表 就要想到增删快 就要想到 add  get remove+first last方法
 * 看到hash就要想到哈希表 就要想到唯一性 就要想到元素需要覆盖hashCode()方法和equals方法
 * 看到Tree 就要想到二叉树 就要想到排序 就要想到两个接口Comparable Comparator
 * 
 * 而且这些常用的集合容器都是不同步的
 * 
 */


jdk1.5以后出现的泛型  新技术的出现是为了解决问题

/* 自动装箱拆箱是简化
 * 泛型
 * jdk 1.5 或5.0 出现的新特性 是为了提高安全性 安全机制 编译时期的技术 为编译器服务
 * 好处
 * 1、将运行时期的问题ClassCastException 转到了编译时期 程序员有机会解决 前期控制类型 很安全
 * 2、避免了强制转换的麻烦
 * <> 什么时候用?
 * 但操作的引用数据类型不确定的时候就使用<> 将要操作的引用数据类型出入即可
 * 其实<>就是一个接受具体引用数据类型的参数范围
 * void show(int x) 参数范围
 * class ArrayList<E> 接受的引用数据类型 比如类名一般开头都大写 比较明确  E 是Elements
 * 在程序中 只要用到了带有<>的类或者接口 就要明确传入的具体数据类型
 * Tool<String,Demo,Person,Integer> t =new Tool<String,Demo,Person,Integer>();
 * 看到尖括号就传类型
 * 泛型技术是给编译器使用的技术 用于编译时期 确保了类型的安全
 * 运行时 会将泛型去掉 生成的class 文件中是不带泛型的 这个称为泛型的擦除
 * 启动的时候启动类加载器
 * 以前的类加载器没见过泛型 为了兼容运行的类加载器 所以擦除
 * 编译器只做检查
 *
 * 泛型的补偿 在运行时通过获取元素的类型进行转换动作 不用使用者再强制转换了
 */
public class Test01 {//中括号被数组用了 大括号定义范围 小括号被方法用了 所以集合用尖括号
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();//技术提升 现在类型安全了


al.add("abc"); //public boolean add(Object obj)自动提升了对象
al.add("bb");
//al.add(4); //al.add(new Integer(4)); 现在限定类型 直接在编译时 出错


Iterator<String> it = al.iterator(); //明确了迭代器的类型就不用在下面强转了
while(it.hasNext()){//编译没事 运行异常 以前都限制类型 现在通过泛型解决
String str =  it.next();//还有一个Integer 不能转化为String java.lang.ClassCastException
System.out.println(str);//因为擦除 然后 避免强转的问题 有个补偿的操作
}
Class clazz = "aa".getClass();//补偿操作 获取类型
System.out.println(clazz);
}
}


public class Person implements Comparable<Person> {//默认是T  type

public int compareTo(Person p) {
// Person p = (Person) o; //Comparable接口加泛型后不需要再强转
int temp = this.age - p.age;
return temp==0?this.name.compareTo(p.name):temp;
}

/**
 * 泛型在集合框架中用的最多 因为集合不能明确装了什么
 * 用泛型来指定类型 让你存指定的
 * 不能放基本数据类型  比如int  不过可以用Integer
 * @author Administrator
 *
 */
public class Test02 {
public static void main(String[] args) {
TreeSet<Person> ts = new TreeSet<Person>(new ComparatorTest01());
ts.add(new Person("lisi",4));
ts.add(new Person("lisi3",34));
ts.add(new Person("lisi2",41));
ts.add(new Person("lisi1",24));


Iterator<Person> it = ts.iterator();//不传参数可以 但是会有黄色感叹号
while(it.hasNext()){
Person p = it.next();//TreeSet 有比较 传入类型要实现Comparable 接口
System.out.println(p.getName()+"..."+p.getAge());
}
  }
}

public class ComparatorTest01 implements Comparator<Person> {


@Override
public int compare(Person o1, Person o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp==0?o1.getAge()-o2.getAge():temp;
}

/*public class Tool {
private Object object;


public Object getObject() {
return object;
}


public void setObject(Object object) {
this.object = object;
}


}*/
//在jdk1.5 后使用泛型来接受类中要操作的引用数据类型
//泛型类 当类中 操作的引用数据类型不确定的时候就用泛型来表示
//
public class Tool<QQ>{
private QQ q;


public QQ getObject() {
return q;
}


public void setObject(QQ object) {
this.q = object;
}

/**
* 将泛型定义在了方法上 会自动找类型匹配
* 自定义的
* @param str
*/
public <W> void show(W str){
System.out.println("show:"+str.toString());
}
public void print(QQ str){//泛型跟着对象走 一旦使用泛型变量方法不确定所以特有方法不能用
System.out.println("print:" +str);//一定具备object的方法 通用
}
/**
* 当方法静态时 不能访问类上定义的泛型 
* 如果静态方法使用泛型 只能将方法定义在方法上
* 泛型放在 修饰符后面 返回值前面 
* @param obj
*/
public static <Y> void method(Y obj){ 
System.out.println("method:"+obj);
}

}
public class GenericDemo01 {
public static void main(String[] args) {
Tool<Student> tool = new Tool<Student>();


tool.setObject(new Student());
// tool.setObject(new Worker()); //比Object安全 但麻烦一点 直接在编译就不通过
Student stu = tool.getObject();


// Student stu = (Student) tool.getObject();//提高了扩展性但是要强转


}




}

public class GenericDemo02 {
public static void main(String[] args) {
Tool<String> tool = new Tool<String>();


tool.show(new Integer(4));//类型检查不通过 经过方法自定义泛型后可自动匹配


tool.print("haha");
}
}


public class GenericDemo03 {
public static void main(String[] args) {
InterImpl in = new InterImpl();
in.show("oo");


InterImp2<Integer> in2 = new InterImp2();//可以自己指定
in2.show(33);
}
}
//泛型接口 把泛型定义在接口上
interface Inter<T>{
public void show(T t);
}


class InterImpl implements Inter<String>{//别忘了加上泛型才能指定类型
@Override
public void show(String str) {
System.out.println(str);
}
}
class InterImp2<Q> implements Inter<Q>{
@Override
public void show(Q q){
System.out.println("show"+q);
}
}


/*
 * 泛型的通配符 ? 未知类型
 */
public class GenericAdvancedDemo01 {
public static void main(String[] args) {
ArrayList<Person> al = new ArrayList<Person>();


al.add(new Worker("abb",11));
al.add(new Worker("ab2b",13));
al.add(new Worker("acb",12));


ArrayList<Student> al2 = new ArrayList<Student>();


al2.add(new Student("acb",12));
al2.add(new Student("acb",12));
al2.add(new Student("acb",12));




printCollection(al);
printCollection(al2);


}
/*
* 迭代并打印集合中的元素
* 可以对类型进行限定
* ? extends E :接受 E类型或者E的子类型对象 上限
*
* ? super E  接受E类型或者E的父类型 下限
*
*/
// public static void printCollection(Collection<? extends Person> al){//Collection<Person> al = new ArrayList<Worker>
// Iterator<?extends Person> it = al.iterator();//泛型类型不匹配  左右两边泛型要一致 但不一定  用?extends 限制类型 很强 安全
// while(it.hasNext()){
//
// Person p = it.next();
// System.out.println(p.getName()+"..."+p.getAge());
// }
//
// }
public static void printCollection(Collection<? super Student> al){//学生类型 或者学生的父类
Iterator<? super Student> it = al.iterator();//
while(it.hasNext()){




System.out.println(it.next());
}


}
// public static void printCollection(Collection<?> al){//不能和Collection<Integer>共存
// Iterator<?> it = al.iterator();//可以不加<?> 因为兼容老版本 但是还是加上比较好 会有感叹号
// while(it.hasNext()){
// System.out.println(it.next());
// }
//
// }
// public static <T> T printCollection(Collection<T> al){//
// Iterator<T> it = al.iterator();//
//// while(it.hasNext()){
//// T str = it.next();
//// System.out.println(str);
//// }
// T t = it.next();
// return t; //返回值为T 可以对类型进行操作
// }




}


public class GenericAdvancedDemo02 {
public static void main(String[] args) {
ArrayList<Person> al = new ArrayList<Person>();


al.add(new Worker("abb",11));
al.add(new Worker("ab2b",13));
al.add(new Worker("acb",12));


ArrayList<Student> al2 = new ArrayList<Student>();


al2.add(new Student("acb",12));
al2.add(new Student("acb",12));
al2.add(new Student("acb",12));


ArrayList<String> al4 = new ArrayList<String>();
// al.addAll(al4);//类型不匹配


al.addAll(al2);


printCollection(al2);
printCollection(al);


}


public static void printCollection(Collection<? extends Person> al){//Collection<Person> al = new ArrayList<Worker>
Iterator<?extends Person> it = al.iterator();//泛型类型不匹配  左右两边泛型要一致 但不一定  用?extends 限制类型 很强 安全
int count =0;
while(it.hasNext()){
count ++;
Person p = it.next();
}
System.out.println(count);


}


}


//一般在存储元素的时候都使用上限  因为这样取出都是按照上限类型来运算 不会出现类型安全隐患
class MyCollection<E>{
public void add(E e){


}


public void addAll(MyCollection<? extends E> e){//类型会有安全隐患
 //扩展后子类来了 也能进入 而且可以判断
}


}


/*
 * class TreeSet<E>{
 * Tree(Comarator<? super E> comp);
 * }
 * 什么时候用下限  通常 对集合中的元素进行取出(按照子类特有属性进行排序)操作时 可以使用下限
 */

public static void main(String[] args) {


ArrayList<Person> al = new ArrayList<Person>();
al.add(new Person("aaa",11));
al.add(new Person("ba",11));
al.add(new Person("ea",13));
al.add(new Person("ca",121));


ArrayList<String> al2 = new ArrayList<String>();
al2.add("aa");
al2.add("ba");
al2.add("ac");


al.contains(al2);//(移除也)依赖于equals 能接受任意对象  每个都有equals
"abc".equals(new Person("ss",11)); //如果没有复写equals 比较的就是地址值 所以可以比较
printCollection2(al);
}


public static void printCollection2(Collection<?> ts) {//不知道类型就泛型?
Iterator<?> it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}



后缀名就是该集合所属的体系

前缀名就是该集合的数据结构

看到array 就要想到数组 就要想到查询快有角标

看到link 就要想到链表 就要想到增删快就要想到add get removefirst last 的方法

看到hash 就要想到哈希表 就要想到唯一性 就要想到元素需要覆盖hashCode 方法和equals 方法

看到tree 就要想到二叉树 就要想到排序 就要想到两个接口Comparable(类对象 自带比较器实现) Comparator (自己定义的比较器可以放在新创集合的时候赋予比较器)


而且这些常用的集合容器一般都是不同步的



原创粉丝点击