Autor Zpráva
martin20a
Profil
Zdravím,
platí v PHP obdoba jak v Java/C++, že když mám konstanty či statické atributy třídy, tak náročnost časová na získání statického atributu těmito způsoby:
class A {
  public static $x = 1;
}
$a = new A();

// 1
echo $a->x;
// 2
A::$x;
...je 2 způsob lepší?

U 2 způsobu, se předpokládám podívá do tabulky načtených tříd najde třídu a ten atribut. Ale zajímalo by mě jak je to u způsobu 1 - čili to se dle mého podívá na adresu třídy a pak se podívá na odkaz třídy do tabulky tříd a tam najde ten atribut, čili by to mělo být náročnější, nebo alespoň zdlouhavější, než způsob č.1, je tak?

Je jasné, že tne rozdíl bude cca v nano sekundách, ale i tak by mě zajímalo co je lepší použít, jelikož třeba právě Netbeans ti dává varování, že je lepší použití č.2 než č.1 pro Java.

Díky :-)
juriad
Profil
martin20a:
První možnost je blbě (v PHP), tedy nad ní nemá smysl uvažovat.
Static properties cannot be accessed through the object using the arrow operator ->.
V Javě se používá druhá možnost především z důvodu přehlednosti, aby šlo na první pohled odlišit třídní a instanční proměnnou. Rychlost provádění je v Javě a C++ v obou případech stejná; oba jazyky se kompilují a provádí se některé optimalizace. (U Javy jsem si to právě ověřil.)


Javový kód
        M m = new M();
        System.out.println(m.x);
        System.out.println(M.x);
se přeloží jako:
        /* L7 */
        0 new 1;
        3 dup;
        4 invokespecial 21;       /* M() */
        7 astore_1;               /* m */
        /* L8 */
        8 getstatic 22;           /* java.lang.System.out */
        11 getstatic 10;          /* M.x */
        14 invokevirtual 28;      /* void println(int arg0) */
        /* L9 */
        17 getstatic 22;          /* java.lang.System.out */
        20 getstatic 10;          /* M.x */
        23 invokevirtual 28;      /* void println(int arg0) */
martin20a
Profil
juriad:
Jo to jsem napsal trochu blbě. Já jsem ve skutečnosti chtěl něco jiného, ale už si nedokážu vzpomenout jak to přesně bylo -> jsem si vzpomenul blbě očividně. :-)

Nicméně díky za ukázku, zeptal bych se ještě na dvě věci:
1) Jak mohu dosáhnout v netbeans/eclipse/... dumpu z překladu?
2) To co jsi zaslal je plný "dump", nebo jen jsi z toho vybral toto, jde mi hlavně o to, že při "m.x" bych řekl, že se musí dostat první přes adresu instance na přesnou adresu třídy? A u "M.x" se musí ta adresa hledat v tabulce, takže to asi bude na stejno, tak jak tak se musí najít. Což by nasvědčovalo tomu, že kdybych 1.000.000x zavolal "m.x" a "M.x", tak by lepší výsledek mohl dostat "m.x", jelikož tam to hledání v tabulce proběhne jen 1x, jestli uvažuji správně.

Je tedy ještě možné, že ten dump takto vypadá díky optimilizaci, že si každé "m.x" převádí na "M.x" :-)

Zrovna se učím na jednu zkoušku a tak si to propojuji s tím co dělám v "programovacím jazyce" PHP s tím co nás učí na příkladech java,c++,... :-))
juriad
Profil
Používám Eclipse a programuji v Javě. Doinstaloval jsem si doplněk Bytecode Visualizer. Pak stačí jakýkoli .class soubor otevřít v tomto editoru.

Celý zdroják je:
public class M {
    
    static int x = 5;

    public static void main(String[] args) {
        M m = new M();
        System.out.println(m.x);
        System.out.println(M.x);
    }

}

Celý vizualizovaný bytecode:
/* ******************************************** */
/* Generated by Dr. Garbage Bytecode Visualizer */
/* http://www.drgarbage.com                     */
/* Version: 4.3.5.201402051140                  */
/* Class retrieved from: Filesystem             */
/* Retrieved on: 2014-06-08 13:19:02.021        */
/* ******************************************** */

/* class file format version 51.0 (java 1.7) */

public class M {

    /* compiled from M.java */

    static int x;

    static {
        /* L4 */
        0 iconst_5;
        1 putstatic 10;           /* M.x */
        4 return;
    }

    public M() {
        /* L2 */
        0 aload_0;                /* this */
        1 invokespecial 15;       /* java.lang.Object() */
        4 return;
    }

    public static void main(java.lang.String[] args) {
        /* L7 */
        0 new 1;
        3 dup;
        4 invokespecial 21;       /* M() */
        7 astore_1;               /* m */
        /* L8 */
        8 getstatic 22;           /* java.lang.System.out */
        11 getstatic 10;          /* M.x */
        14 invokevirtual 28;      /* void println(int arg0) */
        /* L9 */
        17 getstatic 22;          /* java.lang.System.out */
        20 getstatic 10;          /* M.x */
        23 invokevirtual 28;      /* void println(int arg0) */
        /* L10 */
        26 return;
    }
}

Právěže javový kompilátor umí dokázat, že m.x je ve skutečnosti odkaz na statické pole (je součástí veřejného kontraktu dané třídy = je vždy známé), tedy ten mezikrok (který ani neumíš bez reflexe vyjádřit) vypustí. Ta „optimalizace“ je nutná, protože (nejspíš) neexistuje instrukce ani sekvence instrukcí v bytecode, které by přistoupily ke statické proměnné instančně.

Instrukce getfield (pro instanční proměnné) vezme ze zásobníku referenci na objekt a nalezne v něm hodnotu proměnné jejíž název dostane jako parametr a zapíše její hodnotu na zásobník.
Instrukce getstatic (pro statické proměnné) nebere nic ze zásobníku a nalezne hodnotu proměnné jejíž název dostane jako parametr a zapíše její hodnotu na zásobník.
martin20a
Profil
Díky :)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0