java泛型的学习

java泛型的学习------


一、概述
1、jdk1.5之后产生的技术-----泛型
泛型----是jdk1.5以后出现的一种安全的机制。
泛型的好处----
           1、将运行时期的问题在编译时期就出现,暴露出来。
           2、避免强制转换的麻烦。
<>这个号什么时候用:----当操作的引用数据类型不确定的时候,就用"<>",将要操作的引用数据类型传入即可。
                        其实"<>"就是一个用于接收具体引用数据类型的参数范围。
在程序中只要用到了带有"<>"的类、接口,就要明确传入的具体的数据的类型。
如:
1)、ArrayList<E>中的“E”就是一个泛型,E就是一个引用数据类型---引用数据类型有(类、接口、数组)。
2)、Intetor<E>
3)、class Tool<e1,e2,e3>//这里的"<>"里面就是泛型 
Tool<String,person,Integer> t=new Tool<String,person,Integer>();//带泛型的类的实例化的方式。

泛型-----提高了编译的安全性---它是用在编译时期的安全性。
运行时。会将泛型去掉,生成的classes文件中是不带泛型的。这个称为泛型的擦除。
为什么擦除,因为为了兼容运行时的类加载器。
泛型的补偿:----在运行时通过获取元素的类型进行转换动作,不用使用者进行强制转换了。
泛型里放的数据类型---不可以是基本数据类型。


泛型----定义在类上、接口上、方法上。
泛型的通配符----“?”未知类型----统统都匹配的符号。
泛型的上限----为什么要用:一般在定义存元素的时候,一般都是上限。
一般在存储元素的时候都使用上限,因为这样取出都是按照上限类型来运算的,不会出现安全隐患

泛型的使用
例子一、
public class GenericDemo {
    public static void main(String[] args) {
      ArrayList a1=new ArrayList();//这种做法存在安全的隐患
      a1.add("abc");//public boolean add(Object obj);
      a1.add("haha");
      //再运行的时候进行类型匹配时将会报错。
      a1.add(4);//a1.add(new Integer(4));//Integer在15行Integer不能被强制转换成String
      //List里面最好放入同一个类型的。
      /*
       * 这个问题的解决方案-----跟数组的一样:----
       * Int[] arr=new Int[3];
       * arr[0]=9.0;//这个将报错---因为数组中只能存放Int类型的
       * 基于这个原理---
       * ArrayList<String> a2=new ArrayList<String>();//这里的String就是泛型。
       * 编译的时候进行类型的匹配。
       * Iterator<String> it=a1.iterator();
       */
      Iterator<String> it=a1.iterator();
      while(it.hasNext()){
     String str=(String) it.next();
     System.out.println(str);
      }
    }
}

例子二、泛型在类中的使用:------
main-------
public class GenericfindDemo3 {
public static void main(String[] args) {
//没有用泛型的时候-----
/*Tool tool=new Tool();*/
/*tool.setObject(new Worker());
Student stu=(Student) tool.getObject();*/
//运行时报错;弊端----需要强转

//应用了泛型以后。
Tool<Student> tool=new Tool<Student>();
//tool.setP(new Worker());//报错,编译时期类型不对。
tool.setP(new Student());
Student stu=tool.getP();
}
}

class------
//没有泛型之前用的,存在弊端。
/*public class Tool {
private Object object;
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}*/
//有了泛型之后,
/*
 * 在jdk1.5之后,使用泛型来接收类中要操作的引用的数据类型。
 * 泛型,什么时候用,当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。
 * 
 */
public class Tool<T>{
private T p;
public T getP() {
return p;
}
public void setP(T p) {
this.p = p;
}
}


例子三、-----在接口中定义的泛型----------
public class GenericDemo5 {
    /*
     * 在接口中使用的泛型。
     */
public static void main(String[] args) {
InterfaceIMPL im = new InterfaceIMPL();
im.show("interface-----1");
InterfaceIMPL2<String> im2=new InterfaceIMPL2<String>();
im2.show("interface----2");
}
}
public interface IntefaceClass<T> {
    void show(T t);
}
public class InterfaceIMPL implements IntefaceClass<String>{
     //接口上定义的泛型之一
@Override
public void show(String t) {
System.out.println(t);
}
}
public class InterfaceIMPL2<Q> implements IntefaceClass<Q>{
    //接口定义的泛型之二
@Override
public void show(Q t) {
System.out.println(t);
}
}

例子四、---泛型在方法中的使用-------------
//没有泛型之前用的,存在弊端。
/*public class Tool {

private Object object;


public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}*/
//有了泛型之后,
/*
 * 在jdk1.5之后,使用泛型来接收类中要操作的引用的数据类型。
 * 泛型,什么时候用,当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。
 * 
 * 这里就是泛型的方法的基本使用
 */
