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

Posted ll1994

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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定义成一个确定的泛型数据类型,参数就只能是这种数据类型。此时,就用到了通配符代替确定的泛型数据类型。

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

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










以上是关于java 泛型声明与 通配符的使用的主要内容,如果未能解决你的问题,请参考以下文章

Java 泛型泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )

深入Java泛型二通配符与嵌套

Java 泛型方法泛型类通配符通配符上下限

Java 泛型概述与应用

Java泛型用法

Java泛型用法