【问题标题】:Unexpected "transient" constructor modifier意外的“瞬态”构造函数修饰符
【发布时间】:2013-01-05 10:03:16
【问题描述】:

我在使用反射时发现了一些有趣的东西。我试图检索简单类的构造函数及其修饰符。

public class Test {
    public Test(Object... args) {}
}

这是检索构造函数修饰符的代码:

Class<?> clazz = Test.class;
Constructor<?>[] ctors = clazz.getDeclaredConstructors();
for (Constructor<?> ctor : ctors) {        
    int mod = ctor.getModifiers();
    /*if not package-private modifier*/
    if(mod!=0) {
        System.out.println( Modifier.toString(mod)));
    }
}

结果是:

    public transient  

如果我传递给构造函数的不是变量参数,而是数组,没关系。

public class Test {
    public Test(Object[] args) {}
}

结果是:

    public  

无论构造函数修饰符(public、protected、private)或参数类型(原始或引用)如何,都会发生同样的情况。怎么可能,而“瞬态”不是构造函数的有效修饰符?

【问题讨论】:

    标签: java reflection jvm


    【解决方案1】:

    访问修饰符在类文件中被编码为位掩码。 JVM 规范根据它们是否出现在方法修饰符或字段修饰符中为某些位分配不同的含义。第 7 位 (0x0080) 就是这样的一位。

    For methods:

    ACC_VARARGS    0x0080  Declared with variable number of arguments.
    

    For fields:

    ACC_TRANSIENT  0x0080  Declared transient; not written or read by a persistent
                           object manager.
    

    由于您正在查看一种方法,因此此修饰符的正确解释是ACC_VARARGS,而不是ACC_TRANSIENT

    但是,Modifier 类似乎只能处理 JVM 规范中定义的修饰符子集。因为它只需要一个int,它无法区分ACC_VARARGSACC_TRANSIENT

    【讨论】:

    • 这算作toString 方法的错误吗?
    • @JanDvorak:我不确定。按照目前的情况,Modifier 类似乎只能处理 JVM 规范中定义的修饰符子集(因为它无法区分具有相同位值的修饰符)。
    • 我想知道 - 为什么位值实际上会发生冲突?这不是 JVM 开发人员的疏忽吗?
    • 我提出了一个解决方案,即有 两个 toString 方法。一个用于字段,另一个用于方法。
    • @Jan:只有字段可以是瞬态的,只有方法/构造函数可以有可变参数,所以在实践中碰撞不会有问题。是的,两个toString 方法可以解决这个问题。
    猜你喜欢
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 2012-11-12
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 2020-10-25
    相关资源
    最近更新 更多