类型推断

类型推断是Java编译器查看每个方法调用和相应声明的能力,以确定使调用适用的类型参数,推理算法确定参数的类型,如果可用,还确定分配或返回结果的类型,最后,推理算法尝试查找适用于所有参数的最具体类型。

为了说明最后一点,在下面的示例中,推断确定传递给pick方法的第二个参数是Serializable类型:

static T pick(T a1, T a2) { return a2; }

Serializable s = pick("d", new ArrayList());

类型推断和泛型方法

泛型方法向你介绍了类型推断,它使你能够像普通方法一样调用泛型方法,而无需在尖括号之间指定类型,考虑以下示例BoxDemo,它需要Box类:

public class BoxDemo {

public static void addBox(U u,

java.util.List> boxes) {

Box box = new Box<>();

box.set(u);

boxes.add(box);

}

public static void outputBoxes(java.util.List> boxes) {

int counter = 0;

for (Box box: boxes) {

U boxContents = box.get();

System.out.println("Box #" + counter + " contains [" +

boxContents.toString() + "]");

counter++;

}

}

public static void main(String[] args) {

java.util.ArrayList> listOfIntegerBoxes =

new java.util.ArrayList<>();

BoxDemo.addBox(Integer.valueOf(10), listOfIntegerBoxes);

BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);

BoxDemo.addBox(Integer.valueOf(30), listOfIntegerBoxes);

BoxDemo.outputBoxes(listOfIntegerBoxes);

}

}

以下是此示例的输出:

Box #0 contains [10]

Box #1 contains [20]

Box #2 contains [30]

泛型方法addBox定义了一个名为U的类型参数,通常,Java编译器可以推断泛型方法调用的类型参数,因此,在大多数情况下,你不必指定它们,例如,要调用泛型方法addBox,可以使用类型见证指定类型参数,如下所示:

BoxDemo.addBox(Integer.valueOf(10), listOfIntegerBoxes);

或者,如果省略类型见证,Java编译器会自动推断(从方法的参数)类型参数是Integer:

BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);

类型推断和泛型类的实例化

只要编译器可以从上下文中推断出类型参数,就可以用一组空的类型参数(<>)替换调用泛型类的构造函数所需的类型参数,这对尖括号被非正式地称为菱形。

例如,请考虑以下变量声明:

Map> myMap = new HashMap>();

你可以使用一组空的类型参数(<>)替换构造函数的参数化类型:

Map> myMap = new HashMap<>();

请注意,要在泛型类实例化期间利用类型推断,必须使用菱形,在以下示例中,编译器生成未经检查的转换警告,因为HashMap()构造函数引用HashMap原始类型,而不是Map>类型:

Map> myMap = new HashMap(); // unchecked conversion warning

类型推断和泛型与非泛型类的泛型构造函数

请注意,构造函数在泛型和非泛型类中都可以是泛型的(换句话说,声明它们自己的形式类型参数),考虑以下示例:

class MyClass {

MyClass(T t) {

// ...

}

}

考虑以下MyClass类的实例化:

new MyClass("")

此语句创建参数化类型MyClass的实例,该语句显式指定泛型类MyClass的形式类型参数X的类型Integer,请注意,此泛型类的构造函数包含形式类型参数T,编译器为此泛型类的构造函数的形式类型参数T推断类型String(因为此构造函数的实际参数是String对象)。

Java SE 7之前版本的编译器能够推断泛型构造函数的实际类型参数,类似于泛型方法,但是,如果使用菱形(<>),Java SE 7及更高版本中的编译器可以推断出要实例化的泛型类的实际类型参数,考虑以下示例:

MyClass myObject = new MyClass<>("");

在此示例中,编译器为泛型类MyClass的形式类型参数X推断类型Integer,它推断出此泛型类的构造函数的形式类型参数T的类型String。

值得注意的是,推理算法仅使用调用参数、目标类型以及可能明显的预期返回类型来推断类型,推理算法不使用程序后面的结果。

目标类型

Java编译器利用目标类型来推断泛型方法调用的类型参数,表达式的目标类型是Java编译器所期望的数据类型,具体取决于表达式的显示位置,考虑方法Collections.emptyList,声明如下:

static List emptyList();

考虑以下赋值语句:

List listOne = Collections.emptyList();

此语句期望List的实例,此数据类型是目标类型,因为方法emptyList返回List类型的值,所以编译器推断类型参数T必须是值String,这适用于Java SE 7和8,或者,你可以使用类型见证并指定T的值,如下所示:

List listOne = Collections.emptyList();

但是,在这种情况下,这不是必需的,不过,在其他情况下这是必要的,考虑以下方法:

void processStringList(List stringList) {

// process stringList

}

假设你要使用空列表调用方法processStringList,在Java SE 7中,以下语句不编译:

processStringList(Collections.emptyList());

Java SE 7编译器生成类似于以下内容的错误消息:

List cannot be converted to List