public class Tool<T>{
//方法中带的泛型的定义。这种定义的方法的泛型是依赖与类的泛型的。一旦类中的泛型一确定,则方法中的泛型
//也就被确定了,这样存在着缺点,就是一旦类指定泛型后,方法就不能再指定它的泛型了,可扩展性小。
public void show(T str){
System.out.println("show==="+str);
/*
* 这里---一旦你使用泛型,对象的类型不确定,所以不能调用摸个对象的特有的方法,除非这
* 里调用的方式,或属性是所有泛型类共有的属性或方法。
* 如:---这里的System.out.println("show==="+str.length());//就不行
*因为length是String类中的特有的方法。
*但System.out.println("show==="+str.toString());就可以,因为
 toString()方法是Object的方法,Object又是所有已知的类的父类。
*/
}
public void print(T str){
System.out.println("print==="+str);
}
//方法中带泛型的定义之二。
public <TT> TT showTT(TT t){
/*
* 1、方法的定义,这样定义的方法的泛型就不受类的泛型的限制,当调用方法的时候,才会指定泛型,
* 可扩展性强
  2、而且定义该方法的返回值是泛型的类型。
*/
return t;
}
public <RR> void showRR(RR t){
/*
* 1、带泛型的方法的定义,这样定义的方法的泛型就不受类的泛型的限制
*2、在方法被调用的时候才会指定泛型,可扩展性强,
* 3、该方法将泛型打印出来。
*/
System.out.println(t);
}
//静态的方法中带泛型----
/*
* 当方法静态是,不能访问类上定义的泛型,如果静态方法使用泛型,只能将泛型定义在方法上。
*/
    //如:错误的写法---
/*public static void ShowGG(T t){

}*/
//如:正确的写法----
public static <EE> void showEE(EE e){
System.out.println(e);
}
}
public class TestDemo {
public static void main(String[] args) {
Tool<String> tool=new Tool<String>();
tool.show("321321");
tool.print("dedasd");
tool.showTT(new String());
tool.showRR("dadad");
tool.showEE("你家");
}
}


