轮“套娃”的实力,还是应该数得上那群“种花家”的“流氓兔”,钓上来“鹰酱”,实现三个愿望,“我要小钱钱和小钱钱、然后再来三个愿望”。典型的“耍流氓”,不过对于“鹰酱”这样的真正的流氓,耍一耍真倒也没什么。
那兔“流氓”套娃
这里探讨一下 Java 中的“套娃”
1、最基本的“套娃”:在一个类中的成员变量实例化该类
第一种情况:“套娃”导致java.lang.StackOverflowError
public class TaoWa {
private String name;
private String country;
private TaoWa taoWa = new TaoWa("流氓兔", "种花家");
public TaoWa() {}
public TaoWa(String name, String country) {
this.name = name;
this.country = country;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
public class Main {
public static void main(String[] args) {
TaoWa taoWa = new TaoWa("鹰酱", "美利坚");
}
}
在类TaoWa中我们new出了一个TaoWa,来自“种花家”的“流氓兔”,但是在Main真正执行的时候,我们是new了一个“美利坚鹰酱”的TaoWa对象。可能凭空想是想不明白,那么画图来告诉说明为什么“套娃”最后引发了StackOverflowError。
一个类中普通成员变量实例化该类对象“套娃”
从上面的图就能比较明显看出,在堆中会有不断有新的“流氓兔”出现,无限进行下去,最终导致 Stack Overflow 。
第二种情况:“套娃”有讲究
在上面的例子中,我们见识到了“套娃”的“疯狂”,但是,并不是说 Java 不允许我们“套娃”,因为“套娃”这种东西是有用的,尤其在一些考虑到安全的问题,比如实现“单例”等场景。
既然允许“套娃”,那么应该怎么处理?
用static关键字修饰那个实例化本类对象的成员变量。
public class TaoWa {
private String name;
private String country;
private static TaoWa taoWa = new TaoWa("流氓兔", "种花家");
public TaoWa() {}
public TaoWa(String name, String country) {
this.name = name;
this.country = country;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public static TaoWa getTaoWa() {
return taoWa;
}
@Override
public String toString() {
return "TaoWa{" +
"name='" + name + '\'' +
", country='" + country + '\'' +
'}';
}
}
public class Main {
public static void main(String[] args) {
TaoWa taoWa = new TaoWa("鹰酱", "美利坚");
System.out.println(taoWa.getTaoWa());
}
}
输出:
TaoWa{name='流氓兔', country='种花家'}
同样,用图的方法说一说为什么这样“套娃”是可以的。
一个类中成员变量实例化该类对象“套娃”
一旦把实例化本类对象的成员变量用static修饰,那么它属于类层级而不是属于对象层级,在这种情况下,虽然从代码上看起来我们进行了“套娃”,但是实际上在内存中,并没有同第一种情况那样“无限”的“流氓兔”出现,所以这样的情况下,是不会引发 Stack Overflow 的。
总结:
这里的“套娃”是指代码上所体现的一种形式,就是“一个类中的成员变量去实例化该类”,给人一层套一层的感觉,但是在内存中的体现,并不一定是给人“套娃”的感觉。