在其自己的类中实例化对象

huangapple go评论82阅读模式
英文:

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(&quot;abc&quot;);
	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(&quot;&quot;);
		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(&quot;abc&quot;);

答案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(&quot;abc&quot;);
    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(&quot;abc&quot;);
        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,你也会实例化它的两个成员,obj1obj2。这些成员本身都是ConstructorClass,因此它们每个都有obj1obj2成员,这些成员也会被实例化,依此类推,直到出现StackOverflowError错误。

我不太清楚为什么你有这两个成员(即我看不到它们的要求),但如果你真的需要它们,你应该将它们放在一些不同的上下文中(例如,作为static成员,在某个方法中作为局部变量等)。

英文:

Whenever you instantiate a ConstructorClass, you also instantiate its two members, obj1 and obj2. These members are themselves ConstructorClasses, 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("");
    }
}

注意:

如果想要在您的类中实现封装,请确保为变量 strinteger 编写 getter 和 setter 方法。

英文:

Your getting stackoverflow error because of creating below two object at class level itself:

public ConstructorClass obj1= new ConstructorClass(&quot;abc&quot;);
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(&quot;&quot;);
        obj.str= new ConstructorClass(&quot;abc&quot;).str;
        return obj;
    }

    public ConstructorClass getObj2() {
        return new ConstructorClass(1); 
    }
    
} 

class ConstructorExample{
	public static void main(String[] args) {
    	new ConstructorClass(&quot;&quot;);
    }
}

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(&quot;abc&quot;);
      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(&quot;string&quot;);

Now 1st constructor will be used. Then instance field will be created. Instance field creation also calls constructor. Constructor will again createnter code heree 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

这是修复后的代码,已经实现了以下更改:

  1. 从 ConstructorClass 中删除循环调用(对象的方法尝试实例化自身)

  2. 在 ConstructorClass 中引入 setInteger()setString() 方法,用于设置其私有数据成员的值。

  3. 在 MainClass 中实例化 ConstructorClass 对象。

  4. 从 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:

  1. Remove the cyclic calls from ConstructorClass
    (An object's method trying to instantiate itself)

  2. Introduce setInteger() and setString() methods in ConstructorClass to set the values of its private data members.

  3. Instantiate the ConstructorClass objects from MainClass

  4. 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(&quot;abc&quot;);
obj2 = new ConstructorClass(1);
}
public ConstructorClass getObj1() {
ConstructorClass obj = new ConstructorClass(&quot;&quot;);
obj.setInteger(100);
obj.setString(&quot;Hello! How are you doing?&quot;);
return obj;
}
public ConstructorClass getObj2() {
return obj2;
}
public static void main(String[] args) {
MainClass mc = new MainClass();
System.out.println(&quot;obj1 - integer = &quot; + mc.getObj1().getInteger());
System.out.println(&quot;obj1 - string = &quot; + mc.getObj1().getString());
System.out.println(&quot;obj2 - integer = &quot; + mc.getObj2().getInteger());
System.out.println(&quot;obj2 - string = &quot; + mc.getObj2().getString());
}
}

Output:

&gt; javac MainClass.java
&gt; java MainClass
obj1 - integer = 100
obj1 - string = Hello! How are you doing?
obj2 - integer = 1
obj2 - string = null

huangapple
  • 本文由 发表于 2020年4月10日 18:46:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/61138685.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定