例子五、----泛型的高级应用----------------
1)----------------
public class TestDemo {
/*
* 泛型的高级的应用-----
*/
public static void main(String[] args) {
ArrayList<String> a1 = new ArrayList<String>();
a1.add("你好----");
a1.add("大家都好----");
ArrayList<String> a2 = new ArrayList<String>();
a2.add("nihao----");
a2.add("dajiahao----");
/*
* 但如果----就会报错了。因为printCollection(Collection<String>
* //放的是String 类型的数据
* a1) 
* ArrayList<Integer> a2=new ArrayList<Integer>(); 
* a2.add(1);
* a2.add(5);
*/
ArrayList<Integer> a3=new ArrayList<Integer>(); 
a3.add(1);
a3.add(5);
printCollection(a1);
printCollection(a2);
//printCollection(a3);//报错
//
printCollection2(a1);
printCollection2(a2);
printCollection2(a3);
//
printCollection3(a1);
printCollection3(a2);
printCollection3(a3);
}
// 迭代并打印集合中的元素
public static void printCollection(Collection<String> a1) {
Iterator<String> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
// 迭代并打印集合中的元素,使用泛型的----通配符
public static void printCollection2(Collection<?> a1) {
Iterator<?> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
//迭代并打印集合中的元素,使用泛型的----泛型符
//这和使用通配符定义的时候的区别并不大。但是还是有区别的。
public static <T> void printCollection3(Collection<T> a1) {
Iterator<T> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
//"?"是只是在不明确类型,又对类型不进行操作是---就用"?"----//统配符来表示。
public static <T> T printCollection4(Collection<T> a1) {
Iterator<T> it = a1.iterator();
/*while (it.hasNext()) {
System.out.println(it.next());
}*/
T t=it.next();
return t;
}
}

2)、-------------------------------------
public class TestDemo2 {
/*
* 泛型的高级的应用-----
*/
public static void main(String[] args) {
ArrayList<Worker> a1 = new ArrayList<Worker>();
a1.add(new Worker("abc", 21));
a1.add(new Worker("abc", 21));
ArrayList<String> a2 = new ArrayList<String>();
a2.add("nihao----");
a2.add("dajiahao----");
/*
* 但如果----就会报错了。因为printCollection(Collection<String> //放的是String 类型的数据
* a1) ArrayList<Integer> a2=new ArrayList<Integer>(); a2.add(1);
* a2.add(5);
*/
ArrayList<Integer> a3 = new ArrayList<Integer>();
a3.add(1);
a3.add(5);
ArrayList<Student> a4 = new ArrayList<Student>();
a4.add(new Student("xiao", 32));
a4.add(new Student("xiao111---", 22));
ArrayList<Person> a6 = new ArrayList<Person>();
a6.add(new Person("abc", 21));
a6.add(new Person("abc", 21));
// printCollection(a1);
printCollection(a2);
// printCollection(a3);//报错
//
printCollection2(a1);
printCollection2(a2);
printCollection2(a3);
//
printCollection3(a1);
printCollection3(a2);
printCollection3(a3);
printCollection3(a4);
/*
* 当这样public static void printCollection5(Collection<Person> a1) 定义输出方法时
* printCollection5(a1);//报错 printCollection5(a4);//报错
*/
/*
* 当这样public static void printCollection5(Collection<Person> a1)
* 定义输出方法时,不会报错
*/
printCollection5(a1);
printCollection5(a4);
// printCollection5(a2);//报错,只能有Person或其子类能被装进来,并输出。
printCollection6(a1);
//printCollection7(a1);//报错
printCollection7(a4);
printCollection7(a6);
}
// 迭代并打印集合中的元素
public static void printCollection(Collection<String> a1) {
Iterator<String> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
// 迭代并打印集合中的元素,使用泛型的----通配符
public static void printCollection2(Collection<?> a1) {
Iterator<?> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
// 迭代并打印集合中的元素,使用泛型的----泛型符
// 这和使用通配符定义的时候的区别并不大。但是还是有区别的。
public static <T> void printCollection3(Collection<T> a1) {
Iterator<T> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
// "?"是只是在不明确类型,又对类型不进行操作是---就用"?"----//统配符来表示。
public static <T> T printCollection4(Collection<T> a1) {
Iterator<T> it = a1.iterator();
/*
* while (it.hasNext()) { System.out.println(it.next()); }
*/
T t = it.next();
return t;
}
// 迭代并打印集合中的元素,使用泛型的----通配符,如果这里只想输出的数据的类型是Person的子类的话,
// 输出的方法的定义如下
// 这就是泛型的限定,上限
//? extends E接收E类型或者E的子类型对象。-----上限
//? super E接收E类型或E类型的父类的对象。-----下限
public static void printCollection5(Collection<? extends Person> a1) {
/*
* 如果这里只想输出的数据的类型是Person的子类的话,那么我们的第一的想法,---肯定是
* 将“?”号换成Person,但这样是不行的,因为Person,Worker,Student都是一个个
* 单独的类,所以这样printCollection5(Collection<Person> a1)的定义是错误的。
* ,因为在类型转换的时候是会报错的。 所以写泛型的时候-----要保证左右的泛型要一致--- 如:ArrayList<Person>
* list=new ArrayList<Student>();//就会报错。
*/
Iterator<?> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
// 迭代并打印集合中的元素,使用泛型的----通配符,如果这里只想输出的数据的类型是Person的子类的话,
// 输出的方法的定义如下
// 这就是泛型的限定,上限
public static void printCollection6(Collection<? extends Person> a1) {
/*
* 这里又添加了一个功能就是可以获取Person对象,并通过对象 调用其方法。
*/
Iterator<?> it = a1.iterator();
while (it.hasNext()) {
Person p = (Person) it.next();
System.out.println(p.getName() + "===;===" + p.getAge());
}
}
//? super E接收E类型或E类型的父类的对象。-----下限
//这样做既能放Student类,又能放Srudent的父类(Person),但这里不能放Worker类
public static void printCollection7(Collection<? super Student> a1){
Iterator<? super Student> it = a1.iterator();
while (it.hasNext()) {
//Person p = (Person) it.next();
//System.out.println(p.getName() + "===;===" + p.getAge());
System.out.println(it.next());
}
}
}


3)、--------------------------
public class TestDemo4 {
/*
* 泛型的高级的应用-----
*/
public static void main(String[] args) {
ArrayList<Worker> a1 = new ArrayList<Worker>();
a1.add(new Worker("abc", 26));
a1.add(new Worker("abc123", 21));
ArrayList<Student> a2 = new ArrayList<Student>();
a2.add(new Student("xiao", 32));
a2.add(new Student("xiao111", 22));
ArrayList<Person> a3 = new ArrayList<Person>();
a3.add(new Person("ab123", 25));
a3.add(new Person("abc", 21));
}
}
//定义一个集合
/*
 * 一般在存储元素的时候都使用上限,因为这样取出都是按照上限类型来运算的,不会出现安全隐患。
 * 元素是对象,参数是类型。
 */
class MyCollection<E>{
public void add(E e){
}
public void addAll(MyCollection<? extends Person> e){
}
}
4)、-------------------------------------------
public class TestDemo5 {
public static void main(String[] args) {
ArrayList<Person> a3 = new ArrayList<Person>();
a3.add(new Person("ab123", 25));
a3.add(new Person("abc", 21));
ArrayList<String> a11=new ArrayList<String>();
}
   //这个问号,跟不写是一样的,但jdk1.5以后要求要写参数,为了安全的问题
   //问号,代表未知参数类型的时候用的。
public static void printCollection6(Collection<?> a1) {
Iterator<?> it = a1.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
class MyCollection2<E>{
public boolean containsAll(Collection<?> coll){
return true;
}
}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值