bugstar

导航

17.泛型.md

1.Generic概念

public static void main(String[] args) {
    //Generic 
    List<String> l = new ArrayList<String>();
    List<Integer> sl = Collections.synchronizedList(new ArrayList<Integer>());
    l.add("aa");
    sl.add(8);
    //sl.add("8");泛型报错
    System.out.println("List<String>" + l);
    System.out.println("List<Integer>" + sl);
     
    //Generic 简写
    Map<String, Float> sm = Collections.synchronizedMap(new HashMap<>());
    sm.put("Hello", 1f);
    System.out.println("sm" + sm);
    Map<Double, List<String>> smm = Collections.synchronizedMap(new HashMap<>());
    smm.put(2.0, l);
    //smm.putAll(2.0, sl);泛型报错
}

2.泛型类

2.1定义泛型类

定义泛型:

class 类名<声明自定义泛型>{
        
    }  

注意要点

  • 在类上自定义泛型,具体数据类型在使用该类创建对象时候确定的
  • 如果一个类在声明中指定了自定义泛型,如果使用该类创建对象时候没有指定具体的泛型数据类型,默认为Object
  • 在类上自定义泛型不能作用于静态方法,如果静态方法需要使用自定义泛型,需要在方法上声明:static void funStatic(T t){}
package com.company.project.generictext;
 
//GenericApple.java
public class GenericApple<T> {
    private T tInfo;
    //构造
    public GenericApple(){}
    public GenericApple(T tInfo){
        this.tInfo = tInfo;
    }
         
    //getter & setter
    public T gettInfo() {
        return tInfo;
    }
    public void settInfo(T tInfo) {
        this.tInfo = tInfo;
    }
}
package com.company.project.generictext;
//GenericApplePrint.java
public class GenericApplePrint {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //传入给T形参是String,所以构造只能为String
        GenericApple<String> gaString = new GenericApple<>("asdf");
        System.out.println(gaString.gettInfo());
        //传入给T形参是Integer,所以构造只能为Integer
        GenericApple<Integer> gaInteger = new GenericApple<>(6);
        System.out.println(gaInteger.gettInfo());
    } 
 
}

2.2泛型类的继承

package com.company.project.generictext;
//GenericAppleSubClass
public class GenericAppleSubClass extends GenericApple<String> {
 
}

2.3类型通配符

如果要定义一个通用的泛型子类,那么在继承中子类并不是父类的子类型,而数组是:

package com.company.project.upper;
//Shape.java
public abstract class Shape {
    public abstract void draw(Canvas c);
}
package com.company.project.upper;
//Circle.java
public class Circle extends Shape {
 
    @Override
    public void draw(Canvas c) {
        // TODO Auto-generated method stub
        System.out.println("draw a circle on the canvas.");
    
package com.company.project.upper;
//Canvas.java
import java.util.List;
 
public class Canvas {
    public void drawAll(List<? extends Shape> Shapes){
        for (Shape s : Shapes) {
            s.draw(this);
        }//for
    }
}
package com.company.project.upper;
//UpperPrint.java
import java.util.ArrayList;
import java.util.List;
 
public class UpperPrint {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Circle> l = new ArrayList<>();
        Canvas c = new Canvas();
        Circle ci = new Circle();
        l.add(ci);
        c.drawAll(l);
    }
 
}

2.4设置类型形参上下限

要使用泛型通配符‘?’,并且这个通配符不会单独使用:

上限

////只存储Integer和Integer的子类
void Fun1(Collection <? extends Integer> c){
        
    }  

下限

//只存储Integer和Integer的父类
void Fun2(Collection <? super Integer> c){
        
    }  

2.5泛型接口

定义方法

interface 接口名称<自定义泛型>{
    
}  

注意要点

  • 接口上实现自定义泛型,具体数据类型是在 实现一个接口时候指定的
  • 在接口上自定义泛型,如果在实现接口时候没有指定具体数据类型,那么默认为Object
  • 如果要延长接口自定义泛型,那么类如下
class MyClass<T> implements MyInterface<T>{
    
}  

3.泛型方法

package com.company.project.generictext;
 
import java.util.Collection;
//GenericMethod。java
public class GenericMethod {
    //GM-1
    static void fromArryaToCollection1(Object[] o, Collection<Object> c){
        for (Object oo : c) {
            c.add(oo);
        }
    }
     
    //GM-2
    //GenericMethod的:修饰符 <T> 返回类型 方法名称(形参表)
    static <T> void fromArrayToCollection2(T[] t, Collection<T> c){
        for (T t2 : c) {
            c.add(t2);
        }
    }
     
    //错误的拷贝
    static <T> void fromArrayToCollection3(Collection<T> from, Collection<T> to){
        for (T t : from) {
            //这里程序不识别
            to.add(t);
        }
    }
     
    //要用继承去拷贝
    static <T> void fromArrayToCollection4(Collection<? extends T> from, Collection<T> to){
        for (T t : from) {
            //这里程序不识别
            to.add(t);
        }
    }
}
public static void main(String[] args) {
        /*GM-1 print*/
        String[] s = {"1", "a"};
        HashSet<String> hs = new HashSet<>();
        GenericMethod gm = new GenericMethod();
        //Collection<String>不是Collection<Object>的子类,这里会编译错误
        gm.fromArryaToCollection1(s, hs);
         
        /*GM-2 print*/
        Collection<String> cs = new HashSet<>();
        //这里的T表示String
        gm.fromArrayToCollection2(s, cs);
        Integer[] i = new Integer[10];
        Collection<Number> cn = new ArrayList<>();
        //这里的T表示Number
        gm.fromArrayToCollection2(i, cn);
         
    }  

4.类型通配符和泛型方法的区别

大多数时候都可以泛型方法替换类型通配符,如Java中:

5.设置类型通配符的下限

6.擦除和转换

泛型只在编译期间有效,运行时候是没有泛型的。

//这两个函数是重载,可以
public void Fun(Person p){
}
public void Fun(Emplooe p){
}


//这里会报错!因为编译后是同样的函数名称和入参
public void Fun(List<Person> p){
}
public void Fun(List<Emplooe> p){
}

7.泛型和数组

posted on 2018-03-02 13:43  bugstar  阅读(206)  评论(0编辑  收藏  举报