当前位置: 首页 > 知识库问答 >
问题:

描述符和签名属性之间的Java内部类不一致?(班级档案)

洪鸿博
2023-03-14

我试图理解规范中java描述符和内部类签名之间的差异是否有原因。(我在这里直接查看类文件的内容,但我使用javap来说明)。

(注意,我在JDK 1.6.0_33和1.7.0_05上试过这个,当从Java 7使用javap查看时,两者都有相同的问题——根据Sean下面的回答,Java 6的javap似乎没有显示任何通用签名信息。)

更新:感谢那些讨论——我的观点是

  • 描述符(不包含通用信息)是正确的

如果有人想知道的话,我没有使用JAVAP,只是亲自查看类文件,我只是使用JAVAP来展示它。(所以不太可能是javap错误)。

考虑:

public class InnerClassTest1 {

  public int getX() {
    return new Inner1(new ArrayList<String>()).getX(4);
  }

  public class Inner1 {
    private final List arg;

    public Inner1(List arg) {
        this.arg = arg;
    }....

vs

public class InnerClassTest2 {

   public int getX() {
      return new Inner1(new ArrayList<String>()).getX(4);
   }

   public class Inner1<E> {
    private final List<E> arg;

    public Inner1(List<E> arg) {
        this.arg = arg;
    }.....

如果你看一下内部类上javap-cs的输出,就会发现它们有惊人的不同!

公共org.benf.cfr.tests.InnerClassTest1$Inner1(org.benf.cfr.tests.InnerClassTest1,java.util.列表);签名:(Lorg/benf/cfr/test/InnerClassTest1; Ljava/util/List;)V

vs

公共组织。本夫。美国联邦法规。测验。InnerClassTest2$Inner1(java.util.List

... 使用泛型的类缺少外部类的隐式参数!(它正确地出现在InnerClassTest1中)。

我在类文件文档中找不到任何解释——有人知道为什么会这样吗?

谢谢!

李。

更新-

我已将示例文件放在http://www.benf.org/files/innerClassTest.tgz

根据肖恩下面的回答,我试着在java 6上使用javap,我看到了两者相同的输出,没有通用信息——这让我相信java 6的javap没有显示完整的签名信息?

我在1.7.0_05-b06上使用javap得到的确切输出是

public class org.benf.cfr.tests.InnerClassTest2$Inner1<E> {
 final org.benf.cfr.tests.InnerClassTest2 this$0;
 Signature: Lorg/benf/cfr/tests/InnerClassTest2;

public org.benf.cfr.tests.InnerClassTest2$Inner1(java.util.List<E>);
 Signature: (Lorg/benf/cfr/tests/InnerClassTest2;Ljava/util/List;)V
 Code:
   0: aload_0       
   1: aload_1       
   2: putfield      #1                  // Field this$0:Lorg/benf/cfr/tests/InnerClassTest2;
   5: aload_0       
   6: invokespecial #2                  // Method java/lang/Object."<init>":()V
   9: aload_0       
  10: aload_2       
  11: putfield      #3                  // Field arg:Ljava/util/List;
  14: return        

public int getX(int);
  Signature: (I)I
  Code:
   0: iconst_2      
   1: ireturn       
}

共有2个答案

欧阳勇
2023-03-14

InnerClassTest2$Inner1上使用Javap

Compiled from "InnerClassTest2.java"
public class org.benf.cfr.tests.InnerClassTest2$Inner1<E> {
  final org.benf.cfr.tests.InnerClassTest2 this$0;
  public org.benf.cfr.tests.InnerClassTest2$Inner1(java.util.List<E>);
  public int getX(int);
}

与Krakatau拆卸给

.version 51 0
.source InnerClassTest2.java
.class super public org/benf/cfr/tests/InnerClassTest2$Inner1
.super java/lang/Object

.field final private arg Ljava/util/List;
.field synthetic final this$0 Lorg/benf/cfr/tests/InnerClassTest2;

.method public <init> : [_13]
    .limit stack 2
    .limit locals 3
    aload_0
    aload_1
    putfield org/benf/cfr/tests/InnerClassTest2$Inner1 this$0 Lorg/benf/cfr/tests/InnerClassTest2;
    aload_0
    invokespecial java/lang/Object <init> ()V
    aload_0
    aload_2
    putfield org/benf/cfr/tests/InnerClassTest2$Inner1 arg Ljava/util/List;
    return
.end method

.method public getX : (I)I
    .limit stack 1
    .limit locals 2
    iconst_2
    ireturn
.end method

.const [_13] = Utf8 (Lorg/benf/cfr/tests/InnerClassTest2;Ljava/util/List;)V

如您所见,Krakatau输出显示描述符实际上是正确的,但出于某种原因,Javap没有显示它。Javap的一点是,它试图安排输出,使其看起来更像Java。也许这是JDK7中引入的一个新特性,它试图通过隐藏编译器添加的参数,使反汇编泛型看起来更像Java。不幸的是,这使得Javap(甚至更)无法看到真正的内容。

真有趣!

赖渊
2023-03-14

使用上述代码和JDK 1.6.0_33,我得到以下输出:

src\test>javap -c -s InnerClassTest1$Inner1
Compiled from "InnerClassTest1.java"
public class test.InnerClassTest1$Inner1 extends java.lang.Object{
final test.InnerClassTest1 this$0;
  Signature: Ltest/InnerClassTest1;

public test.InnerClassTest1$Inner1(test.InnerClassTest1, java.util.List);
  Signature: (Ltest/InnerClassTest1;Ljava/util/List;)V
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield        #1; //Field this$0:Ltest/InnerClassTest1;
   5:   aload_0
   6:   invokespecial   #2; //Method java/lang/Object."<init>":()V
   9:   aload_0
   10:  aload_2
   11:  putfield        #3; //Field arg:Ljava/util/List;
   14:  return

public int getX(int);
  Signature: (I)I
  Code:
   0:   iload_1
   1:   ireturn
}

src\test>javap -c -s InnerClassTest2$Inner1
Compiled from "InnerClassTest2.java"
public class test.InnerClassTest2$Inner1 extends java.lang.Object{
final test.InnerClassTest2 this$0;
  Signature: Ltest/InnerClassTest2;

public test.InnerClassTest2$Inner1(test.InnerClassTest2, java.util.List);
  Signature: (Ltest/InnerClassTest2;Ljava/util/List;)V
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield        #1; //Field this$0:Ltest/InnerClassTest2;
   5:   aload_0
   6:   invokespecial   #2; //Method java/lang/Object."<init>":()V
   9:   aload_0
   10:  aload_2
   11:  putfield        #3; //Field arg:Ljava/util/List;
   14:  return

public int getX(int);
  Signature: (I)I
  Code:
   0:   iload_1
   1:   ireturn

}

唯一的区别是我的实现(使代码可编译):

    public int getX(int i) {
        return i;
    }

而且你的包名可能不同(org.benf.cfr.tests?)。

但除此之外,我的输出基本相同。代码中是否有其他差异可以解释您看到的内容?根据我对编译过程和类文件的了解,我不希望在输出中看到差异。

问得好找出你看到这个的原因很有趣

 类似资料:
  • 本文向大家介绍JavaScript 描述符和命名属性,包括了JavaScript 描述符和命名属性的使用技巧和注意事项,需要的朋友参考一下 示例 属性是对象的成员。每个命名属性都是一对(名称,描述符)。该名称是允许访问的字符串(使用点符号object.propertyName或方括号符号object['propertyName'])。描述符是对字段的记录,这些字段定义了访问属性时的行为(属性发生了

  • 我们知道,对象可以存储属性。 到目前为止,属性对我们来说只是一个简单的“键值”对。但对象属性实际上是更灵活且更强大的东西。 在本章中,我们将学习其他配置选项,在下一章中,我们将学习如何将它们无形地转换为 getter/setter 函数。 属性标志 对象属性(properties),除 value 外,还有三个特殊的特性(attributes),也就是所谓的“标志”: writable — 如果为

  • 问题内容: 在Java 8之前,可以通过使用匿名内部类来实现lambda功能。例如: 在性能方面,仍然使用这种方法和使用新的Java 8 lambda之间有区别吗? 问题答案: 甲骨文发布了一项研究,比较了Lambda和匿名类之间的性能 请参见Sergey Kuksenko撰写的JDK 8:Lambda性能研究 ,该幻灯片长74张。 简介:预热缓慢,但是当JIT内联时,最坏的情况与匿名类一样快,但

  • 这个版本规范的部署描述文件可在此下载:http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd

  • 本章指定的 Java™ Servlet 规范要求 Web 容器支持部署描述文件。部署描述文件表达了应用开发人员、应用集成人员和 Web 应用部署人员之间的元素和配置信息。 对于 Java Servlet 2.4 和以后的版本,部署描述文件在 XML 模式文档中定义。 为了向后兼容到2.2版本的API编写的应用程序,Web 容器也需要支持2.2版本的部署描述文件。为了向后兼容2.3版本的API编写的

  • 概述 JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。 下面是属性描述对象的一个例子。 { value: 123, writable: false, enumerable: true,