为什么带有varargs的Java方法被识别为瞬态?

时间:2011-02-08 18:25:21

标签: java reflection jls

我正在使用Java Reflection API,并观察到具有可变参数列表的方法变为瞬态。为什么这个和transient关键字在这种情况下意味着什么?

来自Java词汇表,瞬态

  

Java编程语言中的关键字,指示字段不是对象的序列化形式的一部分。当一个对象被序列化时,其瞬态字段的值不包含在串行表示中,而其非瞬态字段的值包括在内。

然而,这个定义并未说明方法。有什么想法吗?

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Dummy {
    public static void main(String[] args) {
        for(Method m : Dummy.class.getDeclaredMethods()){
            System.out.println(m.getName() + " --> "+Modifier.toString(m.getModifiers()));
        }
    }

    public static void foo(int... args){}
}

输出:

main --> public static
foo --> public static transient

3 个答案:

答案 0 :(得分:22)

答案的排序可以在javassist AccessFlag

的代码中找到
public static final int TRANSIENT = 0x0080;
public static final int VARARGS   = 0x0080;

它们似乎都具有相同的值。由于transient对方法没有任何意义,而varargs对于字段没有任何意义,因此它们可以是相同的。

但是Modifier课程不考虑这一点是不行的。我提出了一个问题。它需要一个新常量 - VARARGS和一个新方法 - isVarargs(..)。并且可以重写toString()方法以包括“transient / varargs”。

答案 1 :(得分:6)

这看起来像是实施中的一个错误。我认为根本原因可能是.class文件中为瞬态字段设置的位对于varargs方法是相同的(参见http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf,第122和119页)。

答案 2 :(得分:3)

瞬态字段的标志已在方法的上下文中重载,表示该方法是一种vararg方法。

同样,volatile方法的标志在方法的上下文中已经重载,意味着该方法是一种桥接方法。

请参阅:http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-Java5.pdf

第118-122页(或PDF文件中的26-30)

更新

读取Modifier.java的源代码确认了这个答案的第一句话(“瞬态字段的标志已经过载”)。这是相关的源代码:

// Bits not (yet) exposed in the public API either because they
// have different meanings for fields and methods and there is no
// way to distinguish between the two in this class, or because
// they are not Java programming language keywords
static final int BRIDGE    = 0x00000040;
static final int VARARGS   = 0x00000080;
static final int SYNTHETIC = 0x00001000;
static final int ANNOTATION  = 0x00002000;
static final int ENUM      = 0x00004000;
static final int MANDATED  = 0x00008000;