[英]When is it OK to create object of a class inside a method of that class?
public class TestClass(){
public static void main(String []args) {
TestClass t1 = new TestClass();
t1.anything();
}
}
在同一個 class 的定義中創建一個 object 是不是很奇怪? 因為然后作為響應 - 這個 object 創建了一個新的 object,然后這個新的 object 創建了另一個,並且無限循環開始直到 ZCD2997BF4957F0608 滿為止。
在同一個類的定義中創建一個對象而不是響應對象創建一個新對象然后這個新對象創建另一個對象並開始無限循環並不奇怪
不,main 方法只在您運行程序時運行一次。 它不會再次執行。 因此,該對象將只創建一次。
想想你的主要方法是在你的班級之外。 它創建您的類的一個實例,並使用創建的實例。 因此,當您從main
方法創建實例時,會調用構造函數來初始化實例的狀態,然后當構造函數返回時,將執行 main 方法的下一條語句。
實際上,您可以認為main
方法不是類實例狀態的一部分。
但是,如果您在構造函數中創建了類的實例(比如 0-arg),並將引用作為實例引用變量,那么這將變成無限遞歸。
public class A {
private A obj;
public A() {
obj = new A(); // This will become recursive creation of object.
// Thus resulting in StackOverflow
}
}
如果您嘗試執行以下操作,則只會出現無限循環(堆棧溢出錯誤):
public class TestClass {
public TestClass() {
TestClass t = new TestClass();
}
}
在其他地方,您嘗試創建TestClass
類的對象。
public class TestClass{
public static void main(String []args) {
TestClass t1 = new TestClass();
t1.anything();
}
}
這是一個完全有效的代碼。 當調用main
方法時,不存在TestClass
先前實例(不需要,因為main
方法是static
)。
public class Test2{
public Test2 clone(){
return new Test2();
}
}
這也是完全有效的。 當您創建 Test2 的新實例時,它包含clone
方法,但該方法不會自動執行。 只有在調用clone
方法時,才會再創建一個 Test2 實例。
public class MyLinkedList{
MyLinkedList next;
MyLinkedList(int elems){
if(elems>0){
next = new MyLinkedList(elems-1);
}else{
next = null;
}
}
}
也是完全有效的,即使構造函數使用相同的構造函數創建了一個新實例,因為創建是由條件保護的,所以創建一個實例有時會觸發一個新的創建。
public class Fail{
public Fail(){
new Fail();
}
}
是這里唯一有問題的例子。 編譯器不會抱怨。 它可以被翻譯成字節碼並且可以被執行。 但是,在運行時,您會導致堆棧溢出:
編譯器允許這樣做,因為通常編譯器無法阻止所有無限遞歸。 編譯器允許任何可以被翻譯成字節碼的東西。
但是,如果編譯器檢測到方法或方法鏈無條件地調用自身,則編譯器可能會發出警告。
這並不奇怪。 我所知道的所有面向對象的語言都允許這樣做。 代碼在語義上是對象定義的一部分,但實際上它可以被視為與任何給定對象的實際狀態分開。 因此沒有循環,因為對象構造不會調用您的方法(當然,除非它確實調用了 - 那么您遇到了問題)。
當您使用 new 創建對象構造函數時,會調用初始化實例變量的方法,直到您的超類的所有構造函數都被調用為止。 如果您將一些代碼放在每次創建對象時都會運行的構造函數中
當程序啟動時,它會執行 main 方法。 在 Java 中,您不能在類之外創建方法。 所有方法都必須封裝在一個類中。 因此,作為程序入口點的 main 方法必須在一個類中。 當您運行此程序時,main 方法將運行一次並執行其中的代碼。 在您的情況下,它創建封閉類TestClass
的對象。 這不必發生。 它也可以在這個類之外創建對象。 您只會得到@adarshr 的回答中所述的無限循環。
這一點也不奇怪。 你看, main()
方法是執行的起點。 因此,形象地說,java 是“盲目的”(看不到您告訴它執行/運行的內容),除非它“看到”了main()
方法。 在“看到” main()
方法之后,它現在有能力執行后面的其他指令,所以作為一個要點, main()
方法實際上不屬於它自己的類中的對象。
對於遞歸,它只會在您執行類似@Rohit Jain 所說的操作時發生。 或者根據您的代碼,您不調用anything
,而是調用main()
本身。
public static void main(String []args) {
TestClass t1 = new TestClass();
main(String[] args);
}
}
引用變量t1
字面上沒有調用main
因為它是靜態的。 好消息是, main
不是由您的代碼調用,而是由“jvm”調用,因此嚴格來說,您無法從那里刪除靜態。 它會導致一些好的錯誤消息明確告訴您靜態應該在那里。 這就是為什么您在上面的代碼片段中看到main()
沒有被對象調用的原因。
如果您執行這些操作,那么除此之外還會發生遞歸,您可以安全地在它自己的類中創建一個對象。 盡管如此,我不建議這樣做。 讓一個類具有main()
方法並在該 Main 類(包含 main 方法的類)中實例化(創建對象)其他類。 這樣你就可以運行一次代碼。
我不明白一些東西,我之前創建了類,讓 Main 方法直接調用方法而不創建 class 的 object,有人可以解釋做這篇文章中提到的代碼的目的是什么嗎? 在這個例子中,我讓方法“anything”返回一個字符串,所以我可以將此值分配給 Main 中的一個字符串變量。
public class TestClass(){
public static void main(String []args) {
String doSomething = anything();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.