2016-04-01 6 views
1

私はプログラムを書いています。プログラム内のすべてが 'Engine'クラスによって制御されます。それで私はそれをシングルトンにしました。ここで私の現在のコードは正常に動作します。私のシングルトンクラスがStackOverflowerrorをスローするのはなぜですか?

package org.bautista.cybersafe.core; 

import javax.swing.SwingUtilities; 

import org.bautista.cybersafe.ui.MainUI; 
import org.bautista.cybersafe.util.Cache; 
import org.bautista.cybersafe.util.Config; 
import org.bautista.cybersafe.util.account.Account; 
import org.bautista.cybersafe.util.account.AccountManager; 
import org.bautista.cybersafe.util.user.User; 
import org.bautista.cybersafe.util.user.UserManager; 

public class Engine { 
    private static Engine instance; 
    private AccountManager accountManager; 
    private final MainUI ui; 
    private final UserManager userManager; 
    private final Config config; 
    private User currentUser; 

    private Engine() { 
     instance = this; //THIS IS LINE 22 
     if (!Cache.cacheExists()) { 
      if (!Cache.createCache()) { 
       System.out.println("Error creating cache."); 
      } 
     } 
     config = new Config(); 
     userManager = new UserManager(); 
     ui = new MainUI(); 
    } 

    public static Engine getInstance() { 
     return instance == null ? instance = new Engine() : instance; 
    } 

    public void setCurrentUser(User user) { 
     currentUser = user; 
    } 

    public User getCurrentUser() { 
     return currentUser; 
    } 

    public AccountManager getAccountManager() { 
     return accountManager; 
    } 

    public Config getConfig() { 
     return config; 
    } 

    public UserManager getUserManager() { 
     return userManager; 
    } 

    public void logOut() { 
     currentUser = null; 
     accountManager = null; 
     ui.showLogin(); 
    } 

    public void openAccountViewer(final Account account) { 
     ui.showAccount(account); 
     ui.setTitle("Cyber Safe - [" + currentUser.getUsername() + "] -" 
       + account.getName()); 
    } 

    public void openCreateAccountScreen() { 
     ui.showCreateAccount(); 
    } 

    public void openCreateUserScreen() { 
     ui.showCreateUser(); 
    } 

    public void openLoginScreen() { 
     ui.showLogin(); 
     ui.setTitle("Cyber Safe"); 
    } 

    public void openSafeScreen() { 
     if (accountManager == null) { 
      accountManager = new AccountManager(currentUser); 
     } 
     ui.showSafe(); 
     ui.setTitle("Cyber Safe - [" + currentUser.getUsername() + "]"); 
    } 

    public void refreshUI() { 
     ui.refresh(); 
    } 

    public void updateAccountPreviews() { 
     ui.updateAccountScroller(); 
    } 

    public void run() { 
     try { 
      SwingUtilities.invokeAndWait(() -> ui.setVisible(true)); 
     } catch (final Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

私はライン22

instance = this; 

をコメントアウト私はにStackOverflowErrorを受けます。私がプログラムをデバッグすると、Engineコンストラクタは、最終的にエラーが発生するまで、再帰を実行しているかのように、繰り返し呼び出されていることがわかります。なぜそれが起こるのですか?私の#getInstance()メソッドは、 'Engine'クラスの新しいインスタンスとしてインスタンスを開始するべきではありませんか?ここで

は、スタックトレースです:事前に

Exception in thread "main" java.lang.StackOverflowError 
at java.io.InputStream.<init>(InputStream.java:45) 
at java.io.FileInputStream.<init>(FileInputStream.java:123) 
at org.bautista.cybersafe.util.Config.loadProperties(Config.java:67) 
at org.bautista.cybersafe.util.Config.<init>(Config.java:29) 
at org.bautista.cybersafe.core.Engine.<init>(Engine.java:28) 
at org.bautista.cybersafe.core.Engine.getInstance(Engine.java:34) 
at org.bautista.cybersafe.util.user.UserManager.loadUsers(UserManager.java:73) 
at org.bautista.cybersafe.util.user.UserManager.<init>(UserManager.java:20) 
at org.bautista.cybersafe.core.Engine.<init>(Engine.java:29) 
at org.bautista.cybersafe.core.Engine.getInstance(Engine.java:34) 
at org.bautista.cybersafe.util.user.UserManager.loadUsers(UserManager.java:73) 
at org.bautista.cybersafe.util.user.UserManager.<init>(UserManager.java:20) 
at org.bautista.cybersafe.core.Engine.<init>(Engine.java:29) 
at org.bautista.cybersafe.core.Engine.getInstance(Engine.java:34) 
at org.bautista.cybersafe.util.user.UserManager.loadUsers(UserManager.java:73) 
at org.bautista.cybersafe.util.user.UserManager.<init>(UserManager.java:20) 
at org.bautista.cybersafe.core.Engine.<init>(Engine.java:29) 
at org.bautista.cybersafe.core.Engine.getInstance(Engine.java:34) 
at org.bautista.cybersafe.util.user.UserManager.loadUsers(UserManager.java:73) 
at org.bautista.cybersafe.util.user.UserManager.<init>(UserManager.java:20) 
at org.bautista.cybersafe.core.Engine.<init>(Engine.java:29) 

And here is the full project on Github

ありがとう!

+1

Engineクラスを構成する他のクラスのいずれかで新しいエンジンが作成されていますか? –

+0

コンストラクタはプライベートではありません。ほぼすべてのクラスがEngine.getInstance()メソッドを呼び出します。 @HovercraftFullOfEels – Bautista

+1

スタックトレースを表示してください。 –

答えて

4

スタックトレースは、次のループを示しています

at org.bautista.cybersafe.util.user.UserManager.loadUsers(UserManager.java:73) 
at org.bautista.cybersafe.util.user.UserManager.<init>(UserManager.java:20) 
at org.bautista.cybersafe.core.Engine.<init>(Engine.java:29) 
at org.bautista.cybersafe.core.Engine.getInstance(Engine.java:34) 

Engine.getInstance()通話new Engine()
new Engine()new UserManager()となります。
new UserManager()UserManager.loadUsers()を呼び出します。
UserManager.loadUsers()Engine.getInstance()が呼び出されますが、コールがまだ返されていないため、Engine.instanceはまだ割り当てられていません。

これは、new UserManager()を呼び出す前に、Engine.instanceをコンストラクタに代入して問題を解決する理由です。

初期化ループを防ぐために、コードを再編成する必要があります。 UserManagerEngineは、初期化中に共依存するべきではありません。

別の回答に示唆されているようにprivate static Engine instance = new Engine()を実行しても、初期化ループは修正されません。

+1

これはそれです。よく目撃された! –

+0

ありがとうございます!私は先に進み、それを書き直します:) – Bautista

関連する問題