java对于具有私有构造函数的类,instanceof如何返回true?
这是本书中的一个问题:https://www.cl.cam.ac.uk/teaching/0506/ConcSys/cs_a-2005.pdf第28页
Can you write an additional Java class which creates an object that, when passed to the test method causes it to print “Here!”? As I say in the code, editing the class A itself, or using library features like reflection, serialization, or native methods are considered cheating! I’ll provide some hints in lectures if nobody can spot it in a week or so. None of the PhD students has got it yet.
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof A) {
System.out.println("Here!");
}
}
}
我知道这个问题很不清楚。我可以想出许多不同的“黑客”解决方案,但不确定它们是否会被视为“作弊”:
我找不到正式答案,所以问你什么是好答案
# 1 楼答案
不知怎么的,我不喜欢这种问题。它来自2005年的一次演讲,根据WebSearchs,似乎到目前为止还没有人找到“解决方案”,也没有发表任何解决方案
约束条件是明确的,但什么是允许的还是不允许的问题有些模糊。每一种解决方案都可能被认为是“作弊”,因为带有私有构造函数的类不应该被子类化。这是一个关键的安全机制,负责任的工程师正在努力确保这个安全机制不能被轻易规避
当然,为了解决这个问题,你必须作弊
尽管如此,我还是花了很长一段时间研究这个问题,下面是我最终如何欺骗它的:
1.)下载Apache Bytecode Engineering Library,并将
bcel-6.0.jar
放在一个目录中2.)在同一目录中创建一个文件
CreateB.java
,包含以下内容:3.)编译并执行这个类:
(注意:在linux上,
;
必须是:
)。结果将是一个文件B.class
4.)将问题中给出的类(逐字复制-无任何修改)复制到同一目录中并编译
5.)在同一目录中创建以下类,并对其进行编译:
6.)关键的一步:打电话
输出将是
Here!
关键的一点是
CreateB
类创建了一个扩展A
的B
类,但不调用超级构造函数。(请注意,隐式超级构造函数调用通常由编译器添加。但这里不涉及编译器。字节码是手动创建的)。当类被加载时,所有这些通常都会在VerifyError
时失败,但是这个验证可以通过-Xverify:none
关闭总之:
# 2 楼答案
这里有几个选项:
创建一个类:
然后编辑字节码并删除对X的调用。。当然,这违反了JVM规范,必须使用
-Xverify:none
运行,如上所述。这基本上与@Marco13相同选项2:
编译代码并通过将类路径放入sysloader来运行它(否则它将不起作用):
$ java -Xbootclasspath/p:. Y
当然,他们都在作弊。第一种选择不是Java。第二个是邪恶:)
如果我找到另一种方法,我会发布:)
无论如何,这都离不开低级技巧。JVM规范明确禁止在不调用构造函数的情况下创建对象,因为堆栈中的对象未初始化。JVM规范明确禁止不调用超级构造函数。JVM规范明确要求验证访问保护
不过还是很有趣:)
# 3 楼答案
Java可以支持unicode类名:)
“if(o instanceof A)”中的A可能不同于“public class A”中的A
例如,下面的代码将打印“Here!”而不是“坏”
A.java
А。爪哇
梅因。爪哇
# 4 楼答案
如果我们认为嵌套类A不“修改它”(从技术上说,所有代码行都是完整的),那么这个解决方案可能是唯一有效的选项:
我的意思是,从技术上讲,它遵循所有规则:
Can you write an additional Java class which creates an object that, when passed to the test method causes it to print “Here!”?
-完成As I say in the code, editing the class A itself ... considered cheating!
-从技术上讲,该课程未经编辑。我把它复制粘贴到我的代码中李>... or using library features like reflection, serialization, or native methods are considered cheating!
-完成但是,如果您决定不允许嵌套类
A
,那么我认为,根据当前的定义,这个问题没有合适的解决方案。此外,考虑到书中给出了这个任务的部分,我敢打赌作者想让构造函数protected
而不是private