为什么局部变量会影响类型推断等式约束? [英] Why does a local variable influences type inference equality constraints?

查看:183
本文介绍了为什么局部变量会影响类型推断等式约束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在类型推断中我有一个问题理解捕获。我有一些代码如下所示:

  import java.util.EnumSet; 

class A {
static enum E1 {
X
}

private static< T extends Enum< T>> EnumSet< T> barEnum(Class< T> x){
return null;
}

private static void foo1(EnumSet< E1> s,E1e){
EnumSet< E1> x2 = barEnum(e.getClass());
}

private static void foo2(EnumSet< E1> s){
EnumSet< E1> x = barEnum(s.iterator()。next()。getClass());




$ b

这会在编译时给出两个错误:

  Test.java:15:error:class A中的方法barEnum不能应用于给定的类型; 
EnumSet< E1> x2 = barEnum(e.getClass());
^
要求:Class< T>找到
:Class< CAP#1>
reason:推理变量T具有不兼容的等式约束E1,CAP#2
,其中T是类型变量:
T扩展Enum< T>在方法< T> barEnum(Class< T>)
中声明,其中CAP#1,CAP#2是新鲜类型变量:
CAP#1从?扩展E1
CAP#2从捕获?扩展E1
Test.java:19:错误:类A中的方法barEnum不能应用于给定的类型;
EnumSet< E1> x = barEnum(s.iterator()。next()。getClass());
^
要求:Class< T>找到
:Class< CAP#1>
reason:推理变量T具有不兼容的等式约束E1,CAP#2
,其中T是类型变量:
T扩展Enum< T>在方法< T> barEnum(Class< T>)
中声明,其中CAP#1,CAP#2是新鲜类型变量:
CAP#1从?扩展E1
CAP#2从捕获?扩展E1
注意:Test.java使用未经检查或不安全的操作。
注意:使用-Xlint重新编译:取消选中以获取详细信息。
2错误

在尝试理解错误时,我将 foo2 来捕获局部变量中的 getClass()的值,以查看实际的类型:

  private static void foo2(EnumSet< E1> s){
//这是可行的
Class< ;?扩展Enum> c = s.iterator()。next()。getClass();
EnumSet< E1> y = barEnum(c);
}

现在,错误消失,代码被编译。我不明白如何引入与表达式完全相同类型的局部变量会改变类型推断算法并解决问题。

解决方案

当您将 s.iterator()。next()。getClass()赋值给本地变量时,您使用的是原始类型 - 枚举



如果您使用casting,则可以在不使用局部变量的情况下获得相同的行为:

  private static void foo2(EnumSet< E1> s){
EnumSet< E1> x = barEnum((Class <?extends Enum>)s.iterator()。next()。getClass());
}

您可以通过以下方式避免转换:

  private static void foo2(EnumSet< E1> s){
EnumSet< E1> x = barEnum(s.iterator()。next()。getDeclaringClass());
}


I have a problem understanding captures in type inference. I have some code that looks like this:

import java.util.EnumSet;

class A {
    static enum E1 {
    X
    }

    private static <T extends Enum<T>> EnumSet<T> barEnum(Class<T> x) {
        return null;
    }

    private static void foo1(EnumSet<E1> s, E1 e) {
        EnumSet<E1> x2 = barEnum(e.getClass());
    }

    private static void foo2(EnumSet<E1> s) {
        EnumSet<E1> x = barEnum(s.iterator().next().getClass());
    }
}

This gives two errors when compiling:

Test.java:15: error: method barEnum in class A cannot be applied to given types;
        EnumSet<E1> x2 = barEnum(e.getClass());
                         ^
  required: Class<T>
  found: Class<CAP#1>
  reason: inference variable T has incompatible equality constraints E1,CAP#2
  where T is a type-variable:
    T extends Enum<T> declared in method <T>barEnum(Class<T>)
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends E1 from capture of ? extends E1
    CAP#2 extends E1 from capture of ? extends E1
Test.java:19: error: method barEnum in class A cannot be applied to given types;
        EnumSet<E1> x = barEnum(s.iterator().next().getClass());
                        ^
  required: Class<T>
  found: Class<CAP#1>
  reason: inference variable T has incompatible equality constraints E1,CAP#2
  where T is a type-variable:
    T extends Enum<T> declared in method <T>barEnum(Class<T>)
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends E1 from capture of ? extends E1
    CAP#2 extends E1 from capture of ? extends E1
Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors

While trying to understand the error, I changed foo2 to capture the value of getClass() in a local variable to see the actual type:

private static void foo2(EnumSet<E1> s) {
    // this works
    Class<? extends Enum> c = s.iterator().next().getClass();
    EnumSet<E1> y = barEnum(c);
}

Now, the error disappeared and the code is compiled. I don't understand how the introduction of a local variable with the exact same type as the expression changes the type inference algorithm and solves the problem.

解决方案

When you assign s.iterator().next().getClass() to a local variable, you are using a raw type - Enum. That's how you get over the compilation error, but get a warning instead.

You can get the same behavior without the local variable if you use casting instead:

private static void foo2(EnumSet<E1> s) {
    EnumSet<E1> x = barEnum((Class<? extends Enum>)s.iterator().next().getClass());
}

You can avoid the cast with:

private static void foo2(EnumSet<E1> s) {
    EnumSet<E1> x = barEnum(s.iterator().next().getDeclaringClass());
}

这篇关于为什么局部变量会影响类型推断等式约束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