Netbeans Java скардзячыся канчатковай зменнай ня ініцыялізуецца

Разгледзім наступны код:

final MyClass myObject;
try {
    myObject = new MyClass(...)
} catch (MyClassException){
   //terminate
    System.exit(1);
}

myObject.doSomething();

Праблема заключаецца ў тым, што Netbeans рэдактар ​​/ аналізатар лічыць, што .doSomething() можна было б назваць на unitialised аб'ект, які, вядома ж, гэта не так.

Is there an normal/standard pattern for circumventing this? I could call into a function but would rather not do that. I'd also rather not enclose the whole block in the try catch block since nothing else throws MyClassException

Я (пакуль ;-)) эксперт па Java граматыцы і шаблоны, так я спадзяюся, што я нешта відавочнае адсутнічае.

3

6 адказы

Вы ініцыялізаваць аб'ект у <�паспрабуйце/код> блок, які можа кінуць выключэнне, у выніку чаго аб'ект неинициализированным.

У вашым уловам блок, вы спыніць вашу праграму, але System.exit (1) не спыняе выкананне метаду, замест гэтага, ён завяршае ў цяперашні час працуе JVM - і для кампілятара гэта проста яшчэ адзін спосаб вам тэлефануйце, калі выключэнне.

return actually stops method execution - so no code beyond return; is reached. You can modify your catch block as following:

catch (MyClassException){
   //terminate
    System.exit(1);
    return;
}

Кампілятар не будзе скардзіцца на MyObject ня ініцыялізаваны такім чынам.

<�Моцны> Змяніць

Заўвага: калі вы паставіце myObject.doSomething (); у , нарэшце, блок кампілятар будзе скардзіцца, так як , нарэшце, выконваецца нават пасля таго, як вярнуцца .

finally {
   //compiler error
    myObject.doSomething();
}
5
дададзена
Ах. Дадаць вяртанне. Гэта міла. +1 і прыняць.
дададзена аўтар Bathsheba, крыніца
<�Код> певд Error (); або падобнае было б значна лепш.
дададзена аўтар Tom Hawtin - tackline, крыніца
<�Р> Праблема ў тым, што Netbeans рэдактар ​​/ аналізатар лічыць, што .doSomething() можа быць выкліканы на unitialised аб'екта, які, вядома ж, гэта не так.

Гэта <�моцны> з'яўляецца так: нішто не перашкаджае вам, выкарыстоўваючы SecurityManager , які забароніць System.exit() ад выхаду з віртуальнай машыны Java. У гэтай сітуацыі, наступны аператар <�моцны> можа выконваюцца.

З пункту гледжання граматыкі Java, кампілятар павінен даказаць, што MyObject гэта вызначана прысвоенай пры выкліку myObject.doSomething (); .

JLS паказвае сітуацыі, у якіх гэта можна зрабіць. У прыватнасці, толькі аператары, якія могуць быць выкарыстаны для вызначэння таго, што наступная каманда (ы) не будзе выконвацца ў разрыву , працягнуць , зваротны і кідок . Такім чынам, кампілятар не можа лічыць, што System.exit (1); прадухіліць наступную заяву выконваецца.

1
дададзена
У якасці адпраўной кропкі педантызму, то SecurityManager можа толькі прадухіліць выхад, кідаючы (любое) выключэнне (ці не вяртае).
дададзена аўтар Tom Hawtin - tackline, крыніца

Гэта лепшае, што я магу зрабіць:

final MyClass myObject;
{
    MyClass local = null;
    try {
        local = new MyClass(...)
    } catch (MyClassException){
       //terminate
        System.exit(1);
    }
    myObject = local;
}

myObject.doSomething();
1
дададзена
гэта добра, ён будзе працаваць.
дададзена аўтар omer schleifer, крыніца
Перасоўванне аб'явы ў блок Ьги лепш. але ў пэўным прыкладзе вы далі, дзе няма ніякага, нарэшце, блакаваць доступ да MyObject, вы ніколі не атрымаеце выключэння нулявога паказальніка.
дададзена аўтар omer schleifer, крыніца
Вы які збіраецца upvote гэта? Павінна быць значком для гэтага ;-) Сур'ёзна, хоць я не люблю гэтую карціну і яна абыходзіць кропкі ў іншых адказах.
дададзена аўтар Bathsheba, крыніца

