java 泛型声明与 通配符的使用

一:泛型类
  把泛型定义在类上:作用域是整个类的内部
  格式:public class 类名<泛型类型1,…>
  注意:泛型类型必须是引用类型

import java.util.Arrays;

public class GenericClassDemo {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<String>();
        list.add("javase");
        list.add("javaee");
        list.add("javame");
        System.out.println(list.get(0));//javase
        System.out.println(list);//[javase, javaee, javame]
    }
}
/*泛型类
    把泛型定义在类上:作用域是整个类的内部
    格式:public class 类名<泛型类型1,…>
    注意:泛型类型必须是引用类型
*/
class MyArrayList<T>{
    private Object[] elementData = new Object[10];

    public boolean add(T e) {
        //遍历数组中的元素值,如果当前元素是null,就说明当前位置没有值,就可以往元素位置里面放值
        for(int i=0; i<elementData.length; i++){
            if(elementData[i]==null){
                elementData[i] = e;
                return true;
            }
        }
        return false;
    }

    public T get(int index) {
        //判断索引是否正确
        if(index<0 || index>elementData.length-1){
            return null;
        }
        return (T) elementData[index];
    }

    //[javase, javaee, javame]
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i=0; i<elementData.length; i++){
            //把不等于null的元素添加进sb中
            Object value = elementData[i];
            if(null!=value){
                sb.append(value+",");
            }
        }
        //将最后一个元素最右边的","去除掉
        String result = sb.toString().substring(0, sb.length()-1);

        return result+"]";
    }
}

输出结果:

javase
[javase,javaee,javame]

泛型方法
  把泛型定义在方法上:作用域是整个方法
  格式:public <泛型类型> 返回类型 方法名(泛型类型 .)

package cn.edu360;

public class GenericMethodDemo {
    public static void main(String[] args) {
        Object obj = "哈哈";
        //把obj强转成String
        //String s = (String)obj;
        String s = cast(obj);
        System.out.println(s);//哈哈

        obj = 123;//把123自动装箱成Integer
        //把obj强转成Integer
        //Integer i = (Integer)obj;
        Integer i = cast(obj);
        System.out.println(i);//123
    }

    /*泛型方法
        把泛型定义在方法上:作用域是整个方法
        格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
    */
    public static <T> T cast(Object obj){
        return (T) obj;//你要的是什么类型,我就给你强转成什么类型
    }
}

输出结果:

哈哈
123

  接口泛型可以一直传递下去,接口的子类除了可以继承泛型,还可以定义自己特有的泛型

  

泛型接口
  把泛型定义在接口上
  格式:public interface 接口名<泛型类型1…>

  

public interface InterTest<T> {
    void test(T t);
}
public class GenericInterfaceDemo<E,T,T2> implements InterTest<E> {
    public static void main(String[] args) {

    }

    @Override
    public void test(E t) {
        // TODO Auto-generated method stub

    }
}

二、? ,类型通配符

1.无限定通配符,<?>。

2.上限通配符,<?  extends  Number>。表示参数类型只能是Number的子类。

3.下限通配符,<?  supper Number>。表示参数类型只能是Number的父类。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

//泛型特点:泛型的左右类型必须保持一致且必须是引用类型
public class GenericDemo {
    public static void main(String[] args) {
        /*泛型通配符<?>
        任意类型,如果没有明确,那么就是Object以及任意的Java类了*/
        //test1();

        /*? extends E
        向下限定,E及其子类*/
        //test2();

        /*? super E
        向上限定,E及其父类*/
        test3();

    }
    /*泛型通配符<?>
    任意类型,如果没有明确,那么就是Object以及任意的Java类了*/
        private static void test1() {
            Object obj = "哈哈";
        //    Collection<Object> c = new ArrayList<String>();//error
            Collection<Object> c = new ArrayList<Object>();
            Collection<?> c2 = new ArrayList<Object>();
            Collection<?> c3 = new ArrayList<Animal>();
            Iterator<?> iterator = c3.iterator();
            //不能往c3里面添加值,因为不知道c3接收的是什么泛型的集合
            //可以取出值,用Object类型接收,因为不论任何类型的值都是Object的子类
            obj = iterator.next();
        }

        /*? extends E
        向下限定,E及其子类*/
        private static void test2() {
            Collection<? extends Animal> c = new ArrayList<Animal>();
            Collection<? extends Animal> c2 = new ArrayList<Pig>();
            Collection<? extends Animal> c3 = new ArrayList<Dog>();
            //Collection<? extends Animal> c4 = new ArrayList<Object>();
            //不能往c3里面添加值,因为不知c3接收的是什么泛型的集合
            Iterator<? extends Animal> iterator = c3.iterator();
            //取值的类型可以Animal来接收,因为集合中添加的值肯定是Animal自身或者子类的类型的值
            Animal animal = iterator.next();
        }
    /*? super E
    向上限定,E及其父类*/

