Java var类型(局部变量类型推断)

时间:2020-01-09 10:36:28  来源:igfitidea点击:

在本文中,我们将讨论Java 10中包含的称为局部变量类型推断的功能。Java中添加了新的保留类型名称" var",以定义和初始化局部变量。请注意,var不是关键字,它是保留的类型名称。因此,我们现有的名为var的变量仍然有效,并且我们仍可以创建任何名为var的字段,方法,包。

Java中的类型推断

首先,让我们尝试了解此类型推断的确切含义。

String str = "test";

List<String> cityList = List.of("New Delhi", "Chicago", "London");

在以上两个语句中,左侧的类型可能会让人感到多余和明显。 Java是一种静态类型语言,它要求必须明确声明每个变量的类型,即使类型很明显,我们也必须声明它。

Java 10中引入的var type通过使用右侧的表达式推断局部变量的类型,有助于减少代码中的冗长性。我们不再需要声明变量的类型,它将由编译器从变量初始值设定项中推断出来。因此,现在可以将上述两个语句(从Java 10开始)编写为。

var str = "test";
var cityList = List.of("New Delhi", "Chicago", "London");

让我们看看类型是否被推断

System.out.println("Type of str- " + str.getClass().getName());
System.out.println("Type of cityList- " + cityList.getClass().getName());

输出为

Type of str- java.lang.String
Type of cityList- java.util.ImmutableCollections$ListN

因此,我们可以看到使用var,如何由编译器本身推断局部变量的类型,而不是显式声明每个变量的类型。

局部变量类型推断功能的主要优点是减少样板变量类型定义并提高代码可读性。

由于Java中的大多数库都是由泛型类和方法组成的,这意味着我们将有越来越多的泛型被其他泛型类型参数化。这是一个显示这种情况的示例,其中我们需要迭代String的ArrayLists的HashMap。

Map<String, List<String>> citiesCountryWise = new HashMap<String, List<String>>();
// getData() method provides the data
citiesCountryWise = getData();

// iterating over a map
for(Map.Entry<String, List<String>> entry : citiesCountryWise.entrySet()){
    // iterating over a list
    for(String cityName : entry.getValue()){
        System.out.println("City - " + cityName);
    }
}

使用局部变量类型推断,可以缩短相同的代码以提高可读性。

var citiesCountryWise = new HashMap<String, List<String>>();
citiesCountryWise = getMap();

// iterating over a map
for(var entry : citiesCountryWise.entrySet()){
    // iterating over a list
    for(String cityName : entry.getValue()){
        System.out.println("City - " + cityName);
    }
}

有关局部变量类型推断的要点

  1. 每个使用var的表达式仍具有静态类型,即值的声明类型。这意味着分配其他值将失败。

例如,在下面的语句中,编译器将i的类型推断为int。

var i = 10;

现在无法更改此类型,任何此类尝试都会导致编译时错误。

i = "test"; // Type mismatch: cannot convert from String to int
  1. var不适用于多态代码。例如,让我们将动物的简单类层次结构作为超类,将两个子类猫和狗作为类别。

在这种情况下,如果按如下所示创建Cat类的Object

var c = new Cat();

那么c的类型是什么?动物还是猫?如前所述,局部变量的类型是初始化程序的类型,因此c在这里是Cat类型。

尝试进行以下分配会导致错误。

c = new Dog(); // Type mismatch: cannot convert from Dog to Cat

因此,用var无法实现我们通常可以如下编写的多态代码。

Animal a = new Cat();
a = new Dog();
  1. var用于本地类型推断,因此不能与字段和方法签名一起使用。无法执行以下操作。
public void display(var str) { 
	....
	....
}
  1. 如果没有显式初始化,则不能使用局部变量声明。由于类型是从右侧的表达式推断出来的,因此必须具有该类型。
var a; // Cannot use 'var' on variable without initializer
  1. var变量不能初始化为null。如果为null,则类型不明确,因此任何此类赋值都会导致编译时错误。
var a = null; //Cannot infer type for local variable initialized to 'null'
  1. 我们不能将var与lambda表达式一起使用,因为它们需要显式的target-type。
var x = (a, b) -> a+b;

此lambda表达式将失败,并出现编译错误" Lambda表达式需要显式的目标类型"