Java Neinicializované proměnná se konečně zvědavosti

hlasů
6

Snažil jsem se přijít s nejasnými testovacích případů pro alternativní open-source JVM jsem pomáhal s ( Avian ), když jsem narazil na zajímavý kousek kódu, a byl jsem překvapen, že to nebylo sestavit:

public class Test {
    public static int test1() {
        int a;
        try {
            a = 1;
            return a; // this is fine
        } finally {
            return a; // uninitialized value error here
        }
    }
    public static void main(String[] args) {
        int a = test1();
    }
}

Nejzřejmější cesta kódu (pouze ten, který vidím) je vykonat = 1, „pokus“ pro návrat k (poprvé), pak spustit konečně, což vlastně vrací. Nicméně, javac si stěžuje, že „a“ nemusí být inicializován:

    Test.java:8: variable mohl by nebyly inicializovány  
        vracet;  
               ^  

Jediné, co mě napadá, že by mohlo dojít k / umožnit jiný kód cesta je, když temný výjimka za běhu mělo dojít po začátku pokusu, ale před tím, než hodnota 1 je přiřazena - něco podobného k OutOfMemoryError nebo StackOverflowException, ale já si nemyslím, že o případech, kdy by mohly případně nastat na tomto místě v kódu.

Může někdo blíže seznámit se specifiky standardu Java vrhnout nějaké světlo na toto téma? Je to jen případ, kdy kompilátor je konzervativní - a proto odmítají sestavit co by jinak bylo platný kód - nebo něco cizinec tady děje?

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


7 odpovědí

hlasů
10

Mohlo by se zdát absurdní, že existuje výjimka může dojít k a = 1 linie, ale může dojít k chybě JVM. Tak, přičemž proměnná a inicializována. Takže chyba kompilátoru je kompletní smysl. To je to, že temný chyba runtime, které jste zmínil. Nicméně bych tvrdit, že OutOfMemoryError zdaleka není temný a měly by být alespoň zamyslel vývojáři. Navíc nezapomeňte, že stát, který nastaví OutOfMemoryError by se mohlo stát v jiném vlákně a jednu akci, která tlačí množství paměti haldy používá přes limit je přiřazení proměnné.

Tak jako tak, protože jste při pohledu na kompilátoru design, Jsem také za předpokladu, že už víte, jak hloupé to je vracet hodnoty v bloku finally.

Odpovězeno 08/08/2009 v 07:54
zdroj uživatelem

hlasů
7

Jazyková specifikace Java vyžaduje, že proměnná je přiřazena před použitím. JLSDefinuje zvláštní pravidla pro které známý jako „jednoznačnému zařazení“ pravidla. Všechny Java kompilátory je třeba se jimi řídit.

JLS 16.2.15:

V rozhodně přiřazeno před finally iff V rozhodně přiřazeno před příkazem try.

Jinými slovy, při zvažování nakonec prohlášení, že se pokusila blok catch příkazy v rámci try-catch-finallyúkolů závěrky nejsou brány v úvahu.

Netřeba dodávat, že je specifikace jsou velmi konzervativní tady, ale oni chtěli mít specifikace být jednoduchý a zároveň poněkud omezené (věří, že pravidla jsou již komplikované) než být shovívavější, ale těžko pochopit a důvod kolem.

Překladače musí dodržovat tyto definitivní pravidla přiřazení, takže všechny kompilátory vydávat stejné chyby. Překladače není dovoleno provádět žádné další analýzu, než JLSurčuje, k potlačení jakékoliv chyby.

Odpovězeno 08/08/2009 v 07:58
zdroj uživatelem

hlasů
3

Věřím, že je to jen kvůli sémantiky try-catch-finally vztahu. Ze specifikace jazyka Java :

Jestliže výkon bloku try dokončí normálně, pak se konečně blok je proveden ...

Jestliže výkon bloku try náhle dokončí kvůli hodu s hodnotou V ...

Jestliže výkon bloku try náhle dokončí z jakéhokoli jiného důvodu R, pak se konečně blok je proveden ...

Poslední případ se zdá být nejvíce relevantní. Zdá se, že konečně blok by měl být schopen správně provedena v případě, že blok try náhle dokončí bez udání důvodu. Samozřejmě, pokud try blok skončil před tímto převodem nakonec blok nebude platná. I když, jak jste řekl, že to není velmi pravděpodobné.

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

hlasů
2

Chyby kompilátoru dojít v podmíněných bloků v případě, že kompilátor není jisté, že tyto (úspěch) Prohlášení poběží jako

int i=5;int d;
if(i<10)
{system.out.println(d);}

Chyby kompilátoru nedojde, pokud podmíněného příkazu je jistá a undoubtful kód nebude dosaženo podobné

int i;

if(true){}

else
{System.out.println(d);}

a chyby kompilátoru dojde, pokud podmíněného příkazu určitě nastat i undoubtful kód bude dosaženo jako

int i;
if(true)
{System.out.println(d);}
else{}

as try bloky spadají pod toto oni se řídí stejnými pravidly.

Odpovězeno 01/11/2012 v 18:09
zdroj uživatelem

hlasů
2

Je velmi pravděpodobné, že je zapotřebí, aby javac deku předpoklad, že výjimka by mohla vzniknout v libovolném bodě v bloku try, a to i v průběhu úkolu, a že tedy konečně může vrátit neinicializované proměnné. Teoreticky by to mohlo udělat podrobnou analýzu a zjistil, že ve všech cest přes bloku try ‚a‘ bude vždy úspěšně inicializován, ale to je hodně práce pro téměř žádný zisk.

Nyní, když někdo prostě poukázat na příslušný oddíl specifikaci jazyka Java ...

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

hlasů
1

Myslím, že Java překladačů předpokládá nejhorší případ - neexistuje žádná záruka, že se něco v bloku try dokonce proveden z nějakého důvodu. Takže jeho stížnost je platná. Proměnná možná nebyl inicializován.

Odpovězeno 08/08/2009 v 08:24
zdroj uživatelem

hlasů
0

Kompilátor právě tady konzervativní.

Odpovězeno 08/08/2009 v 07:11
zdroj uživatelem

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