    private static void test3() {
        //Collection<? super Animal> c = new ArrayList<Pig>();
        Collection<? super Animal> c2 = new ArrayList<Animal>();
        Collection<? super Animal> c3 = new ArrayList<Object>();
        //可以添加值,因为泛型的类型至少是Animal本身或者Animal的父类泛型,根据多态的特点,至少可以添加Animal类型的值
        c3.add(new Animal());
        Iterator<? super Animal> iterator = c3.iterator();
        //因为最大的父类确定不了,所以只能用obj类接收
        Object obj = iterator.next();
    }

}
class Animal{}
class Dog extends Animal{}
class Pig extends Animal{}

泛型的好处:

  

    在定义泛型对象的使用方法时,还不知道T是什么类型,它可能是String类型,也可能是Integer类型。如果,把T定义成一个确定的泛型数据类型,参数就只能是这种数据类型。此时,就用到了通配符代替确定的泛型数据类型。

  使用泛型、通配符提高了代码的复用性。

  把一个对象分为声明、使用两部分的话。泛型侧重于类型的声明上代码复用,通配符则侧重于使用上的代码复用。泛型用于定义内部数据类型的不确定性,通配符则用于定义使用的对象类型不确定性。

原文地址:https://www.cnblogs.com/ll1994/p/8280708.html

时间: 2024-08-28 23:23:47

java 泛型声明与 通配符的使用的相关文章

java泛型之使用通配符参数

类型安全虽然有用,但是有时可能会影响代码结构,使得无法被完全接受.例如,对于上一节的Stats类,假设希望添加方法sameAvg(),该方法用于判定两个Stats对象包含的数组的平均值是否相同,而不考虑每个对象包含的数值数据的具体类型.例如,如果一个对象包含double值1.0.2.0.和3.0,另一个对象包含整数值2.1和3,那么平均值是相同的.实现sameAvg()方法的一种方式是传递Stats参数,然后根据调用对象比较参数的平均值,只有当平均值相同时才返回true.例如: ...... I

JAVA 泛型中的通配符 T,E,K,V,?

前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 泛型带来的好处 在没有泛型的情况的下,通过对类型 Object 的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的.对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这

【转】聊一聊-JAVA 泛型中的通配符 T,E,K,V,?

原文:https://juejin.im/post/5d5789d26fb9a06ad0056bd9 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 泛型带来的好处 在没有泛型的情况的下,通过对类型 Object 的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类

java泛型中的通配符

概述 在学习java中泛型这块内容的时候,刚开始非常容易理解,但是,到通配符的时候,我就晕了,因为学习java这块内容的指导思想,是比对着.net来的,可是java中的通配符,.net中没有这样的概念,于是花时间学习了一下,下面通过例子向大家讲解通配符 实例代码 package com.tgb.mydemo; import java.util.ArrayList; import java.util.List; public class Test { public static void main

Java泛型中的通配符的使用

package com.srie.testjava; import java.util.ArrayList; import java.util.List; public class TestClassDefine2<T, S extends T> { public static void main(String[] args) { List<String> slist = new ArrayList<String>(); List<Integer> iLis

java泛型中的上、下界通配符

java泛型中,通配符?表示未知类型,等同于<? extends Object>,<? extends T>是上边界限定通配符,<? super T>是下边界限定通配符. 一.区别 在一个list中,上下界通配符能够存放和读取的对象类型如下图所示: 二.原则 上下界通配符的使用应当遵循PECS原则:Producer Extends,Consumer Super. 限定通配符总是包括自己 上界类型通配符:add方法受限 下界类型通配符:get方法受限 如果你想从一个数据类

Java泛型 通配符? extends与super

本文来源:https://i.cnblogs.com/EditPosts.aspx?opt=1 感谢博主.本文仅供参考学习. Java 泛型 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object extends 示例 static class Food{} static class Frui

Java 泛型解析,太难了,认真读才能理解

Java 泛型 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object extends 示例 static class Food{} static class Fruit extends Food{} static class Apple extends Fruit{} static clas

浅谈Java泛型之&lt;? extends T&gt;和&lt;? super T&gt;的区别

关于Java泛型,这里我不想总结它是什么,这个百度一下一大堆解释,各种java的书籍中也有明确的定义,只要稍微看一下就能很快清楚.从泛型的英文名字Generic type也能看出,Generic普通.一般.通用的,是一个概括性的词,那么泛型从名字上也就好理解了,它是一种通用类型,是java中各种类型的概括. ?是java泛型中的通配符,它代表java中的某一个类,那么<? extends T>就代表类型T的某个子类,<? super T>就代表类型T的某个父类. 这里我们先定义一组