泛型【泛型介绍、自定义泛型】

第十五章、泛型

一、泛型的理解和好处

1、 问题

1、不能对加入到集合ArrayList中的数据类型进行约束(不安全)

2、遍历的时候,需要进行类型转换,如果集合中的数据大,会影响效率

2、好处

1、编译时,检查添加元素的类型,提高了安全性

2、减少了类型转换的次数(用到向下转型)提高效率

(1)eg:

//无泛型
ArrayList list = new ArrayList();
        list.add(new Dog("大黄",2));
        list.add(new Dog("二哈",3));
        list.add(new Dog("小布",4));

        for(Object obj:list) {
            Dog d1 = (Dog)obj;//使用了类型转换
            System.out.println(d1.getName());
        }
//有泛型
ArrayList <Dog1> list = new ArrayList<Dog1>();
        list.add(new Dog1("大黄",2));
        list.add(new Dog1("二哈",3));
        list.add(new Dog1("小布",4));
//        list.add(new Cat("咪咪", 1));添加失败
        for(Dog1 dog : list) {//省略了强制类型转换
            System.out.println(dog.getName());
        }
    }

3、泛型介绍

1、泛型又称参数化类型,1.5版本后的,解决数据类型的安全性问题

2、在类声明或实例化时只要指定好的需要的具体的类型即可

3、java泛型会有提示,如果程序在编译类型没有发出经过,运行时就不会产生ClassCaseException类型转换异常,代码更简洁、强壮

4、作用:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值类型、或者是参数类型。

(1)eg:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        US <String> u  = new US("哈宝");
    }

class US <E> {//类定义泛型
    E ss;//属性定义泛型,E表示ss的数据类型,该数据类型在定义Persion对象时指定,在编译期间,就确定E的编译类型

    public US(E ss) {//E也可以是参数类型
        this.ss=ss;
    }
    public E ff() {    //方法返回类型也可以定义
        return ss;
    }
}

4、泛型的语法

4.1、泛型的声明

1、interface 接口 { } 和class类<K,v>{}

2、说明

(1)其中:T,K,V 不代表值,而是表示类型。

(2)任意字母都可以。常用T表示,是Type的缩写

4.2、泛型的实例化

1、eg

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Set <Student> set = new HashSet <Student> ();
        set.add(new Student("傻瓜",11));
        set.add(new Student("恶狗    ",16));
        set.add(new Student("蕾姆",18));
        for(Student student:set) {
            System.out.println(student);
        }
        HashMap<String, Student> hashMap1 = new HashMap<String,Student>();
        hashMap1.put("ton", new Student("憨包", 20));
        hashMap1.put("jack", new Student("包包", 28));
        hashMap1.put("smith", new Student("hsp", 35));
//        entryset取出。迭代器
        Set<Map.Entry<String, Student>> entries = hashMap1.entrySet();
        Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
        while(iterator.hasNext()) {
            Map.Entry<String, Student> next = iterator.next();
            System.out.println(next.getKey()+"——"+next.getValue());
        }

    }

5、泛型使用的注意事项

1、interface List{} public class HashSet{}

(1)说明:T,E只能是引用类型,且可以是多个

(2)eg:int错误,int是基本数据类型

2、在指定泛型具体类型后,可以传入该类型或其子类类型

(1)理解:就是支持了继承

3、泛型的定义形式两种

(1)List list = new ArrayList();

(2) List list = new ArrayList<> ();

(3)推荐(2)写法

4、如果我们这样写 List list3 = new ArrayList();

默认给它的泛型就是就Object类。

6、自定义泛型

6.1、基本语法

1、class 类名<T,R…>{ //…代表可以多个

​ 成员

}

6.2、注意细节

1、普通成员可以使用泛型(属性、方法)

2、使用泛型的数组,不能初始化

3、静态方法中不能使用类的泛型

4、泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)

5、如果在创建对象时,没有指定类型,默认为Object

6、eg

