Java 类可以有自己类型的字段吗
我做了下面的事情,一段时间后,我发现了一个stackoverflow错误,我明白为什么会这样Java 类可以有自己类型的字段吗,java,oop,object,Java,Oop,Object,我做了下面的事情,一段时间后,我发现了一个stackoverflow错误,我明白为什么会这样 public class Cat { String name="default name"; Cat insideCat; public Cat(){ System.out.println("Cat constructor"); insideCat = new Cat(); } } 但是如果我不在构造函数中创建一个新的Cat对象,
public class Cat {
String name="default name";
Cat insideCat;
public Cat(){
System.out.println("Cat constructor");
insideCat = new Cat();
}
}
但是如果我不在构造函数中创建一个新的Cat对象,而是获取一个Cat类型的参数并将其分配给insideCat字段,该怎么办呢
public class Cat {
String name="default name";
Cat insideCat;
public Cat(Cat insideCat){
System.out.println("Cat constructor");
this.insideCat = insideCat;
}
}
我只是在玩弄代码,只是想找出Java能做什么和不能做什么。在第二段代码中,一切看起来都很正常,直到我开始测试这个类。我需要一个Cat对象来创建一个Cat对象(要创建这个Cat对象,我需要另一个Cat对象…它会继续)。所以技术上我不能测试这个类
所以我的问题是为什么java允许创建自己类型的实例变量?我猜构造函数的全部目的是初始化它的实例变量。所以要么我必须创建一个新对象来初始化insideCat,要么我必须从外部获取Cat对象。两者似乎都不起作用
我错过了什么。是否存在这样的情况:自身类型的实例变量可以变得有用,并且可以毫无问题地使用?提出这样的类是不是很糟糕的OOP实践 这样的类一直存在 考虑链表或树,例如:
class ListNode {
ListNode next;
// Etc.
}
class TreeNode {
TreeNode left;
TreeNode right;
// Etc.
}
您不会在构造函数中初始化“子”对象,而是在以后添加它们
在您的示例中,您需要有一个稍后创建
insideCat
的方法。一般来说,您不会创建具有完全相同状态的子对象,在构建时会有一些区别,在这种情况下,您可能会遇到“哦,上帝,现在停止创建这些对象”的情况,或者在添加它们时,例如。,您可以通过方法而不是构造函数来添加它们。拥有同一类的实例成员没有什么错。
员工有经理,经理也是员工
public class Employee{
private Employee manager;
//getters setters and constructor
}
有许多自引用数据结构的示例是有效的。想象一个
链接列表
。每个LinkNode
都有一个数据字段和指向下一个LinkNode
的指针
class LinkNode {
int data;
LinkNode nextLink;
public LinkNode(int d1) {
data = d1;
nextLink = null;
}
...
}
class LinkedList {
private LinkNode first;
...
}
您的StackOverflow
问题源于这样一个事实:创建一个而不是X
需要无限地创建另一个X,
想想你的
Cat
示例。为什么实例化一个Cat需要所有的东西…另一个Cat
可以有多个构造函数。因此,您可以有另一个构造函数
public Cat(){...}
这将允许您创建一个内部猫。之后,您可以创建另一个包含内部Cat的Cat。显然,根据您的需要,这里的设计可能不太好。Dave Newton关于链表的回答是这种用法的一个很好的现实例子。如何实现双链表?有一个相同类型的字段是可以的,但子对象的创建必须以某种方式停止。您的子对象是无条件创建的。您可以通过将
null
传递到第一个Cat(…)
构造函数来轻松测试此类。然后,如果愿意,您可以提供一种方法,稍后将其他内容分配给insideCat
。实例化cat确实需要其他cat;)然而,这里的例子是从生物学上倒退过来的,并且假设出生时有一只新生猫。我不同意。你可以有一个名为“consumate”的方法返回对新猫的引用…但它不必发生在幼猫的构造函数中。确切地说:怀孕前的猫没有任何意义。我明白了-我们在这里原则上同意构造函数。我知道我的类在现实生活中没有意义。我只是想要一个例子,并随机将其命名为“Cat”。我读到构造函数的全部目的是初始化其实例变量,所以我不是通过在新方法中初始化这些特殊字段来打破这一点吗?@DesirePRG一个构造函数的“全部目的”是构造一个对象。实例变量在构造期间可能不处于最终状态。在列表示例中,next
值在添加到列表中之前可能不存在。列表本身将负责查找最后一个列表节点,将其next
设置为新列表项,等等。在这种情况下,ListNode
需要做的就是将next
设置为null
或null对象。好吧,如果我说,构造函数可以初始化所选的一组实例变量,并将其余字段保持为null(假设只有对象字段),直到初始化这些字段才有意义!关于构造函数,抽象类仍然可以有构造函数,但不能构造对象。那么,我们可以说构造函数的目的是构造一个对象吗?@DesirePRG-Yes;ctor只会初始化它需要初始化的内容。我认为说“构造函数的目的是构造一个对象”是。。。显而易见。抽象类必须扩展才能使用;抽象类的构造函数仍然可以用于构造子类实例。除非扩展抽象类的ctor,否则不能使用它:它的目的仍然是构造一个类;这样做需要额外的语义,这似乎无关紧要。@DaveNewton我不明白为什么我想不出你在答案中提供的例子:)显然是我这边的反对票