5

我一直在玩这个,到目前为止,我还没有找到任何方法来隐藏或通过混淆层隐藏它的类型来欺骗instanceof返回false,但这并不意味着这是不可能的,因为我远离最了解 Java 的人。所以特地来请教专家。

我尝试了以下组合,在每种情况下,instanceof操作员都能够识别对象的真实/基本类型。

public class Test {

    public static void main(String[] args) {
        Object o = new TestObject();
        printType("Base Class", o);

        o = (TestSuperObject)(new TestObject());
        printType("Super Class", o);

        o = (TestInterface)(new TestObject());
        printType("Interface", o);

        o = (TestInterface)((TestSuperObject3)(new TestObject3()));
        printType("Interface on Super Class", o);

        o = (TestSuperObject3)((TestInterface)(new TestObject3()));
        printType("Super Class on Interface", o);
    }


    private static void printType(String testCase, Object o) {
        System.out.println(testCase);
        System.out.println("TestObject:" + (o instanceof TestObject));
        System.out.println("TestObject2:" + (o instanceof TestObject2));
        System.out.println("TestObject3:" + (o instanceof TestObject3));
        System.out.println();
    }

}

这些类被定义为...

public class TestObject extends TestSuperObject implements TestInterface
public class TestObject2 extends TestSuperObject implements TestInterface
public interface TestInterface
public class TestSuperObject
public class TestObject3 extends TestSuperObject3
public class TestSuperObject3 implements TestInterface

所以基本上,有没有办法隐藏这些信息或以某种方式丢失类型信息?我不问是因为我有这样做的理由,而是如果可能的话,我想知道它并在未来保持警惕。另外,我只是觉得它很有趣。

4

4 回答 4

4

有可能让自己与 JVM 混淆,instanceof但不会。

  • 同名但在不同包中的类是不一样的。这意味着你可以做

    // in one class
    ClassA classA = new ClassA(); // package1.ClassA
    another.test(classA);
    
    // calls in another class
    public void test(Object o) {
       if (o instanceof ClassA) // package2.ClassA => false 
    
  • 使用不同的类加载器,包o.getClass().getName()是相同的,但由于类加载器不同,instanceof返回 false。

  • 即使可以将对象分配给任何引用类型,该对象也是null并且始终是错误的。null instanceof ClassBnull
于 2012-10-16T14:16:38.780 回答
1

所以基本上,有没有办法隐藏这些信息或以某种方式丢失类型信息?

不,这是不可能的。

每个对象都有一个真实的类型,Java 的强+静态类型系统使得不可能改变一个对象的类型,或者假装它的实际类型与它的实际类型不同。


(假设有可能陷入本机代码并颠覆 Java 类型系统,但这样做的后果可能非常糟糕......崩溃 - JVM 糟糕。)

于 2012-10-16T14:04:22.523 回答
0

您可以通过混淆器运行代码。但这基本上是一个重命名。TestObject可以重命名为 eg A,但instanceof A仍然返回正确的结果。

顺便说一句:命名你的类 *Object 是一个坏主意(在面向对象的语言中)。

于 2012-10-16T14:27:29.480 回答
0

这取决于OP真正想要什么,但这可能会做到。

基本上我将课程设为私有。这意味着任何object instanceof Class代码都不会编译(在私有类的范围之外)。

于 2012-10-16T14:31:49.963 回答