英文:
Instantiating Objects in its own Class
问题
这是我在这里的第一个问题。我是一名计算机工程专业的学生,我们的老师给了我们一些要解决的问题。
他基本上要求我们创建2个 类
;其中一个应该包含2个重载的 构造函数
,以及一些关于 数据封装
的方法;另一个应该是 主类
。我们的任务是从主类中使用那个类的方法来“控制
”第一个类。他还提到,我们应该在这些类之间传递一些原始
和引用类型
变量的值。我写了一些代码,但是在初始化具有构造函数的类时,我遇到了**堆栈溢出错误
**。据我所知,当进行递归时,会出现这个错误,但我不明白我在哪里出现了递归。
下面是我编写的构造函数类(对不起,我的命名不好,但由于这只是作业,我没有考虑命名):
public class ConstructorClass {
//字段
private String str;
private int integer;
//构造函数
public ConstructorClass(String a) {
str= a;
}
public ConstructorClass(int a) {
integer= a;
}
//对象
public ConstructorClass obj1= new ConstructorClass("abc");
public ConstructorClass obj2= new ConstructorClass(1);
//方法
public int getInteger() {
return this.integer;
}
public String getString() {
return this.str;
}
public ConstructorClass getObj1() {
ConstructorClass obj= new ConstructorClass("");
obj.str= obj1.str;
return obj;
}
public ConstructorClass getObj2() {
return obj2;
}
}
编辑:这是我遇到的错误:
> Exception in thread "main" java.lang.StackOverflowError at
> ConstructorClass.<init>(ConstructorClass.java:19)
第19行是:
public ConstructorClass obj1= new ConstructorClass("abc");
英文:
This is my first question here. I am a comp. Eng. student and our teacher gave us some problems to work on.
He basically asked us to create 2 classes
; one of which should contain 2 overloaded constructors
and some methods regarding data encapsulation
, and the other should be the main class
. Our job is to "control
" the first class from the main class using methods from that class. He also mentioned that we should pass values of some primitive
and reference type variables between classes. I wrote some piece of code, but i get a StackOverflow Error
during the class that has constructors in it is initializing. To my knowledge, you get this error when you do a recursion, but I don't get where I am doing it.
Here's the constructor class I coded (sorry for my bad naming, but since its just homework I didn't think on my names):
public class ConstructorClass {
//Fields
private String str;
private int integer;
//Constructors
public ConstructorClass(String a) {
str= a;
}
public ConstructorClass(int a) {
integer= a;
}
//Objects
public ConstructorClass obj1= new ConstructorClass("abc");
public ConstructorClass obj2= new ConstructorClass(1);
//Methods
public int getInteger() {
return this.integer;
}
public String getString() {
return this.str;
}
public ConstructorClass getObj1() {
ConstructorClass obj= new ConstructorClass("");
obj.str= obj1.str;
return obj;
}
public ConstructorClass getObj2() {
return obj2;
}
}
Edit: This is the error I am getting:
> Exception in thread "main" java.lang.StackOverflowError at
> ConstructorClass.<init>(ConstructorClass.java:19)
Line 19 is :
public ConstructorClass obj1= new ConstructorClass("abc");
答案1
得分: 2
你之所以得到这个结果,是因为基本上你有以下内容:
public class ConstructorClass {
// 对象
public ConstructorClass obj1 = new ConstructorClass("abc");
public ConstructorClass obj2 = new ConstructorClass(1);
}
这是一种隐藏的递归形式。
这大致相当于编写:
public class ConstructorClass {
public ConstructorClass(int a) {
public ConstructorClass obj1 = new ConstructorClass("abc");
public ConstructorClass obj2 = new ConstructorClass(1);
...
}
...
}
即从每个构造函数中调用构造函数。
还请参阅官方 Java 初始化字段教程 - 尽管在这里没有明确提到,但它关于“实例初始化块”的内容也适用于使用最终方法来初始化实例字段,这正是你在这里所做的:
Java 编译器会将初始化块复制到每个构造函数中。
详细信息在JLS 14,第8.3.2节“字段初始化”中有规定:
如果声明符是实例变量(即非静态字段),则以下规则适用于其初始化程序:
- [...]
- 在运行时,将计算初始化程序并在创建类的每个实例时执行赋值(§12.5)。
英文:
You get this because you've basically got the following:
public class ConstructorClass {
//Objects
public ConstructorClass obj1= new ConstructorClass("abc");
public ConstructorClass obj2= new ConstructorClass(1);
}
This is a hidden form of recursion.
It is roughly equivalent to writing
public class ConstructorClass {
public ConstructorClass(int a) {
public ConstructorClass obj1= new ConstructorClass("abc");
public ConstructorClass obj2= new ConstructorClass(1);
...
}
...
}
i.e. invoking the constructor from every constructor.
Also see the official java tutorial on initializing fields - although this is not explicitly mentioned there, what it says about "instance initializer blocks" also applies to using a final method to initialize an instance field, which is what you did here:
> The Java compiler copies initializer blocks into every constructor.
The details are specified in JLS 14, Chapter 8.3.2. Field Initialization :
> If the declarator is for an instance variable (that is, a field that is not static), then the following rules apply to its initializer:
<ul>
<li> [...]
<li> At run time, the initializer is evaluated and the assignment performed each time an instance of the class is created (§12.5).
答案2
得分: 0
每当你实例化一个ConstructorClass
,你也会实例化它的两个成员,obj1
和obj2
。这些成员本身都是ConstructorClass
,因此它们每个都有obj1
和obj2
成员,这些成员也会被实例化,依此类推,直到出现StackOverflowError
错误。
我不太清楚为什么你有这两个成员(即我看不到它们的要求),但如果你真的需要它们,你应该将它们放在一些不同的上下文中(例如,作为static
成员,在某个方法中作为局部变量等)。
英文:
Whenever you instantiate a ConstructorClass
, you also instantiate its two members, obj1
and obj2
. These members are themselves ConstructorClass
es, so they each have obj1
and obj2
members which also get instantiated, and so on, until you fail with a StackOverflowError
.
I'm not sure why you have these two members (i.e., I can't see a requirement for them), but if you really need to have them, you should have them in some different context (e.g., as static
members, as local variables in some method, etc.)
答案3
得分: 0
因为在类级别上创建了以下两个对象,所以您的代码出现了堆栈溢出错误:
public ConstructorClass obj1 = new ConstructorClass("abc");
public ConstructorClass obj2 = new ConstructorClass(1);
以下代码可能适用于您:
public class ConstructorClass {
// 字段
private String str;
private int integer;
// 构造方法
public ConstructorClass(String a) {
str = a;
}
public ConstructorClass(int a) {
integer = a;
}
// 方法
public int getInteger() {
return this.integer;
}
public String getString() {
return this.str;
}
public ConstructorClass getObj1() {
ConstructorClass obj = new ConstructorClass("");
obj.str = new ConstructorClass("abc").str;
return obj;
}
public ConstructorClass getObj2() {
return new ConstructorClass(1);
}
}
class ConstructorExample {
public static void main(String[] args) {
new ConstructorClass("");
}
}
注意:
如果想要在您的类中实现封装,请确保为变量 str
和 integer
编写 getter 和 setter 方法。
英文:
Your getting stackoverflow error because of creating below two object at class level itself:
public ConstructorClass obj1= new ConstructorClass("abc");
public ConstructorClass obj2= new ConstructorClass(1);
Following code might work for you:
public class ConstructorClass {
//Fields
private String str;
private int integer;
//Constructors
public ConstructorClass(String a) {
str= a;
}
public ConstructorClass(int a) {
integer= a;
}
//Methods
public int getInteger() {
return this.integer;
}
public String getString() {
return this.str;
}
public ConstructorClass getObj1() {
ConstructorClass obj= new ConstructorClass("");
obj.str= new ConstructorClass("abc").str;
return obj;
}
public ConstructorClass getObj2() {
return new ConstructorClass(1);
}
}
class ConstructorExample{
public static void main(String[] args) {
new ConstructorClass("");
}
}
Note:
If want to achieve encapsulation in your class make sure you have getter and setter methods for variable str
and integer
答案4
得分: 0
Stackoverflow is coming as class is getting instantiated recursively partially due to these lines
//Objects
public ConstructorClass obj1= new ConstructorClass("abc");
public ConstructorClass obj2= new ConstructorClass(1);
Remove above two lines issue will gone. You will get 1 compile issue which should be easy to solve.
What's happening internally is, Suppose from your main class you tried to create an object of this class using
ConstructorClass cc = new ConstructorClass("string");
Now the first constructor will be used. Then the instance field will be created. Instance field creation also calls the constructor. The constructor will again create an instance field. And this loop keeps on going, which causes issues.
You need to learn how classes get loaded and in what order they get created. If you tried to use an instance block or static block, it would add more complexity/learning for you.
英文:
Stackoverflow is coming as class is getting instantiated recursively partially due to these lines
//Objects
public ConstructorClass obj1= new ConstructorClass("abc");
public ConstructorClass obj2= new ConstructorClass(1);
Remove above two lines issue will gone. You will get 1 compile issue which should be easy to solve.
What's happening internally is, Suppose from ur main class you tried to create object of this class using
ConstructorClass cc = new ConstructorClass("string");
Now 1st constructor will be used. Then instance field will be created. Instance field creation also calls constructor. Constructor will again createnter code here
e instance field. And this loops keeps on going which causes issues.
U need to learn how classes get loaded and in what order it gets created. If u tried to use instance block or static block it would add more complexity/learning for you.
答案5
得分: 0
这是修复后的代码,已经实现了以下更改:
-
从 ConstructorClass 中删除循环调用(对象的方法尝试实例化自身)
-
在 ConstructorClass 中引入 setInteger() 和 setString() 方法,用于设置其私有数据成员的值。
-
在 MainClass 中实例化 ConstructorClass 对象。
-
从 MainClass 中调用 ConstructorClass 的 setInteger() 和 setString() 方法。
修复后的代码:
// 文件名: MainClass.java
class ConstructorClass {
// 字段
private String str;
private int integer;
// 构造函数
public ConstructorClass(String a) {
str = a;
}
public ConstructorClass(int a) {
integer = a;
}
// 方法
public int getInteger() {
return this.integer;
}
public String getString() {
return this.str;
}
public void setInteger(int a) {
integer = a;
}
public void setString(String a) {
str = a;
}
}
public class MainClass {
// 对象
ConstructorClass obj1;
ConstructorClass obj2;
public MainClass() {
obj1 = new ConstructorClass("abc");
obj2 = new ConstructorClass(1);
}
public ConstructorClass getObj1() {
ConstructorClass obj = new ConstructorClass("");
obj.setInteger(100);
obj.setString("Hello! How are you doing?");
return obj;
}
public ConstructorClass getObj2() {
return obj2;
}
public static void main(String[] args) {
MainClass mc = new MainClass();
System.out.println("obj1 - integer = " + mc.getObj1().getInteger());
System.out.println("obj1 - string = " + mc.getObj1().getString());
System.out.println("obj2 - integer = " + mc.getObj2().getInteger());
System.out.println("obj2 - string = " + mc.getObj2().getString());
}
}
输出:
> javac MainClass.java
> java MainClass
obj1 - integer = 100
obj1 - string = Hello! How are you doing?
obj2 - integer = 1
obj2 - string = null
英文:
Here is the fixed code, with the following changes implemented:
-
Remove the cyclic calls from ConstructorClass
(An object's method trying to instantiate itself) -
Introduce setInteger() and setString() methods in ConstructorClass to set the values of its private data members.
-
Instantiate the ConstructorClass objects from MainClass
-
Call the setInteger() and setString() methods of ConstructorClass from MainClass
Working code:
// File name: MainClass.java
class ConstructorClass {
//Fields
private String str;
private int integer;
//Constructors
public ConstructorClass(String a) {
str = a;
}
public ConstructorClass(int a) {
integer = a;
}
//Methods
public int getInteger() {
return this.integer;
}
public String getString() {
return this.str;
}
public void setInteger(int a) {
integer = a;
}
public void setString(String a) {
str = a;
}
}
public class MainClass {
//Objects
ConstructorClass obj1;
ConstructorClass obj2;
public MainClass() {
obj1 = new ConstructorClass("abc");
obj2 = new ConstructorClass(1);
}
public ConstructorClass getObj1() {
ConstructorClass obj = new ConstructorClass("");
obj.setInteger(100);
obj.setString("Hello! How are you doing?");
return obj;
}
public ConstructorClass getObj2() {
return obj2;
}
public static void main(String[] args) {
MainClass mc = new MainClass();
System.out.println("obj1 - integer = " + mc.getObj1().getInteger());
System.out.println("obj1 - string = " + mc.getObj1().getString());
System.out.println("obj2 - integer = " + mc.getObj2().getInteger());
System.out.println("obj2 - string = " + mc.getObj2().getString());
}
}
Output:
> javac MainClass.java
> java MainClass
obj1 - integer = 100
obj1 - string = Hello! How are you doing?
obj2 - integer = 1
obj2 - string = null
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论