精华内容
下载资源
问答
  • Java 范型

    2018-02-23 17:51:12
    Java 范型 1. Type 接口简介 简单来说:Type 是所有类型的父接口, 如 参数化类型(parameterized types 对应 ParameterizedType)、 数组类型(array types 对应 GenericArrayType)、 类型变量(type variables 对应...

    Java 范型

    1. Type 接口简介

    简单来说:Type 是所有类型的父接口, 如 参数化类型(parameterized types 对应 ParameterizedType)、 数组类型(array types 对应 GenericArrayType)、 类型变量(type variables 对应 TypeVariable )和基本(原生)类型(primitive types 对应 Class),。

    子接口有 ParameterizedType、TypeVariable、GenericArrayType、WildcardType、实现类有Class。

    2. ParameterizedType(参数化类型)

    下面的这些都是 parameterizedType

    Map<String, Person> map;
    Set<String> set1;
    Class<?> clz;
    Holder<String> holder;
    List<String> list;
    
    static class Holder<V>{
    }

    而类似于这样的不是 ParameterizedType.

    Set set;
    List aList;

    ParameterizedType 的几个主要方法

    public interface ParameterizedType extends Type {
        Type[] getActualTypeArguments();
        Type getRawType();
        Type getOwnerType();
    }
    • getActualTypeArguments 返回这个 Type 类型的参数的实际类型数组。 如 Map

    class ParameterizedTypeBean {
        // 下面的 field 的 Type 属于 ParameterizedType
        Map<String, User> map;
        Set<String> set1;
        Class<?> clz;
        Holder<String> holder;
        List<String> list;
    
        // Map<String,Person> map 这个 ParameterizedType 的 getOwnerType() 为 null,
        // 而 Map.Entry<String, String> entry 的 getOwnerType() 为 Map 所属于的 Type。
        Map.Entry<String, String> entry;
    
        // 下面的 field 的 Type 不属于ParameterizedType
        String str;
        Integer i;
        Set set;
        List aList;
    
        static class Holder<V> {
        }
    }
    public class ParameterizedTypeTest {
    
        @Test
        public void testParameterizedType() {
            Field f = null;
            try {
                Field[] fields = ParameterizedTypeBean.class.getDeclaredFields();
                // 打印出所有的 Field 的 Type 是否属于 ParameterizedType
                for (int i = 0; i < fields.length; i++) {
                    f = fields[i];
                    System.out.println((f.getName()
                            + " getGenericType() instanceof ParameterizedType "
                            + (f.getGenericType() instanceof ParameterizedType)));
                }
                getParameterizedTypeMes("map" );
                getParameterizedTypeMes("entry" );
    
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }
    
        }
    
        private static void getParameterizedTypeMes(String fieldName) throws NoSuchFieldException {
            Field f;
            f = ParameterizedTypeBean.class.getDeclaredField(fieldName);
            f.setAccessible(true);
            System.out.println(f.getGenericType());
            if(f.getGenericType() instanceof ParameterizedType){
                ParameterizedType pType = (ParameterizedType) f.getGenericType();
                System.out.println(pType.getRawType());
                for (Type type : pType.getActualTypeArguments()) {
                    System.out.println(type);
                }
                System.out.println(pType.getOwnerType()); // null
            }
        }
    }

    3. TypeVariable 变量

    TypeVariable 描述所谓范型变量,也就是 或者

    public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
        // 变量上边界数组,没有指定的话是 Object
        Type[] getBounds();
    
        // 获取变量被定义在什么 GenericDeclaration 上
        D getGenericDeclaration();
    
        // 获取变量名字
        String getName();
    
        // jdk1.8
        AnnotatedType[] getAnnotatedBounds();
    }
    • getBounds 得到上边界的 Type 数组,如 K 的上边界数组是 InputStream 和 Serializable。V 没有指定的话,上边界是 Object

    • getGenericDeclaration 返回的是声明这个 Type 所在的类 的 Type

    • getName 返回的是这个 type variable 的名称

    class TypeVariableBean<K extends InputStream & Closeable, V> {
        // K 的上边界是 InputStream
        K key;
        // 没有指定的话 ,V 的上边界 属于 Object
        V value;
    
        // 不属于 TypeTypeVariable
        V[] values;
        String str;
        List<K> kList;
    }
    
    public class TypeVariableTest {
    
        @Test
        public void test() throws NoSuchFieldException {
            TypeVariableBean bean = new TypeVariableBean<FileInputStream, String>();
            Field field = TypeVariableBean.class.getDeclaredField("value");
    
            if (field.getGenericType() instanceof TypeVariable) {
                TypeVariable t = (TypeVariable) field.getGenericType();
                System.out.println(field.getName());            // value
                System.out.println(t.getGenericDeclaration());  // TypeVariableBean
            }
        }
    }

    4. GenericArrayType(范型数组)

    范型数组,组成数组的元素中有范型则实现了该接口;它的组成元素是 ParameterizedType 或 TypeVariable 类型

    // 属于 GenericArrayType
    List<String>[] pTypeArray;
    // 属于 GenericArrayType
    T[] vTypeArray;
    
    // 不属于 GenericArrayType
    List<String> list;
    // 不属于 GenericArrayType
    String[] strings;
    // 不属于 GenericArrayType
    User[] users;

    下面我们一起来看一下例子:

    class GenericArrayTypeBean<T> {
        public void test(List<String>[] pTypeArray, T[] vTypeArray,
                         List<String> list, String[] strings, User[] users) {
        }
    }
    
    public class GenericArrayTypeTest {
    
        @Test
        public void test() {
            Method method = GenericArrayTypeBean.class.getDeclaredMethods()[0];
            Type[] types = method.getGenericParameterTypes();           // 这是 Method 中的方法
            for (Type type : types) {
                System.out.println(type instanceof GenericArrayType);   // 依次输出true,true,false,false,false
            }
        }
    }

    5. WildcardType(通配符的类型)

    extends 用来指定上边界,没有指定的话上边界默认是 Object,super 用来指定下边界,没有指定的话为 null。

    几个主要方法介绍:

    public interface WildcardType extends Type {
        Type[] getUpperBounds();
        Type[] getLowerBounds();
    }
    • getLowerBounds 得到上边界 Type 的数组

    • getUpperBounds 得到下边界 Type 的数组

    下面一起来看一下例子:

    class WildcardTypeBean {
        private List<? extends Number> a;  // a 没有下界,
        //  没有指定的话,上边界默认是 Object ,下边界是  String
        private List<? super String> b;
    
        private Class<?> clazz;
    
        // 没有通配符
        private List<String> c;
    }
    
    public class WildcardTypeTest {
    
        @Test
        public void test() {
            try {
                Field[] fields = WildcardTypeBean.class.getDeclaredFields();
                for (int i = 0; i < fields.length; i++) {
                    Field field = fields[i];
                    Type type = field.getGenericType();
                    String nameString = field.getName();
                    System.out.println("下面开始打印" + nameString + "是否具有通配符");
                    //1. 先拿到范型类型
                    if (!(type instanceof ParameterizedType)) {
                        System.out.println("---------------------------");
                        continue;
                    }
    
                    //2. 再从范型里拿到通配符类型
                    ParameterizedType parameterizedType = (ParameterizedType) type;
                    type = parameterizedType.getActualTypeArguments()[0];
                    if (!(type instanceof WildcardType)) {
                        System.out.println("---------------------------");
                        continue;
                    }
    
                    WildcardType wildcardType = (WildcardType) type;
                    Type[] lowerTypes = wildcardType.getLowerBounds();
                    if (lowerTypes != null) {
                        System.out.println("下边界:" + Arrays.toString(lowerTypes));
                    }
                    Type[] upTypes = wildcardType.getUpperBounds();
                    if (upTypes != null) {
                        System.out.println("上边界:" + Arrays.toString(upTypes));
                    }
                    System.out.println("---------------------------");
                }
            } catch (SecurityException e) {
                e.printStackTrace();
            }
    
        }
    }

    6. GenericDeclaration

    GenericDeclaration 该接口用来定义哪些对象上是可以声明范型变量,目前实现 GenericDeclaration 接口的类包括 Class、Method、Constructor。

    public interface GenericDeclaration extends AnnotatedElement {
        // 用来获取该GenericDeclaration的范型变量声明
        public TypeVariable<?>[] getTypeParameters();
    }
    
    ```java
    public class GenericTest<A extends List & Serializable, C> {
    
        public static void main(String[] args) throws Exception {
            // 类的范型获取
            TypeVariable[] types = GenericTest.class.getTypeParameters();
            for(TypeVariable type : types){
                type.getName();     // 获取变量名字,返回A、B
                type.getGenericDeclaration();       // 获取变量被定义在什么GenericDeclaration上,这里返回GenericTest.class
                type.getBounds()[0].getTypeName();  // 变量上边界数组,这里返回List.class
            }
    
            // 方法的范型获取
            TypeVariable<Method>[] type2s = GenericTest.class.getMethod("test").getTypeParameters();
            for(TypeVariable type : type2s){
                type.getName();     // T、E
                type.getGenericDeclaration();   // test
                type.getBounds();
            }
        }
    
        public <T, E>T test() {
            return null;
        }
    }

    参考:

    http://blog.csdn.net/gdutxiaoxu/article/details/68926515

    展开全文
  • Java范型

    2021-03-30 16:40:16
    范型 Generics 让数据类型变得参数化 定义范型时,对应的数据类型是不确定的 范型方法被调用时,会指定具体类型 核心目标,解决容器类型在编译时安全检查的问题 public class GenericDemo { public static void ...

    范型 Generics

    让数据类型变得参数化

    • 定义范型时,对应的数据类型是不确定的
    • 范型方法被调用时,会指定具体类型
    • 核心目标,解决容器类型在编译时安全检查的问题
    public class GenericDemo {
        public static void main(String[] args) {
            List<String> linkedList = new LinkedList();
            linkedList.add("works");
    //        linkedList.add(1);
            for (int i = 0; i < linkedList.size(); i++) {
                String item = (String) linkedList.get(i);
                System.out.println(item);
            }
        }
    }
    

    范型一般用作类型校验

    • 泛型类
    • 范型接口
    • 范型方法
    class 类名称 <范型标识:可以随便写任意标识号,标识指定的范型的类型>{
    	修饰符 范型标识/* ( 成员变量类型) */
    	修饰符 构造函数(范型标识 参数)
    	.......
    } 
    
    public class GenericDemo {
        public static void main(String[] args) {
            GenericClassExample<String> stringExample = new GenericClassExample<String>("abc");
            GenericClassExample<Integer> integerExample = new GenericClassExample<Integer>(123);
            System.out.println(stringExample.getMember().getClass());
            System.out.println(integerExample.getMember().getClass());
            System.out.println(integerExample.sayHello("haha"));
        }
    }
    
    
    @Data
    public class GenericClassExample<T> {
    
        //member这个成员变量的类型为T,T的类型由外部指定
        private T member;
        public GenericClassExample(T member) {
            this.member = member;
        }
    
        public T handleSomething(T target){
            return target;
        }
    
        public String sayHello(String name){
            return "Hello" + name;
        }
    
    }
    
    

    泛型类

    • 范型的参数不支持基本类型
    public class GenericDemo {
        public static void handleMember(GenericClassExample<Integer> integerGenericClassExample){
            Integer result = 111 + integerGenericClassExample.getMember();
            System.out.println("result is" + result);
        }
        public static void main(String[] args) {
            GenericClassExample<String> stringExample = new GenericClassExample<String>("abc");
            GenericClassExample<Integer> integerExample = new GenericClassExample<Integer>(123);
            System.out.println(stringExample.getClass());
            System.out.println(integerExample.getClass());
            handleMember(integerExample);
        }
    }
    
    
    @Data
    public class GenericClassExample<T> {
    
        //member这个成员变量的类型为T,T的类型由外部指定
        private T member;
        public GenericClassExample(T member) {
            this.member = member;
        }
    
        public T handleSomething(T target){
            return target;
        }
    
        public String sayHello(String name){
            return "Hello" + name;
        }
    
    }
    

    能否在范型里面使用具备继承关系的类

    • 使用通配符?,但是会使得范型的类型检查失去意义
    public class GenericDemo {
        public static void handleMember(GenericClassExample<?> integerGenericClassExample){
            Integer result = 111 + (Integer) integerGenericClassExample.getMember();
            System.out.println("result is" + result);
        }
        public static void main(String[] args) {
            GenericClassExample<String> stringExample = new GenericClassExample<String>("abc");
            GenericClassExample<Number> integerExample = new GenericClassExample<Number>(123);
            System.out.println(stringExample.getClass());
            System.out.println(integerExample.getClass());
            handleMember(integerExample);
        }
    }
    
    • 给范型加入上边界 ?extends E
    public class GenericDemo {
        public static void handleMember(GenericClassExample<? extends Number> integerGenericClassExample){
            Integer result = 111 + (Integer) integerGenericClassExample.getMember();
            System.out.println("result is" + result);
        }
        public static void main(String[] args) {
            GenericClassExample<String> stringExample = new GenericClassExample<String>("abc");
            GenericClassExample<Number> integerExample = new GenericClassExample<Number>(123);
            System.out.println(stringExample.getClass());
            System.out.println(integerExample.getClass());
            handleMember(integerExample);
        }
    }
    
    
    • 给范型加入下边界 ?super E
    public class GenericDemo {
        public static void handleMember(GenericClassExample<? super Integer> integerGenericClassExample){
            Integer result = 111 + (Integer) integerGenericClassExample.getMember();
            System.out.println("result is" + result);
        }
        public static void main(String[] args) {
            GenericClassExample<String> stringExample = new GenericClassExample<String>("abc");
            GenericClassExample<Number> integerExample = new GenericClassExample<Number>(123);
            System.out.println(stringExample.getClass());
            System.out.println(integerExample.getClass());
            handleMember(integerExample);
        }
    }
    

    范型接口

    package com.imooc.demo.generic;
    
    public interface GenericIFactory<T,N> {
        T nextObject();
        N nextNumber();
    }
    
    
    public class GenericFactoryImpl<T,N> implements GenericIFactory<T,N>{
        @Override
        public T nextObject() {
            return null;
        }
    
        @Override
        public N nextNumber() {
            return null;
        }
    }
    
    

    范型方法

    public class GenericDemo {
        public static void handleMember(GenericClassExample<? super Integer> integerGenericClassExample){
            Integer result = 111 + (Integer) integerGenericClassExample.getMember();
            System.out.println("result is" + result);
        }
        public static void main(String[] args) {
            GenericClassExample<String> stringExample = new GenericClassExample<String>("abc");
            GenericClassExample<Number> integerExample = new GenericClassExample<Number>(123);
            System.out.println(stringExample.getClass());
            System.out.println(integerExample.getClass());
            handleMember(integerExample);
            Integer[] integers = {1,2,3,4,5,6};
            Double[] doubles = {1.1,1.2,1.3,1.4,1.5};
            Character[] characters = {'A','B','C'};
            stringExample.printArray(integers);
            stringExample.printArray(doubles);
            stringExample.printArray(characters);
        }
    }
    
    
    @Data
    public class GenericClassExample<T> {
    
        //member这个成员变量的类型为T,T的类型由外部指定
        private T member;
        public GenericClassExample(T member) {
            this.member = member;
        }
    
        public T handleSomething(T target){
            return target;
        }
    
        public String sayHello(String name){
            return "Hello" + name;
        }
    
        public static <T> void printArray(T[] inputArray){
            for (T element : inputArray) {
                System.out.printf("%s", element);
                System.out.printf(" ");
            }
            System.out.println();
        }
    
    }
    
    

    范型字母的含义

    • E - Element:在集合中使用,因为集合中存放的是元素
    • T - Type:Java 类
    • K - Key:键
    • V - Value:值
    • N - Number:数值类型
    展开全文
  • JAVA范型

    2020-08-19 16:37:44
    JAVA泛型 Reference Why 不使用范型带来的危害:当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。取出...

    JAVA泛型

    Reference

    Why

    不使用范型带来的危害:当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。

    范型可以提供编译时类型安全监测机制。

    What

    泛型,即“参数化类型”, 类似于方法中的变量参数。定义方法时有形参,然后调用此方法时传递实参。

    • 泛型只在编译阶段有效.
    • 泛型的类型参数只能是类类型,不能是简单类型。

    How

    1. 泛型类:
    /*
     * 泛型类
     * Java库中 E表示集合的元素类型,K 和 V分别表示表的关键字与值的类型
     * T(需要时还可以用临近的字母 U 和 S)表示“任意类型”
     */
    public class Pair<T> {}
    
    1. 泛型接口
    public interface Generator<T> {}
    
    1. 泛型方法
        public static <T> T getMiddle(T a) {}
    
    1. 通配符: 解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。
    ArrayList heroList<? extends Hero> 
    ArrayList heroList<? super Hero>
    ArrayList list<?>
    

    实际使用

    为了将reader中已有的方法暴露给plugin package使用,引入了sdk package。在sdk package中定义 IPosition interface,采用泛型类,降低reader的修改范围。
    Reader:

    public interface Element extends IElements<Position> {
    	public Position getStartPosition();
    }
    

    SDK:

    public interface IElement<T extends IPosition> {
    	public T getStartPosition();
    }
    
    展开全文
  • java范型

    2020-05-02 14:58:47
    public class GenericMethodTest { // 泛型方法 printElement public static < E > void printElement( E[] YourArray ) {//这里的<E>表示你可以输入任何类型的数组 // 输出数组元素 ...
    public class GenericMethodTest
    {
       // 泛型方法 printElement                       
       public static < E > void printElement( E[] YourArray )
       {//这里的<E>表示你可以输入任何类型的数组
          // 输出数组元素            
             for ( E element : YourArray ){        
                System.out.printf( "%s ", element );
             }
             System.out.println();
        }
     
        public static void main( String args[] )
        {
            // 创建不同类型数组: Integer, Double 和 Character
            Integer[] intArray = { 3,6,9,2,4,8 };
            Double[] doubleArray = { 3.3,6.6,9.9,2.2,4.4,8.8};
            Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
            
            //正常调用泛型方法
            System.out.println( "整型数组元素为:" );
            printElement( intArray  ); // 传递一个整型数组
     
            System.out.println( "\n双精度型数组元素为:" );
            printElement( doubleArray ); // 传递一个双精度型数组
     
            System.out.println( "\n字符型数组元素为:" );
            printElement( charArray ); // 传递一个字符型数组
        } 
    }
    
    
    展开全文
  • java 范型

    千次阅读 2006-10-24 08:45:00
    java 范型编程 原文:http://www.blogjava.net/ctguzhupan/archive/2006/08/14/63404.html1.一个简单的范型示例在以前,你可能遇到过这样的代码:1List list = new LinkedList(); 23list.add("a"); 45list....
  • Java 范型深度解析

    2019-07-02 03:29:55
    Java 范型自1.5引入,但有不少 Javaers 在工作中不能有效利用,一方面是对其语法规范不够熟悉;另一方面不能有效利用围绕范型的一些设计模式,开源优秀框架的使用经验,使得自己的代码质量更上一层楼。 本场 Chat 从...
  • java范型简介

    2019-07-02 22:53:25
    java范型简介 一.简单认识java范型 经常听人说“范型”,我一直不是太明白什么叫“范型”,今天就查阅了一些文章,给我的第一感觉就是之所以在java中用范型,就是为了让一些错误在编译阶段就可以暴露出来,而...
  • java范型理解

    2019-06-13 11:48:44
    java范型理解基本介绍问题1.设计范型的目的是什么?2.为什么范型要设计成伪范型(为什么有边界擦除)?3.Java是伪泛型, 为什么可以做到消除强制类型转化? 基本介绍 ...问题 2.为什么范型要设计成伪范型(为什么有边界...
  • 本文详细介绍Java范型,写一篇关于范型的博客原因有两个,前几天要写个范型方法(返回值根据传入的类型而定),竟然想了半天,最后还是从网上找了个范型方法的写法;再者,前一段时间在看Gson, Gson这个JSON包的精华...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,303
精华内容 521
关键字:

java范型

java 订阅