class Tiger<T,R,M>{
    String name;
    R r;
    M m;
    T t;
    T ts[];//可以定义,不能初始化
//    T[] ts = new T[8]    参数类型不允许直接实例化。因为数组在new不能确定T的类型,无法在内存开辟空间
    public Tiger(String name, R r, M m, T t) {
        super();
        this.name = name;
        this.r = r;
        this.m = m;
        this.t = t;
    }
//    static R r2; 
//    因为静态是和类相关的,类加载时,对象不加载。
//    所以静态方法和静态属性使用了泛型,JVM无法判断大小

7、自定义泛型接口

7.1、基本语法

interface 接口名<T,R…>{ //…代表可以多个 成员

7.2注意细节

1、接口中,静态成员也不能使用泛型(这个和泛型类规定一样)

2、泛型接口的类型,在继承接口或者实现接口时确定

3、没有指定类型,默认为Object

7.3、eg

interface IA extends IUsb<String, Double>{    
}
//当我们去实现IA接口时,因为IA在继承IUse 接口时,指定了U为String,R为Ddouble类型
class AA implements IA{
    @Override
    public Double get(String u) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void hi(Double r) {
        // TODO Auto-generated method stub
    }
    @Override
    public void run(Double r1, Double r2, String u1, String u2) {
        // TODO Auto-generated method stub
    }
}
class CC implements IUsb{    //如果没写,泛型默认为Object
    @Override
    public Object get(Object u) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void hi(Object r) {
        // TODO Auto-generated method stub    
    }
    @Override
    public void run(Object r1, Object r2, Object u1, Object u2) {
        // TODO Auto-generated method stub    
    }
}
interface IUsb<U,R>{
    int n =10;
//    U name; 不能这样使用
//    普通方法中,可以使用接口泛型
    R get(U u);
    void hi(R r);
    void run(R r1,R r2,U u1,U u2);
//    在jdk8中,可以在接口中,使用默认方法,也是可以这样使用发那些
    default R method(U u) {
        return null;
    }
}

8、自定义泛型方法

8.1基本语法

1、修饰符 <T,R…> 返回类型 方法名(参数列表){

}

8.2、注意细节

1、泛型方法,可以定义在普通类中,也可以定义在泛型类中

2、泛型方法被调用时,类型确认

3、public void eat(E e){ }。修饰符后没有<T,R…>eat 方法不是泛型类型,而是使用了泛型。

8.3、eg

        Car car = new Car(); 
        car.fly("宝马", 100);//当调用方法时,传入参数,编译器,就会确定类型
    }

}
class Car{    //普通类
    public void run() {//普通方法    
    }
//    说明
//    1、<T,R>就是泛型
//    2、是提供给fly使用的
    public <T,R>void fly(T t,R r){//泛型方法    
        System.out.println(t.getClass());//String类型
        System.out.println(r.getClass());//Integer类型
    }
}
class Fish<T,R>{
    public void run() {//普通方法
    }
    public <U,M> void eat() {
    }
//    说明
//    1、下面hi方法不是泛型方法
//    2、是普通方法使用类定义的泛型
    public void hi(T t) {
    }
//    泛型方法,可以使用类声明的泛型,也可以使用自己声明泛型
    public <K> void hello(R r,K k) {
    }
}

9、泛型的继承和通配符

1、泛型不具备继承性

(1)List list = new ArrayList ();

2、<?>:支持任意泛型类型

3、<? extends A>:支持A类以及A类的子类,规定了泛型的上线

4、<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限。

5、eg

//        泛型没有继承性
//        List <Object> list = new ArrayList<>();
    List<Object> list1 = new ArrayList<>();
    List<String> list2 = new ArrayList<>();
    List<AA1> list3 = new ArrayList<>();
    List<BB1> list4 = new ArrayList<>();
    List<CC1> list5 = new ArrayList<>();    

//    这种方法<?>,全部加的进去
    printCollection1(list1);
    printCollection1(list2);
    printCollection1(list3);
    printCollection1(list4);
    printCollection1(list5);

//    这种方法 List<? extends AA> c 表示 上限,可以接受AA或者AA子类
    printCollection2(list1);//不行
    printCollection2(list2);//不行
    printCollection2(list3);//可以
    printCollection2(list4);//可以
    printCollection2(list5);//可以

//    这种方法 List<? super 
    printCollection3(list1);//可以
    printCollection3(list2);//不行
    printCollection3(list3);//可以
    printCollection3(list4);//不行
    printCollection3(list5);//不行
    }
    public static void printCollection1(List<?>c) {    //通配符,取出时,就是Object
        for(Object object : c ) {
            System.out.println(object);
        }
    }
//    ? extends AA 表示 上限,可以接受AA或者AA子类
    public static void printCollection2(List<?extends AA1>  c) {    //通配符,取出时,就是Object
        for(Object object : c ) {
            System.out.println(object);
        }
    } 
//    ?super 子类类名AA1:支持AA类以及AA类的父类,不限直接父类。
    public static void printCollection3(List<? super AA1>c) {    //通配符,取出时,就是Object
        for(Object object : c ) {
            System.out.println(object);
        }
    }
}
class AA1{
}
class BB1 extends AA1{    
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
Theme Argon By solstice23