Jak mohu zjistit, zda třída Java je volána vlastní main () nebo z jiné třídy?

hlasů
1

Mám třídu Java, který vypadá takto:

public class My_ABC
{
  int a=0;
  boolean B=true;

  static  // Initialize and load existing data only once at start-up
  {
     // need to know if it's called from its own main()
     // or by another class to conditionally set veriables
  }

  public My_ABC(int AA,boolean BB)
  {

  }

  public static void main(String[] args) 
  {
    My_ABC my_abc = new My_ABC(3,true);
  }
}

Protože je statický blok spustit při načtení třídy, jak mohu zjistit, zda je to jen z jeho vlastní main()nebo jiné třídě podmíněně nastavit proměnné?


Chápu, když někteří z vás řekl: „Všechny druhy zvonky jít pryč!“ No, je to proto, že mám situaci: Jsem navrhování třídu, která potřebuje nahrát velké množství dat na hranici mého PC (4G RAM), a běžím 32-bitovou verzi Javy, který lze použít pouze 1,5 g Ram max; takže když jsem otestovat tuto třídu sama o sobě, musím nahrát tolik dat, kolik je to možné vyzkoušet všechny možné situace, ale když to je voláno z více jiných tříd, nemůže to udělat (by způsobilo mimo chyby haldy prostor), takže by to mělo zavést pouze min. zapotřebí údaje. A přesto protože všechny údaje by měly být vkládány pouze jednou při startu, by mělo být ve statickém bloku; jinak musím zavést zvláštní logiku pro zjištění, zda je to být prvním načtení (potřebné k načtení dat) nebo 2., 3. času (neměly by se znovu a znovu načíst data). A kdybych implementovat další logiku k tomu, že i pohybovat kódu načíst data ze statického bloku, způsobilo by to zbytečné složitosti, protože když jsem se přesunout na 64-bitová verze Java (snad brzy), který navíc složitost by dodatečnou zátěž ( budu mít dostatek místa k načtení všech dat, i když volána z jiných tříd). Takže narychlo temp je odpovídajícím způsobem jej detekovat ve statickém bloku a zvládnout ten rozdíl, až budu mít dostatek prostoru, jen komentář je ven, aniž by bylo nutné měnit programování logické struktury.

Díky za všechny odpovědi a rady, jsem se snažil přístup „StackTraceElement“, funguje to skvěle! To vyřešit můj problém.

Položena 08/06/2009 v 18:14
zdroj uživatelem
V jiných jazycích...                            


6 odpovědí

hlasů
3

Myslím, že byste měli rozhodně změnit svůj přístup.

Ale protože jste požádáni něco konkrétního tady to je (shrnutí od ostatních).

public class X { 
    static { 
        System.out.println("Static free block");
        StackTraceElement [] st  = new RuntimeException("").getStackTrace();
        if( st.length == 1 ) {
            System.out.println("Invoked from main");
        } else { 
            System.out.println("Invoked from somewhere else");
        }
    }
    public static void main( String [] args ) { 
        System.out.println("Main");
    }
}

Pomocí této funkce lze testovat:

public class Y  { 
    public static void main( String [] args ) { 
        X x = new X();
    }
}

ps Nevím proč Josef smazat svou odpověď, že byl v dobré cestě.

Odpovězeno 08/06/2009 v 18:33
zdroj uživatelem

hlasů
3

Stačí se podívat na skutečné Stack. Test s tímto realizaci vašeho statického bloku. Výtisk se bude lišit, zda si ‚popraven‘ třída My_ABC nebo třída byla načtena později:

static // Initialize and load existing data only once at start-up
{
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    for (StackTraceElement el : stackTrace) {
        System.out.println(el);
    }
    // in real life you wouldn't print but use the stackTrace array
    // to identify why the class has been loaded and do your initialisation
}
Odpovězeno 08/06/2009 v 18:29
zdroj uživatelem

hlasů
2

VELMI špinavý roztok by bylo házení a chytání výjimku v statickém inicializace bloku. Při chytání výjimky, aby bylo vytisknout trasování zásobníku na ByteArrayOutputStream, transformovat bytové pole na řetězec a analyzovat stopy, zda statické inicializátor byla volána z hlavní metodu, kterou očekáváte.

Nicméně, dělá to zní jako černá magie, a musí se vyhnout ve prospěch lepších návrhů. , ,

Odpovězeno 08/06/2009 v 18:27
zdroj uživatelem

hlasů
2

Technicky vaše statické inicializátor nemůže být nazýván z jeho vlastní hlavní metodu, protože to bude vždy spuštěn před k mainmetodě:

// output: 'foobar'
public class Foobar {
    static { System.out.print("foo"); }
    public static void main(String[] args) { System.out.print("bar"); }
}

Takže se snažíte testovat nemožné ;-)

Odpovězeno 08/06/2009 v 18:20
zdroj uživatelem

hlasů
1

Pomocí statických inicializátory k načtení dat je riskantní v nejlepším případě. Možná alternativní řešení by bylo, aby se tato třída single-instance (buď prostřednictvím využití Singleton nebo prostě tím, že zajistí ve svém kódu, že je to pouze instance jednou). Pak byste mohl zavolat konstruktor nebo metodu zatížení s praporkem, který oznamuje, jak nastavit proměnné.

FWIW, myslím, že i načítání dat pomocí statické metody (ke kterému opět mohl předat vlajku), i když není skvělým řešením, by bylo vhodnější, aby pomocí statické inicializátor.

Odpovězeno 08/06/2009 v 18:19
zdroj uživatelem

hlasů
0

Nevím, jestli je to možné absolutně vědět, zda je vložen třídy, protože jeho vlastní main()je vyvolán, nebo proto, že jiná třída dělal odkaz na to - nebo prostě rozhodl se nahrát. Můžete zkoumat trasování zásobníku, ale to by mělo za následek velmi křehké kódu. Kód, který by mohl pracovat na jednom JVM, ale ne jiný. Nebo kód, který pracuje v desktopové aplikace, ale ne applet nebo webové aplikace Start. To není dobrý nápad.

Lepší by bylo, aby přehodnotila svůj návrh. Pokud třída potřebuje vědět, kdo ji načíst třída je na tom příliš mnoho věcí. Faktor, že část se do konfigurační třídy (nebo čehokoliv, co je vhodné), takže ten, kdo se načítá třídy může poskytnout správné informace.

Zde je šikovný trik, jak vytvořit singleton: Použijte jednohodnotové výčet. JVM zaručuje, že tam nemůže být více než jedna instance vytvořena. V konstruktoru ENUM (ne statická Inicializátor blok), dělat to, co databáze nebo souborový systém přístupu, který potřebujete, házení vhodné RuntimeExceptions podle potřeby, pokud se věci nepodaří. ENUM bude vytvořena při načtení třídy, takže nemusíte používat statickou init blok.

Odpovězeno 08/06/2009 v 18:31
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more