继承类并重写父类方法
2025年09月21日
继承类并重写父类方法
与创建类并实现接口相似,继承类并重写父类的方法,只需要在调用类访问器的visit方法时,指定该类所继承的父类,重写父类的方法就是使用visitMethod方法为该类添加一个访问标志与父类中的方法相同、方法名称与方法描述符都相同的方法。与实现接口不同的是,我们可以在重写的方法中调用父类的方法。
以继承BaseClass为例,BaseClass类如下。
public class BaseClass { public void sayHello() { System.out.println("BaseClass sayHello"); } }
现在我们使用ClassWriter创建一个新的类,类名为SubClass,并指定该类继承BaseClass类。然后重写父类的sayHello方法,在子类的sayHello方法中,先调用父类的sayHello方法,再输出“SubClass sayHello”字符串。如代码清单5-17所示。
代码清单5-17 使用ClassWriter创建SubClass类
public class UseAsmOverrideMethod { public static void main(String[] args) throws IOException { // 创建的类的类名 String subClassName = BaseClass.class.getName() .replace("Base", "Sub"); ClassWriter cw = new ClassWriter(0); // 设置class文件结构的版本号、类名、类签名、父类、实现的接口 cw.visit(Opcodes.V1_8, ACC_PUBLIC, subClassName.replace(".", "/"), null, Type.getInternalName(BaseClass.class), null); // 生成初始化方法 // generateInitMethod(cw); // 创建sayHello方法 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "sayHello", "()V", null, null); // 调用父类的方法 mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(BaseClass.class), "sayHello", "()V", false); // 插入输出"SubClass sayHello"的字节码指令 mv.visitFieldInsn(GETSTATIC, Type.getInternalName(System.class), "out", Type.getDescriptor(System.out.getClass())); mv.visitLdcInsn("SubClass sayHello"); mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(System.out.getClass()), "println", "(Ljava/lang/String;)V", false); mv.visitInsn(RETURN); // 设置局部变量表和操作数栈的大小 mv.visitMaxs(2, 1); // 获取生成的类的字节数组 byte[] byteCode = cw.toByteArray(); // 保存到文件 ByteCodeUtils.savaToFile(subClassName, byteCode); } }
注意:为了简化代码,省去了为类生成方法的代码,所以生成的这个SubClass类是不能被加载使用的。
运行代码清单5-17的代码,我们将得到一个SubClass类。SubClass类如图5.8所示。

图5.8 SubClass类