为什么instanceof有时似乎在静态泛型函数中工作?

发布于 2024-09-01 03:13:14 字数 722 浏览 9 评论 0原文

问候。这是我在这个网站上的第一篇文章。

我认为由于类型擦除,人们无法指望以下代码能够编译,事实上,它无法在早期版本的 Eclipse 上编译。我的理解是 instanceof 是一个运行时运算符,无法知道将在运行时编译掉的泛型类型:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E e)
   {
      if ( !(e instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }

但是,我很惊讶地发现您的线程之一实际上在答案中包含了一些这样的代码,我最新的 Eclipse(Windows 上的 Galileo,带有 JVM 1.6 rev 20)对此非常满意 - 而且它也有效。 (我确实注意到有人说它在 Eclipse 上有效,但在该线程中的另一个 IDE/JDK 上无效,但不记得具体细节。)

有人可以解释为什么它有效,更重要的是,因为我必须指导我的学生,它是否应该在未来发挥作用。

谢谢。 (我希望代码格式正确 - 从我的角度来看,它看起来缩进正确,并且没有制表符。)

Greetings. This is my first post in this site.

I thought that because of type erasure, one could not expect the following code to compile, and indeed, it did not compile on an earlier version of Eclipse. My understanding was that instanceof was a run-time operator and could not know about the generic type which would be, by run-time, compiled away:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E e)
   {
      if ( !(e instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }

However, I was surprised to see that one of your threads actually included some code like this in an answer, and my latest Eclipse (Galileo on Windows with JVM 1.6 rev 20) is perfectly happy with it -- and it works, too. (I did notice that someone said it worked on Eclipse but not in another IDE/JDK in that thread, but don't remember the specifics.)

Can someone explain why it works, and more importantly, because I have to guide my students, whether it should be expected to work in the future.

Thank you. (I hope the code formatting comes through correctly - it looks indented correctly from my perspective and there are no tabs.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉酒的小男人 2024-09-08 03:13:14

被删除的是E。事实上,您不能执行 if (e instanceof E),因为类型参数 E 已被删除。但是,String 不是参数化类型,并且 e 确实有运行时类型,因此 if (e instanceof String) 工作得很好。

JLS 15.20.2 类型比较 instanceof 运算符

关系表达式:
    关系表达式引用类型实例

instanceof 运算符的 RelationalExpression 操作数的类型必须是引用类型或 null 类型;否则,会出现编译时错误。 instanceof 运算符后面提到的 ReferenceType 必须表示引用类型;否则,会出现编译时错误。 如果 ReferenceType 后面提到的 instanceof 运算符不表示一个编译时错误具体化类型(§4.7)。

String 是一种可具体化的类型。 E 不是。

JLS 4.7 可具体化类型

由于某些类型信息在编译期间被删除,因此并非所有类型在运行时都可用。在运行时完全可用的类型称为可具体化类型。当且仅当满足以下条件之一时,类型才是可具体化的:

  • 它指的是非泛型类型声明。
  • 它是一个参数化类型,其中所有类型参数都是无界通配符
  • 它是原始类型。
  • 它是一个原始类型。
  • 它是一个数组类型,其组件类型是可具体化的。

另请参阅

What is erased is E. You can't, in fact, do if (e instanceof E), because the type parameter E is erased. However, String is not a parameterized type, and e does have a run-time type, so if (e instanceof String) works just fine.

JLS 15.20.2 Type comparison instanceof operator

RelationalExpression:
    RelationalExpression instanceof ReferenceType

The type of a RelationalExpression operand of the instanceof operator must be a reference type or the null type; otherwise, a compile-time error occurs. The ReferenceType mentioned after the instanceof operator must denote a reference type; otherwise, a compile-time error occurs. It is a compile-time error if the ReferenceType mentioned after the instanceof operator does not denote a reifiable type (§4.7).

String is a reifiable type. E is not.

JLS 4.7 Reifiable Types

Because some type information is erased during compilation, not all types are available at run time. Types that are completely available at run time are known as reifiable types. A type is reifiable if and only if one of the following holds:

  • It refers to a non-generic type declaration.
  • It is a parameterized type in which all type arguments are unbounded wildcards
  • It is a raw type.
  • It is a primitive type.
  • It is an array type whose component type is reifiable.

See also

喜爱纠缠 2024-09-08 03:13:14

效果很好。采用 E e 的方法被编译为 Comparable e,但这并不会阻止对运行时存在的类型(您的 String)进行检查。例子)。您不能做的是检查类似 ArrayList (或您自己的类的通用专业化)的内容,因为 ArrayList 类型在运行时存在,但是 < code>ArrayList没有。因此,人们使用诸如检查列表的第一个元素之类的技巧。

That works fine. The method that takes E e is compiled as Comparable e, but that doesn't prevent checks against types that exist at runtime (String in your example). What you can't do is check for something like ArrayList<String> (or a generic specialization of your own class), because the ArrayList type exists at runtime, but ArrayList<String> does not. Thus, people use hacks like checking the first element of the list.

淡淡的优雅 2024-09-08 03:13:14

小写的 e 是一个对象,每个对象都有它的类型。您可以检查任何对象的instanceof。用不同的名称阅读你的代码,会更容易得到:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E paramObject)
   {
      if ( !(paramObject instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }

The lower case e is an object and every object has it's type. You can check instanceof on any object. Read your code with different names and it'll be easier to get:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E paramObject)
   {
      if ( !(paramObject instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文