美文网首页
泛型方法

泛型方法

作者: 呆呆李宇杰 | 来源:发表于2017-09-10 16:32 被阅读157次

引言

泛型不仅可以应用于整个类上,还可以在类中包含参数化的方法。而这个类所在的类可以是泛型类,也可以是非泛型类。这就意味着,是否拥有泛型方法,与所在的类是否是泛型没有关系。

泛型方法可以让该方法独立于整个类而变化。这就意味着,只要能做到,那么就应当使用泛型方法。也就是说,如果泛型方法可以取代整个类泛型化,那么就应该只使用泛型方法,因为它可以使事情更加地清楚明白。
另外,对于一个static的方法而言,无法访问泛型类的类型参数,所以static要想使用泛型,则必须声明为泛型方法。

定义

要定义泛型方法,只需将泛型参数列表置于返回值之前,如下。

public class GenericMethods {
    public <T> void f(T x) {
        System.out.println(x.getClass().getName());
    }

    public static void main(String[] args) {
        GenericMethods gm = new GenericMethods();
        gm.f("");
        gm.f(1);
        gm.f(1.0);
        gm.f(1.0f);
        gm.f('c');
        gm.f(gm);
    }
}
// Outputs
java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Float
java.lang.Character
com.daidaijie.generices.method.GenericMethods

GenericMethods并不是参数化的,尽管这个类和其内部的方法可以被同时参数化,但是在上面例子中,只有方法f()具有类型参数,这是由该方法的返回类型前面的类型参数列表指明的。

注意,当使用泛型类的时,必须在创建对象的时候指定类型参数的值,而使用泛型方法的时候,通常不必指明参数类型,因为编译器会为我们找出具体的类型。这称为类型参数推断。因此,我们可以像调用普通方法一样调用f(),而且就像是f()被无限次的重载过。它甚至可以接受GenericMethods作为其类型参数。
如果调用f()的时候传入基本类型,那么将触发自动打包机制,将基本类型的值包装对应的对象。泛型方法和自动打包机制减少了许多之前我们不得不编写的代码。

类型推断的作用

在Java SE7之前,如果要创建一个泛型对象,那么将必须写非常啰嗦的代码来实现。如果创建一个持有ListMap,就要像下面那样。

Map<Person,List<? extends Pet>> petPeople = new HashMap<Person,List<? extends Pet>>(); 

然而,在泛型方法中,类型参数推断可以为我们简化一部分的操作。我们可以编写一个工具类,它包含各种各样的static方法,专门用于创建各种常用的容器对象。

public class New {
    public static <K, V> Map<K, V> mapOf() {
        return new HashMap<K, V>();
    }

    public static <T> List<T> listOf() {
        return new ArrayList<T>();
    }

    public static <T> LinkedList<T> linkListOf() {
        return new LinkedList<T>();
    }

    public static <T> Set<T> setOf() {
        return new HashSet<T>();
    }

    public static <T> Queue<T> queue() {
        return new LinkedList<T>();
    }

    public static void main(String[] args) {
        Map<String, List<String>> sls = New.mapOf();
        List<String> ls = New.listOf();
        LinkedList<String> lls = New.linkListOf();
        Set<String> ss = New.setOf();
        Queue<String> qs = New.queue();
    }
}

以上的类型推断的一个使用,尽管说这段代码在Java SE7之前为创建类型少写了很多代码,但是如果有人需要阅读以上的代码,他必须去分析工具类New,以及New所隐含的功能,这似乎导致了与不使用News的工作效率差不多。

类型推断的限制

在Java SE8之前,类型推断也有一定限制,类型推断只对赋值操作有效,将一个泛型方法调用的结果作为参数,传递给另一个方法,这时候编译器并不会执行类型判断。在这种情况下,编译器认为,调用泛型方法后,其返回值被赋给一个Object类型的变量。

public class LimitsOfInference {
    static void f(Map<Person, List<? extends Pet>> petPeople) {}

    public static void main(String[] args) {
        f(New.mapOf()); // compile error before java8
    }
}

显式的类型说明

在泛型的方法中,可以显示的指明类型,不过这种语法非常少用。要显示的指明类型,必须在点操作符与方法名之间插入尖括号,然后将类型置于尖括号内。如果是定义该方法的类的内部,必须在点操作符之前使用this关键字,如果是使用static的方法,必须在点操作符之前加上类名,这种写法看解决LimitsOfInference中的问题。

public class LimitsOfInference {
    static void f(Map<Person, List<Pet>> petPeople) {
    }

    public static void main(String[] args) {
        f(New.<Person, List<Pet>>mapOf());
    }
}

泛型和可变参数列表也能够很好的共存

public class GenericVarargs {
    public static <T> List<T> makeList(T... args) {
        List<T> result = new ArrayList<>();
        for (T item : args) {
            result.add(item);
        }
        return result;
    }

    public static void main(String[] args) {
        List<String> ls = makeList("A");
        System.out.println("ls = " + ls);
        ls = makeList("A", "B", "C");
        System.out.println("ls = " + ls);
        ls = makeList("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
        System.out.println("ls = " + ls);
    }
}
// Outputs
ls = [A]
ls = [A, B, C]
ls = [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]

相关文章

  • Java 泛型

    泛型类 例如 泛型接口 例如 泛型通配符 泛型方法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型上下边...

  • 泛型的使用

    泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法 泛型类 泛型接口 泛型通配符 泛型方法 静态方法与...

  • Java泛型

    泛型有三种实现方式,分别是泛型接口、泛型类、泛型方法。下面通过泛型方法来介绍什么是类型参数。 泛型方法声明方式:访...

  • 重走安卓进阶路——泛型

    ps.原来的标题 为什么我们需要泛型? 泛型类、泛型接口和泛型方法(泛型类和泛型接口的定义与泛型方法辨析); 如何...

  • JAVA泛型

    泛型方法 泛型类

  • 三泛型的使用

    1.泛型类和泛型方法 (1)格式 (2)示例例如a.泛型类 b.实现方法 2.泛型接口和泛型方法 (1)格式 (2...

  • 泛型

    一、泛型类、泛型接口和泛型方法1、泛型接口的定义: 2、两种泛型类的定义:(1) (2) 3、泛型方法的定义,可以...

  • 泛型 & 注解 & Log4J日志组件

    掌握的知识 : 基本用法、泛型擦除、泛型类/泛型方法/泛型接口、泛型关键字、反射泛型(案例) 泛型 概述 : 泛型...

  • 泛型

    泛型类 是在实例化类的时候指明泛型的具体类型 泛型方法 是在调用方法的时候指明泛型的具体类型 泛型方法中是用...

  • 泛型

    关于泛型类,泛型方法,泛型接口泛型类:public class FanXingLeiDemo {//这里是泛...

网友评论

      本文标题:泛型方法

      本文链接:https://www.haomeiwen.com/subject/bavzjxtx.html