泛型: 1.5新特性。 解决安全问题,是一个安全机制!
可以指定容器 里要装入的是什么样的数据类型。
可以修饰类,可以修饰方法,
什么是泛型?
如何使用泛型?
为什么要使用泛型?
import java.util.*;
public class TestFanXing_1 {
public static void main(String[] args) {
ArrayList a1 =new ArrayList();
a1.add("努力!");
a1.add("坚持!");
a1.add("我不二");
//a1.add(4); 编译时间没问题,运行时期出错.
Iterator it =a1.iterator();
while(it.hasNext())
{
String st =(String)it.next();
System.out.println(st);
}
}
}
上面例子没有使用泛型. 容器装的类型不一致,会导致程序不安全.
看下面的例子:
使用了泛型, 解决了安全问题,是一个安全机制.
import java.util.*;
public class TestFanXing_1{
public static void main(String[] args) {
ArrayList<String> a1 =new ArrayList<String>(); //定义一个数组容器 里面存放Sstring对象
a1.add("努力!");
a1.add("坚持!");
a1.add("我不二");
Iterator<String> it =a1.iterator(); //构造一个迭代器 取出集合中的元素
while(it.hasNext()) //迭代器中是否有元素
{
String st =it.next(); //返回迭代的下一个元素
System.out.println(st+":"+st.length()); //输出元素 以及元素的长度
}
}
}
如何自定义泛型类?
自己定义的类 如何使用泛型?在什么时候使用泛型?
如果有很多类 需要相同的数据,后来的类也需要相同的这些数据,那边就用一个泛型类来设计。提高代码的复用性。
在类名字后面加上 <引用数据类型> 不能是基本数据类型。
注意:在使用泛型类的时候,由类指定要new什么类型的对象
例如A泛型类 要new一个String类型对象 .要这么写: A<String> aa =new A<String>();
class ChenLiHong
{
}
class LvJun
{
}
class Happy<YY> //泛型类
{
private YY yy;
public void setYY(YY yy)
{
this.yy=yy;
}
public YY getYY()
{
return yy;
}
}
/*
class Happy 普通类
{
private Object obj;
public void setObject(Object obj)
{
this.obj=obj;
}
public Object getObject()
{
return obj;
}
}
*/
class TestRead
{
public static void main(String[] args)
{
Happy<ChenLiHong> ha =new Happy<ChenLiHong>();
/*
Happy ha =new Happy();
定义的类没有加泛型 编译没有问题 运行出错会出现类型转换异常
ha.setObject(new LvJun()); //编译没有问题,因为参数是Obj类型
ChenLiHong clh =(ChenLiHong)ha.getObject();//运行出错,类型转换异常,设置的是LVJUN,得到的是CHENLIHONG
定义的类 没有加泛型,以前都是客观的,设置什么对象,得到的就点是什么对象。 而且必须强转类型
ha.setObject(new ChenLiHong()); //正确
ChenLiHong clh =(ChenLiHong)ha.getObject(); //正确
*/
//定义的类加了泛型 ,也就是由类 来指定要操作的什么样的类型对象。
//ha.setYY(new LvJun()); 翻译时期就会出错,提高了代码安全性。
ha.setYY(new ChenLiHong());
ChenLiHong clh =(ChenLiHong)ha.getYY();
}
}
泛型定义在接口上:
两种方法: 不常用,但要知道.
语法格式:
接口泛型类: interface Inter<T>
{
void show(T t);
}
//子类在实现泛型类的时候直接定义String类型
第一种实现: class A implements Inter<String>
{
public void show(T t)
{
System.out.println("show :"+t);
}
}
构造类: A<String> aa =new A<String>();
aa.show("成功!");
//子类在实现泛型类的时候 A类不确定什么类型 实现的Inter也不确定什么类型
第二种实现:class A<T > implements Intre<T>
{
public void show(T t)
{
System.out.println("show :"+t);
}
}
构造类: A<Integer> aa =new A<Integer>();
aa.show(4);
泛型定义在方法上: 提高代码的复用性
1:一个A类 内部 有个方法被定义泛型, 那边这个方法只属于本身.
2:一个A类被定义泛型,当A类被new对象的时候,就直接规定是什么引用数据类型.
//如果A类被定义泛型,调用自己内部的普通方法,那么方法随着A类对象的类型走.
如果A类被定义泛型,调用自己内部的泛型方法,那么A类随着方法类型走.
如果A类被定义泛型,调用自己内部的静态方法,编译会出错,因为class A<T> T只有对象的时候才会被明确类型
如果A类被定义泛型,静态方法又不确定是什么类型,那么在静态方法上加泛型.
例如:
class A<T>
{
//如果A类被定义泛型,调用自己内部的普通方法,那么方法随着A类对象的类型走.
public void show(T tt)
{
System.out.println("show : "+tt);
}
//如果A类被定义泛型,调用自己内部的泛型方法,那么A类随着方法类型走.
public <Q> void print(Q qq)
{
System.out.println("print :"+qq);
}
/*
public static void meme(T tt)
{
System.out.println("meme :"+tt);
}
//A.meme("你好"); 编译错,meme是静态方法,类名调用静态方法,而A类上的泛型<T>只有new对象的时候才会被明确类型
*/
//如果A类被定义泛型,静态方法又不确定是什么类型,那么在静态方法上加泛型.
public static<W> void meme(W ww)
{
System.out.println("meme :"+ww);
}
}
class TestRead
{
public static void main(String[] args)
{
A<String> aa =new A<String>();
aa.show("坚持");
aa.print("哈哈");
//aa.print(new A()); //A@de6ced
A.meme("你好");
}
}
? 通配符 ,也可以理解为占位符 (具备泛型,但是什么类型不确定.)
使用占位符的好处:扩展性强, 弊端:不能使用特有方法.
public static<T> void print(ArrayList<T> ap) T代表具体类型
public static void print(ArrayList<?> ap) ? 通配符,什么类型不确定
import java.util.*;
class TestRead
{
public static void main(String[] args)
{
ArrayList<String> ay =new ArrayList<String>();
ay.add("我不抽烟");
ay.add("我不喝酒");
ay.add("我不吃饭");
ArrayList<Integer> ae =new ArrayList<Integer>();
ae.add(2);
ae.add(5);
ae.add(8);
print(ae);
}
//遍历集合 一个String类型 一个Integer类型 ,
//遍历集合,要定义2个迭代器比较麻烦,有什么办法呢? 单独设计一个方法
/*
public static void print(ArrayList<String> ap) //ArrayList<String> ap =new ArrayList<String>();
{
Iterator<String> it = ap.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
主函数调用 : print(ay); //正确. 参数规定String 引用类型
print(ae); //错误 ArrayList<String> ap =new ArrayList<Integer>(); 左右两边类型不匹配
*/
/*
public static<T> void print(ArrayList<T> ap) T代表具体类型
public static void print(ArrayList<?> ap) // ?代表不明确类型. ArrayList<String> ap =new ArrayList<String>();
{
Iterator<?> it = ap.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
主函数调用 : print(ay); //正确. 参数规定<?> ? 通配符 ,也可以理解为占位符 (具备泛型,但是什么类型不确定.)
print(ae); //正确 参数规定<?> ? 通配符 ,也可以理解为占位符 (具备泛型,但是什么类型不确定.)
?和 T的区别: T代表具体类型 ?代表不明确类型 比如:传的参数是? 占位符,打印元素和长度,编译就会出错,长度是属于具体类型,而?代表是什么类型不确定.
使用占位符的好处:扩展性强, 弊端:不能使用特有方法.
*/
}
泛型的限定:
? extends E :可以接受E类型或者E的子类型,上限
? super E :可以接受E类型或者E的父类型 下限
/*
import java.util.*;
class TestRead
{
public static void main(String[] args)
{
ArrayList<Person> a2 =new ArrayList<Person>();
a2.add(new Person("小强"));
a2.add(new Person("小进"));
a2.add(new Person("向前"));
print(a2);
ArrayList<Student> a4 =new ArrayList<Student>();
a4.add(new Student("小强00"));
a4.add(new Student("小进00"));
a4.add(new Student("向前00"));
print(a4);
}
//打印一个类型的范围: 只打印 Person 和Person的子类 别的不管. 这个时候使用泛型限定
//<? extends Person> 只能打印,或者只能接收Person 和Person的子类
public static void print(ArrayList<? extends Person> a3)
{
Iterator<? extends Person> it =a3.iterator();
while(it.hasNext())
{
System.out.println(it.next().getName());
}
}
/*
public static void print(ArrayList<Person> a3)
{
Iterator<Person> it =a3.iterator();
while(it.hasNext())
{
System.out.println(it.next().getName());
}
}
主函数: print(a4); //出错,这句话等于ArrayList<Student> a3 =new ArrayList<Person>(); 左右2边要一致.
}*/
/*
class Person
{
private String name;
Person(String name)
{
this.name=name;
}
public String getName()
{
return name;
}
public String toString()
{
return "person:"+name;
}
}
class Student extends Person
{
private String name;
Student(String name)
{
super(name);
}
}
class Worker extends Person
{
Worker(String name)
{
super(name);
}
}
*/
/*
? super E :可以接受E类型或者E的父类型
例子:
*/
import java.util.*;
class TestRead
{
public static void main(String[] args)
{
TreeSet<Student> ts =new TreeSet<Student>(new StuComp());
ts.add(new Student("sss--5555"));
ts.add(new Student("sss--888"));
ts.add(new Student("sss--333"));
ts.add(new Student("sss--444"));
Iterator<Student> it =ts.iterator();
while(it.hasNext())
{
System.out.println(it.next().getName());
}
TreeSet<Worker> ts1 =new TreeSet<Worker>(new StuComp());
ts1.add(new Worker("fgdfg"));
ts1.add(new Worker("hdfdh3"));
ts1.add(new Worker("fhdfh23"));
ts1.add(new Worker("hfgj555"));
Iterator<Worker> it1 =ts1.iterator();
while(it1.hasNext())
{
System.out.println(it1.next().getName());
}
}
}
/*
class StuComp implements Comparator<Student>
{
public int compare(Student s1,Student s2)
{
return s1.getName().compareTo(s2.getName());
}
}
class WorkerComp implements Comparator<Worker>
{
public int compare(Worker s1,Worker s2)
{
return s1.getName().compareTo(s2.getName());
}
}
*/
class StuComp implements Comparator<Person> // 可以接受E类型或者E的父类型
{
public int compare(Person p1,Person p2)
{
return p2.getName().compareTo(p1.getName());
}
}
class Person
{
private String name;
Person(String name)
{
this.name=name;
}
public String getName()
{
return name;
}
public String toString()
{
return "person:"+name;
}
}
class Student extends Person
{
private String name;
Student(String name)
{
super(name);
}
}
class Worker extends Person
{
Worker(String name)
{
super(name);
}
}