我试图理解规范中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
}
在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(甚至更)无法看到真正的内容。
真有趣!
使用上述代码和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,