题目比较绕。以下用一个简单的例子说明:
public class A
{
@Override
public String toString()
{
return "A";
}
public static void main(String[] args)
{
A a = new A();
B b = new B();
System.out.println(a.toString());
System.out.println(b.toString());
}
}
class B
{
}
执行之后效果如下:
A
B@c17164
代码中,A的toString方法重写(override)了Object类的原始方法。
现在希望能够有方案对A对象调用Object类的toString方法从而获得A的索引值(reference)。
尝试一,反射,失败。
import java.lang.reflect.Method;
public class A
{
public String toString()
{
return "A";
}
public static void main(String[] args) throws Exception
{
A a = new A();
Method m = Object.class.getMethod("toString");
System.out.println(m.invoke(a));
}
}
尝试二,研究super关键字的用法,发现没有类似于
a.super.toString()这样的写法,失败。
从而得出基本结论,采用编写代码的方式很难达到效果。
不过以下方法绕过了代码的语法规则和编译器的检查。可以达到要求的效果:
- 把编写好的Java代码通过编译器生成类文件。
- 使用Java ByteCode Editor打开生成的类文件。
- 找到 invokevirtual A/toString()Ljava/lang/String;
- 修改为 invokespecial java/lang/Object/toString()Ljava/lang/String;
- 保存,执行,检查效果。
A@11b86e7
invokespecial这个OpCode只有在以下三种情况下才能写出来:
- 生成某个类的实例对象。
- 在类的内部调用超类方法。
- 在类的内部调用私有方法。
因此如果不是手动修改ByteCode,似乎没什么办法实现以上的需求。
分享到:
相关推荐
* 在子类中使用关键字super可以调用被子类覆盖的父类中的方法。 异常处理 * 在Java语言中,通常把可能发生异常的代码放到try块中,并用紧跟其后的catch块来捕获和处理异常。 抽象类和接口 * 抽象方法是一种仅有...
5. final关键字:final修饰的类不能被继承,final修饰的方法不能被子类覆盖。final还可以修饰变量,使其成为常量。 6. 构造方法:子类在实例化时,其构造方法会调用父类的构造方法,这是通过super关键字实现的。 7...
继承中的构造方法在子类的构造方法的第一行代码如果没有调用父类的构造或者没有调用子类的其他构造,则默认调用父类无参构造。super关键字的用法有三种:1. 在子类的成员方法中,访问父类的成员变量。2. 在子类的...
内部类可以直接访问外部类的所有成员,包括私有成员,而外部类访问内部类的成员则需要创建内部类对象。内部类可以使用不同的访问修饰符,包括默认修饰符、public、private、protected等。 以上是对Java基础知识点的...
4. **多态性与方法的重载、覆盖**:多态性允许一个接口有多种实现,方法重载是在同一类中定义多个同名但参数不同的方法,而方法覆盖发生在子类中,子类重写父类的方法。重载是编译时多态,覆盖是运行时多态。 5. **...
修饰方法时,方法不能被子类覆盖;修饰类时,类不能被继承。 `instanceof`运算符用来检查一个对象是否属于某个类或其子类,这对于多态场景下的类型判断非常有用。 总结来说,Java类的特性是面向对象编程的重要组成...
当final用于方法时,这个方法不能被子类覆盖。当final用于变量时,如果是基本数据类型,变量值不可更改;如果是引用类型,则引用本身不可更改,但引用所指向的对象内容可以修改。 super和this关键字在Java中用于...
`private`方法不能被子类重写,因为它们对外部类是不可见的。 5. **内部类的引用**: 内部类的对象包含对外部类对象的引用,可以通过`OuterClassName.this`引用外部类对象,而`InnerClassName.this`则表示内部类...
方法覆盖通常发生在子类需要扩展或修改父类功能时。子类中的覆盖方法必须与父类中被覆盖的方法有相同的名称、参数列表和访问修饰符。返回类型可以不同,但不推荐这样设计,因为这并不构成方法的重载。 7. **构造...
在处理对象时,打印对象通常会调用toString方法,该方法在Object类中定义,但可以被子类覆盖以返回对象的字符串表示。在Java中,比较对象相等性通常使用equals方法而不是==运算符,后者比较的是引用是否指向同一对象...
final修饰的参数对于基本类型的参数无太大意义,但对于引用类型参数来说,可以防止在方法内部被重新指向。 关键字static用于定义类级别成员,比如静态变量和静态方法。这些成员属于类本身,而不是类的实例。静态...
这保证了在多态环境中调用该方法时,总是执行父类中的特定实现。例如,`Object`类的`equals()`和`hashCode()`方法被声明为`final`,以确保所有类都遵循统一的比较和哈希计算规则。 然后是`final`变量。`final`变量...
- 父类的公共属性和方法会被子类继承,私有属性和方法则不会。 - 子类可以添加自己的属性和方法,同时可以覆盖父类的方法。 - 尊重封装原则,避免直接访问或修改私有属性和方法,以维护代码的稳定性和安全性。 ...
当应用于方法时,表示该方法不能被子类覆盖;当应用于类时,表示该类不能被继承。 ### 内部类 内部类是在另一个类内部定义的类。它可以访问外部类的成员,包括私有成员。内部类分为成员内部类、局部内部类、匿名...
在方法或类中使用final,还可以防止方法被子类重写或类被继承。 在面向对象编程中,这三个核心特性——封装、继承和多态,以及控制符和final关键字等,共同构成了面向对象程序设计的基石,使得程序设计更加模块化、...
- 当一个类有很多子类,并且这些子类都重写了父类的某个方法时,子类对象的上转型对象在调用这个方法时就可能表现出不同的行为,这就是多态性。 #### 抽象abstract - **抽象类**:不能直接实例化,主要用于定义一...
`final`类不能被继承,`final`方法不能被子类覆盖,而`final`变量一旦赋值后就不能被改变。 - **abstract修饰符**:`abstract`修饰符用于声明抽象类和抽象方法。抽象类不能实例化,只能被继承,而抽象方法只有声明...
- **方法锁定**:使用`final`修饰的方法不能被继承类覆盖或重新定义。这样做有两个目的:一是锁定方法的行为,防止子类改变其实现;二是确保继承结构中的方法行为一致,不会被覆盖。需要注意的是,类中的所有`...
对于方法,不能被子类覆盖;对于类,不能被继承。 ### 总结 面向对象高级特性是Java编程的重要组成部分,掌握这些概念对于开发高质量的软件至关重要。类的继承、接口、多态、Java中的包、包装类、内部类以及访问...