编译器需要类型参数T的值,因此它以值Object开始,因此,Collections.emptyList的调用返回List类型的值,该值与方法processStringList不兼容,因此,在Java SE 7中,你必须指定类型参数值的值,如下所示:

processStringList(Collections.emptyList());

Java SE 8中不再需要这样做,什么是目标类型的概念已经扩展为包括方法参数,例如方法processStringList的参数,在这种情况下,processStringList需要一个List类型的参数,方法Collections.emptyList返回List的值,因此使用List的目标类型,编译器推断类型参数T的值为String,因此,在Java SE 8中,以下语句编译:

processStringList(Collections.emptyList());

有关详细信息,请参阅Lambda表达式中的目标类型。

java 类型推断_Java™ 教程(类型推断)相关推荐

  1. matlab中float类型的_Java局部变量类型推断(Var类型)的26条细则

    原文链接:https://dzone.com/articles/var-work-in-progress 作者:Anghel Leonard 译者:沈歌 Java局部变量类型推断(LVTI),简称 v ...

  2. java的数值类型举例_Java基本类型(示例代码)

    全新的世界,Hello World 大部分的编程语言都是以"Hello World"开始,它是一个敲门砖,当你用它砸开那道编程大门后,一个全新的世界会展现在你的面前.当踏入一步后, ...

  3. java枚举类型赋值_java枚举类型(转载)

    public class TestEnum { /*最普通的枚举*/ public enum ColorSelect { red, green, yellow, blue; } /* 枚举也可以象一般 ...

  4. java integer 相加_JAVA Integer类型自加

    JAVA语言中有一些基本数据类型,比如int,long,double... 这些数据类型可以支持一些运算操作符,其中对于int类型的++/--操作符 Integer类型是一个对象类型,居然也可以支持+ ...

  5. java直接量_Java教程:Java直接量(字面量)

    Java教程直接量是指在程序中通过源代码直接给出的值,例如在int a = 5;代码中,为变量 a 所分配的初始值 5 就是一个直接量. 直接量的类型 并不是所有的数据类型都可以指定直接量,能指定直接 ...

  6. java动态语言_java动态类型语言支持(三)

    invokedynamic指令 在前面java动态类型语言支持(一)(二)中我们有提到invokedynamic指令和java.lang.invoke包中的MethodHandle机制,在某种程度上他 ...

  7. java字节数_Java各种类型占用的字节数

    数据类型 大小(二进制位数) 范围 默认值 byte(字节) 8 -128 - 127 0 shot(短整型) 16 -32768 - 32768 0 int(整型) 32 -2147483648-2 ...

  8. 大数据 java 代码示例_Java变量类型与示例

    大数据 java 代码示例 Java变量 (Java variables) Variables are the user-defined names of the memory blocks, and ...

  9. java 时间类型添加_java date类型 怎么 插入 时间 到 数据库

    展开全部 JDBC环境下 如果使用的是PreparedStatement接口: 1.String sql = "insert into 表名(date类型的列) values(?)" ...

  10. java提取姓名_java获取类型名字的不同方法

    java的Class>类型提供了多种方法获取类型的名字.这些方法的返回值区别如下: 测试代码: 1 importjava.math.BigDecimal;2 3 public classTest ...

最新文章

  1. GPU与CPU交互技术
  2. 将Pandas中的DataFrame类型转换成Numpy中array类型的三种方法
  3. source code compiled install mongodb
  4. 领域驱动设计案例:Tiny Library:领域模型
  5. SAP Spartacus AutoFocus directive的一个例子
  6. 使用Express在Node.js中实现非常基本的路由
  7. 牛客网未通过代码---
  8. 2021年中国电影营销数字化发展分析
  9. python 菜鸟-Python 元组
  10. 洪峰:泛系、自由与“一、百、万”工程(一)
  11. Linux下安装Java运行环境
  12. 160个CrackMe破解思路合集
  13. 微信小程序自定义侧滑删除组件
  14. UVA 11137 - Ingenuous Cubrency
  15. 细数处女座的101个特质
  16. json_encode函数参数详解
  17. 全志H3停产,A40I/T3更胜一筹--CoM-X40I核心模块来了
  18. 计算机网络的形成与发展
  19. 小学计算机老师师德师风演讲稿,小学教师师德师风演讲稿【五篇】
  20. PLC和触摸屏通过智能网关与另一台主站PLC双向通讯

热门文章

  1. 一米霜降肥牛,煎饼果子,all you can eat 牛油串串
  2. [Scala的协变和逆变]
  3. 电脑硬盘空间如何免费扩容2TB+
  4. 资深技术 Leader 曹乐:如何成为技术大牛
  5. Servlet小服务程序(Service + Applet)
  6. UE基础知识:虚幻引擎编辑器界面-英汉对照表
  7. flyaway mysql_keycloak搭配mysql
  8. Windows Sqlserver Automatic Log Audit Via C/C++
  9. 电话聊天狂人 (25分)
  10. mysql的group by语句不会产生_MySQL:为什么查询列表中多了它,GROUP BY语句就会报错呢?...