大意失荊州啊-java基础之多态 代理
创始人
2025-05-28 02:05:51
0

遇到个java基础的bug,搞了许久,用了一个开源库,代码比较多,就赖得一点点看完整代码,结果是越懒越花时间,使用简单的代码模拟了一下,如下:

Animal.java

abstract class Animal {public static Animal getInstance() {return new Dog();}public void hello() {log("hello");}public abstract void log(String message);
}

Main.java

public class Main {public static void main(String[] args) {Animal.getInstance().hello();}
}

运行结果如下:

hello

很简单,就是输出一个字符串,于是我往Animal中增加另一个函数,如下:

Animal.java

abstract class Animal {public static Animal getInstance() {return new Dog();}public void hello() {log("hello");}public void world() {log("world");}public abstract void log(String message);
}

Main.java

public class Main {public static void main(String[] args) {Animal.getInstance().hello();Animal.getInstance().world();}
}

运行结果如下:

hello
Exception in thread "main" java.lang.RuntimeExceptionat com.company.Dog.log(Dog.java:14)at com.company.Animal.world(Animal.java:14)at com.company.Dog.world(Dog.java:3)at com.company.Main.main(Main.java:6)

如上结果,出了异常,理想的结果是输出一个hello和一个world,但是只输出了hello,当时我没太在意这个异常,就是很奇怪为什么我增加一个方法就不行,不都是同一个类中的方法吗?于是我打印一下类名,如下:

abstract class Animal {public static Animal getInstance() {return new Dog();}public void hello() {System.out.println("hello: " + getClass().getName());log("hello");}public void world() {System.out.println("world: " + getClass().getName());log("world");}public abstract void log(String message);
}

运行结果如下:

hello: com.company.Cat
hello
world: com.company.Dog
Exception in thread "main" java.lang.RuntimeExceptionat com.company.Dog.log(Dog.java:14)at com.company.Animal.world(Animal.java:16)at com.company.Dog.world(Dog.java:3)at com.company.Main.main(Main.java:6)

当时我就觉得是不是见鬼了,明明一个类上的两个方法,为什么打印的对象一个是猫一个是狗?

要解决这个问题还是得看完整代码,如下:

Animal.java

abstract class Animal {public static Animal getInstance() {return new Dog();}public void hello() {System.out.println("hello: " + getClass().getName());log("hello");}public void world() {System.out.println("world: " + getClass().getName());log("world");}public abstract void log(String message);
}

Cat.java

public class Cat extends Animal {@Overridepublic void log(String message) {System.out.println(message);}
}

Dog.java

public class Dog extends Animal {private Cat cat = new Cat();@Overridepublic void hello() {cat.hello();}@Overridepublic void log(String message) {throw new RuntimeException();}
}

Main.java

public class Main {public static void main(String[] args) {Animal.getInstance().hello();Animal.getInstance().world();}
}

这里就很完整了,Animal.getInstance()拿到的对象是Dog,在Dog中又创建了一个Cat对象。画一下内存图就可以很容易理解了,如下:

首先看Animal.getInstance().hello();的对象内存图,如下:
在这里插入图片描述

如上图,有些函数是继承自父类的,有些则覆盖父类的,可以看到调用的hello函数是Cat对象上的,所以就不难理解下面的输出结果了:

hello: com.company.Cat
hello

再来看Animal.getInstance().world();的对象内存图,如下:
在这里插入图片描述
如上图,可以看到调用的world函数是Dog对象上的,所以就不难理解下面的输出结果了:

world: com.company.Dog
Exception in thread "main" java.lang.RuntimeExceptionat com.company.Dog.log(Dog.java:14)at com.company.Animal.world(Animal.java:16)at com.company.Dog.world(Dog.java:3)at com.company.Main.main(Main.java:6)

所以总结起来就很简单了,Dog实际上是一个代理类,它没有实际的功能,实际的功能都在Cat类上,所以解决这个问题就很简单了,在Dog中覆盖world函数,并代理给Cat来执行,如下:

public class Dog extends Animal {private Cat cat = new Cat();@Overridepublic void hello() {cat.hello();}@Overridepublic void world() {cat.world();}@Overridepublic void log(String message) {throw new RuntimeException();}
}

运行结果如下:

hello: com.company.Cat
hello
world: com.company.Cat
world

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...