合成方法的惩罚是什么?

在Eclipse下开发Java应用程序时,我收到了关于“通过合成方法访问的方法/值”的警告。 解决方案只是将私有访问修饰符更改为默认级别。

这让我想知道:使用合成方法的惩罚是什么? 有一些? 我假设编译器/ Eclipse会引发警告,但它是如此相关的东西还是可以安全忽略的东西?

我没有在这里看到这些信息,所以我问。

Eclipse警告您,您可能正在公开您认为是私有的信息。 合成访问器可以被恶意代码利用,如下所示。

如果您的代码需要在安全的VM中运行,那么使用内部类可能是不明智的。 如果您可以使用reflection并且可以完全访问所有内容,则合成访问器不太可能产生可测量的差异。


例如,考虑这个类:

public class Foo { private Object baz = "Hello"; private class Bar { private Bar() { System.out.println(baz); } } } 

Foo的签名实际上是:

 public class Foo extends java.lang.Object{ public Foo(); static java.lang.Object access$000(Foo); } 

access$000会自动生成,让单独的Bar访问baz并使用Synthetic属性进行标记。 生成的精确名称取决于实现。 常规编译器不允许您针对此方法进行编译,但您可以使用ASM(或类似)生成自己的类,如下所示:

 import org.objectweb.asm.*; public class FooSpyMaker implements Opcodes { public static byte[] dump() throws Exception { ClassWriter cw = new ClassWriter(0); cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Spy", null, "java/lang/Object",null); MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); ctor.visitCode(); ctor.visitVarInsn(ALOAD, 0); ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); ctor.visitInsn(RETURN); ctor.visitMaxs(1, 1); ctor.visitEnd(); MethodVisitor getBaz = cw.visitMethod(ACC_PUBLIC, "getBaz", "(LFoo;)Ljava/lang/Object;", null, null); getBaz.visitCode(); getBaz.visitVarInsn(ALOAD, 1); getBaz.visitMethodInsn(INVOKESTATIC, "Foo", "access$000", "(LFoo;)Ljava/lang/Object;"); getBaz.visitInsn(ARETURN); getBaz.visitMaxs(1, 2); getBaz.visitEnd(); cw.visitEnd(); return cw.toByteArray(); } } 

这将创建一个名为Spy的简单类,允许您调用access$000

 public class Spy extends java.lang.Object{ public Spy(); public java.lang.Object getBaz(Foo); } 

使用此方法,您可以检查没有reflection的baz的值或任何暴露它的方法。

 public class Test { public static void main(String[] args) { Foo foo = new Foo(); Spy spy = new Spy(); System.out.println(spy.getBaz(foo)); } } 

Spy实现要求它与Foo位于同一个包中,并且Foo不在密封的JAR中 。

我很确定惩罚只不过是一个额外的方法调用。 换句话说,几乎与所有用例完全无关。

如果它处于特别热门的路径中,您可能会担心,但您应该使用分析器确定这实际上是您的问题。

我只是关闭警告。