Справа ў тым, што па-за/злавіць блок Ьги вы спрабуеце выклікаць метад на, магчыма, не рэалізаваны аб'екце. Гэта адбываецца таму, што блок Try/засаўка можа выклікаць выключэння, таму аб'ект не ствараецца, таму ў гэтым выпадку вы не будзеце мець аб'ект, калі вы спрабуеце выклікаць DoSomething() <�код /> метад на яго.

Калі ўключыць выклік метаду ў блоку Try/злавіць, ён будзе працаваць.

You can find related information here: Java Tutorials: Lesson: Exceptions

1
дададзена
Калі выключэнне выклікаецца ў межах блока ўлову, чым myObject.doSomething() не будзе дасягнута на ўсіх
дададзена аўтар omer schleifer, крыніца
Не зусім, таму што калі аб'ект не будзе створаны, я заканчваў System.exit (1). Радыкальны я ведаю.
дададзена аўтар Bathsheba, крыніца
А што, калі, напрыклад, ёсць выключэнне ў блоку злавіць? :-)
дададзена аўтар ragatskynet, крыніца
@Bathsheba што, калі выключэнне адбываецца ўнутры уловам блок? Вы ведаеце, вы можаце запусціць з памяці пры спробе памерці.
дададзена аўтар John Dvorak, крыніца

Кропка канчатковым зменных і членаў, каб заўсёды быць ініцыялізаваны. Нягледзячы на ​​тое, што ваш код ніколі не будзе выклікаць йоЗотеЬЫпд , ён пакіне канчатковае поле не вызначана. Гэта становіцца праблемай, калі вы дадаеце , нарэшце, пункт да блоку прымеркі злавіць - вы можаце ўвесці , нарэшце, становішча, калі адбываецца выключэнне і MyObject не будуць даступныя, якія кампілятар павінен пазбягаць. Хуткае рашэнне заключаецца ў перамяшчэнні йоЗотеЬЫпд выклік у блоку паспрабаваць:

final MyClass myObject;
try {
    myObject = new MyClass(...);
    myObject.doSomething();
} catch (MyClassException){
   //terminate
    System.exit(1);
}

Гэта павінна працаваць нармальна, пакуль DoSomething таксама ня кінуць MyClassException . Калі ён кідае такое выключэнне, вы, верагодна, неабходна адрозніваць выпадак прыйшоў Ці з канструктара або метаду (калі, вядома, гэта мае значэнне для вашай логіцы).

0
дададзена
<�Р> рэдактар ​​Netbeans/аналізатар лічыць, што .doSomething() можа быць выкліканы на unitialised аб'екта, які, вядома ж, гэта не так.

Вы тут не так. Вы на самой справе <�моцны> спрабуе для ініцыялізацыі зменнай. Кампілятар не «даверу» у ініцыялізацыі і прычына простая: <�моцны> можа згенеруе выключэнне, якое вы маглі б злавіць <�моцны>, але не кінуць новы RuntimeException() або зрабіць System.exit (1) . Напрыклад:

try {
    myObject = new MyClass(...)
} catch (MyClassException e){
   //hey I catch this but do nothing lmao yolo
    e.printStackTrace();
}

myObject.doSomething();

вы маглі б злавіць выключэнне, надрукаваць StackTrace і працягнуць праграму, і следствам гэтага можа быць NullPointerException .

0
дададзена
Але ёсць System.exit ў блоку выключэнні. Такім чынам, гэта азначае, што там ёсць выключэнне, JVM ня дасягне выкліку .doSomething.
дададзена аўтар Juned Ahsan, крыніца
Я ведаю, чаму кампілятар не можа быць палепшаны для сцэнара, калі сама JVM становіцца спыненая.
дададзена аўтар Juned Ahsan, крыніца
Але JVM кампілятар не працуе такім чынам. Ён не не верыць у тое, што ён знаходзіцца ўсярэдзіне пункта прымеркі ўлову, незалежна ад таго, што вы паклалі туды. Вы не можаце сказаць Java «Гэй, паверце мне, там не будзе якіх-небудзь пытанне, паглядзіце, я паставіў System.exit (1) там!»
дададзена аўтар Asier Aranbarri, крыніца