null प्रतिबंध और nullable types
(bugs.openjdk.org)- Java टाइप्स पर nullness markers जोड़कर
Foo!के जरिएnullको अस्वीकार करने औरFoo?के जरिए उसे जानबूझकर स्वीकार करने वाली एक preview language feature तैयार कर रहा है - बिना किसी marker वाला
Foonullness के लिहाज़ से unspecified रहेगा, ताकि पुराने कोड के साथ compatibility बनी रहे; और अलग nullness वाले types के बीच conversion पर warning या runtime checks लग सकते हैं nullको अस्वीकार करने वाले fields और arrays default valuenullका उपयोग नहीं कर सकते, इसलिए instance fields कोsuper(...)call से पहले definitely assigned होना होगा और arrays को component initial value चाहिए होगी- जब
nullकोFoo!में narrow किया जाएगा तोNullPointerExceptionहोगा, और array/field store paths में ArrayStoreException और FieldStoreException के जरिए pollution रोका जाएगा - Valhalla की value class flattening जैसी optimizations के लिए
nullexclusion पर भरोसा कर पाना बुनियादी शर्त है, लेकिन standard library पर इसे लागू करना या पुराने कोड को अपने-आप दोबारा interpret करना अभी लक्ष्य नहीं है
Java types में nullness को स्पष्ट करने वाली preview feature
- Java types पर nullness markers लगाकर यह बताया जाता है कि type के value set में
nullशामिल है या नहीं Foo!एक null-restricted type है, जो value set सेnullको बाहर रखता हैFoo?एक nullable type है, जो value set मेंnullको जानबूझकर शामिल करता है- बिना marker वाला
Foonullness के लिहाज़ से unspecified है; इसमेंnullआ सकता है, लेकिन यह नहीं पता चलता कि वह इरादतन है या नहीं - यह feature एक preview feature है, जो
--enable-previewcompile और runtime flags से सक्रिय होती है
लक्ष्य और गैर-लक्ष्य
- Java reference types में यह व्यक्त करना कि वे
nullकी अपेक्षा करते हैं या नहीं, और अलग nullness वाले types के बीच conversion पर warning और checks देना - मौजूदा Java code के साथ compatibility बनाए रखना, और source या binary incompatibility पैदा किए बिना इसे धीरे-धीरे अपनाया जा सके
nullको अस्वीकार करने वाले type की variables को पहली बार पढ़े जाने से पहले initialize होना चाहिए, और अलग से compile की गई classes में भी runtime परnullrejection लागू होना चाहिए- Valhalla की value class flattening जैसी runtime optimizations को null-restricted types पर भरोसा करने लायक metadata और integrity guarantees देना
- अभी जिन चीज़ों को लक्ष्य नहीं बनाया गया है, वे हैं:
- मौजूदा code को अपने-आप दोबारा reinterpret नहीं करना
- हर संभावित
nullको compile error नहीं बनाना intजैसे primitive types के लिए nullable रूप नहीं जोड़ना- इस चरण में standard library पर language extension लागू नहीं करना
इसकी ज़रूरत क्यों है
- Java में
Stringvariable या तोStringobject reference रख सकता है याnull, लेकिन language level पर यह बताने का तरीका नहीं है कि इनमें से कौन-सा इरादा है - बहुत-से programs मान लेते हैं कि
nullनहीं होगा, लेकिन Javadoc specification और implementation code में इसे लगातार enforce करने के लिए अतिरिक्त मेहनत चाहिए - जब यह अपेक्षा टूटती है, तो
nullimplementation code के भीतर बहता हुआ उस जगह exception पैदा कर सकता है जो मूल bug से काफ़ी दूर हो - अगर developer type के हिस्से के रूप में
nullको reject या accept करने का इरादा व्यक्त करे, तो compile-time feedback और runtime checks अनपेक्षितnullको जल्दी पकड़ने में मदद करते हैं - Valhalla में value class type variables को values की flattened representation के रूप में optimize किया जा सकता है, लेकिन अगर
nullencode करने के लिए extra bit चाहिए हो तो memory usage बढ़ सकता है या storage optimization असंभव हो सकती है - Amber में pattern match candidates की nullness,
switchकी exhaustiveness पर असर डाल सकती है, और type pattern की nullness इस बात पर असर डाल सकती है किnullmatch होगा या नहीं
nullness marker syntax और type structure
- nullness को type का मूल हिस्सा माना जाता है, इसलिए
Foo?औरFoonullness के हिसाब से अलग types हैं - array type और array component type दोनों पर nullness markers लग सकते हैं
Foo?[]!ऐसा type है जिसमें array खुद null-restricted है, और components nullableFooहैं- multi-dimensional arrays में हर bracket pair के बाद marker लगाया जा सकता है, और परंपरा के अनुसार इसे बाएँ से दाएँ outer से inner की ओर पढ़ा जाता है
- parameterized types और type arguments पर भी nullness markers लग सकते हैं
Predicate!<Foo?>एक null-restrictedPredicateहै, और type argument nullableFooहै
- null-restricted या nullable type व्यक्त करने के लिए source में
!या?का स्पष्ट रूप से होना ज़रूरी है - आगे चलकर यह देखा जा सकता है कि class या compilation unit के सभी types को default रूप से null-restricted माना जाए और केवल
?को exception की तरह लिखा जाए, लेकिन इसकी details अलग काम का विषय हैं
field और array initialization rules
- मौजूदा Java में reference type fields और array components की default value
nullहोती है, लेकिन null-restricted fields या array components के लिए यह शुरुआती value उपयुक्त नहीं है - null-restricted fields और arrays को पढ़े जाने से पहले program को हमेशा initialize करना होगा
- अगर null-restricted instance field में initializer नहीं है, तो हर constructor में explicit या implicit
super(...)call से पहले उसका definite assignment होना चाहिए- Flexible Constructor Bodies JEP constructor की शुरुआत में ज़रूरी initialization code लिखने की सुविधा देता है
- इस early construction context में
thisको refer करना या uninitialized fields को पढ़ने का जोखिम पैदा करने वाले operations की अनुमति नहीं है
- अगर null-restricted instance field में initializer है, तो वह हर constructor की शुरुआत में
super(...)call से पहले चलेगाthis(...)call करने वाला constructor, मौजूदा नियमों की तरह, initializer न चलाने वाला एक special case है
- null-restricted static fields को class के सभी static initializers और initialization blocks खत्म होने तक definitely assigned होना चाहिए
- अगर कोई दूसरी class class initialization के दौरान उस field को पढ़ने की कोशिश करे, तो runtime check early read पकड़कर exception फेंकेगा
- null-restricted component type वाले arrays में array creation expression के समय हर component की initial value देनी होगी
- array initializer के जरिए सभी values सूचीबद्ध की जा सकती हैं
- नई short syntax भी संभव है, लेकिन उसका syntax अभी TBD है
expression nullness और nullness conversions
- Java compiler type checking के दौरान हर expression की nullness तय करता है
- variable reference की nullness variable declaration से आती है, और method call की nullness referenced method के return type से आती है
nullliteral nullable होता है- बाकी ज़्यादातर reference-type expressions null-restricted होते हैं
- इनमें literals, string concatenation,
this, class instance creation, array creation, method references, और lambda expressions शामिल हैं
- इनमें literals, string concatenation,
- nullness conversions assignment, invocation, और casting contexts में मान्य हैं
- widening nullness conversion में ये शामिल हैं
Foo!→Foo?Foo!→ unspecifiedFooFoo?→ unspecifiedFoo- unspecified
Foo→Foo?
- narrowing nullness conversion में ये शामिल हैं
Foo?→Foo!- unspecified
Foo→Foo!
- narrowing nullness conversion को compiler unboxing conversion की तरह अपने-आप कर सकता है, लेकिन runtime पर dynamic check होगा और
NullPointerExceptionआ सकता है nullliteral को सीधे null-restricted type में convert करने की कोशिश compile-time error है
runtime checks और exceptions
- runtime पर अगर
nullvalue को narrowing nullness conversion के जरिए null-restricted type में बदला जाता है, तो NullPointerException होता है - source code में साफ़ तौर पर न दिखने वाले narrowing nullness conversions भी runtime execution के दौरान हो सकते हैं
- null-restricted component type वाले array को source code में कम specific type की तरह handle किया जाए, तब भी सामान्य array store check
nullvalue को reject करेगा- यह conversion failure ArrayStoreException पैदा करता है
- अगर compile time पर null-restricted न रहा field बाद में अलग compilation के कारण null-restricted बन जाए, तो नया field store check
nullstore को reject करेगा- यह conversion failure FieldStoreException पैदा करता है
- overriding संबंध वाले method calls में, पहले super method parameter call type में conversion हो सकता है और उसके बाद overriding method parameter type में conversion हो सकता है
- method return value भी पहले declared method return type में convert हो सकती है, फिर call site के expected return type में convert हो सकती है
generics, type arguments, overriding
- type variable के उपयोग पर भी nullness marker लगाया जा सकता है;
T!null-restricted type है औरT?nullable type है - null-restricted और nullable type-variable types, generic code के भीतर खास nullness assert करते हैं
- type argument के रूप में उपयोग होने वाले types भी nullness व्यक्त कर सकते हैं, और type-variable type पर लगा nullness marker, type argument में assert की गई nullness को override कर देता है
- generic API के erased implementation के भीतर null restriction enforce नहीं किया जा सकता
- लेकिन generic API boundaries पर होने वाले सामान्य implicit casts runtime पर null-restricted type arguments को enforce करते हैं
- interoperability के लिए type arguments के भीतर की nullness को सख़्ती से enforce नहीं किया जाता
Predicate<String!>कोPredicate<String>याPredicate<String?>में convert किया जा सकता है- ऐसी unchecked nullness conversion warning पैदा कर सकती है
- array component type की nullness बदलना भी unchecked nullness conversion के रूप में स्वीकार है, और किन परिस्थितियों में runtime check होगा यह अभी TBD है
- method signature identity तय करते समय nullness को नज़रअंदाज़ किया जाता है
- parameter और return type की nullness मेल न खाने पर भी एक method दूसरे method को override कर सकता है
- अगर अलग-अलग APIs स्वतंत्र रूप से nullness markers अपनाएँ, तो ऐसे mismatch आम हो सकते हैं
- nullness method applicability पर असर नहीं डालती और type argument inference failure का कारण नहीं बन सकती, लेकिन generic method के return type के लिए inferred nullness पर असर डाल सकती है
- inference algorithm की details अभी TBD हैं
compiler warnings और errors
- किसी type को null-restricted बनाने पर नए compile-time errors आ सकते हैं
- जब उस type के fields या arrays initialize न किए गए हों
- जब
nullliteral को उस type में convert करने की कोशिश हो nullliteral की तुलना null-restricted type expression से करना भी compile-time error बन सकता है
- इसके अलावा बाकी स्थितियों में nullness analysis सहायक है और compile-time errors नहीं बनाती
javacruntime errors से बचाने के लिए warnings देगा, और IDE व दूसरे analysis tools को भी यही दिशा अपनाने की सलाह है- warnings के संभावित कारण ये हैं
- narrowing nullness conversion, जिसमें
?type से आने वाले cases भी शामिल हैं ?type expression को member access या दूसरे null-hostile operations में इस्तेमाल करना- type arguments की nullness का bounds से मेल न खाना
- method parameter या return की nullness का overridden method से मेल न खाना
- type की nullness बदलने वाली unchecked conversion
- narrowing nullness conversion, जिसमें
class files, reflection, और सहायक बदलाव
- null markers के अधिकांश उपयोग
classfile में मिट जाते हैं, और उनसे जुड़े runtime conversions सीधे bytecode में व्यक्त होते हैं Signatureattribute syntax को update किया जाता है ताकि type के भीतर!और?की अनुमति हो- nullness को method और field descriptor में encode नहीं किया जाता
- field pollution रोकने के लिए नया
NullRestrictedattribute यह बताता है कि fieldnullvalue स्वीकार नहीं करता- इस field पर
ACC_STRICTभी होना चाहिए, और इसका strict initialization होना चाहिए - verifier जाँचता है कि constructor जब
super(...)call करे, तब तक सभी strict-initialized instance fields assigned हों - field में लिखने की हर कोशिश
nullvalue की जाँच करेगी, और मिलने परFieldStoreExceptionफेंकेगी
- इस field पर
- null-restricted array creation को
anewarrayinstruction support नहीं करता; इसे reflection API call से करना होगा Foo!.classयाFoo?.classजैसे literals नहीं होंगे, और उनके लिए कोईjava.lang.Classinstance भी नहीं होगा- नया RuntimeType API उन type sets को वर्णित करता है जिन्हें runtime पर array और field store checks enforce करते हैं, और इसमें सभी class व interface types के null-restricted variants शामिल हैं
FieldAPI field केRuntimeTypeकी query support करेगा, और यह valuegetTypeके result से अलग हो सकती हैArrayAPI, component type कोRuntimeTypeके रूप में व्यक्त करने वालेnewInstancevariant को support करेगी- यह variant array component की initial value देने की अनुमति भी देगा
- बिना initial value के null-restricted array creation की कोशिश reject की जाएगी
- पारंपरिक deserialization, null-restricted fields और arrays के साथ compatible नहीं है; एक अलग JEP ऐसा serialization mechanism देगा जो uninitialized null-restricted fields और arrays को expose नहीं करेगा
javadocद्वारा generated documents में nullness markers शामिल होंगेjava.lang.reflect.Typeऔरjavax.lang.modelAPIs type representation में nullness को encode करेंगी
alternatives और dependencies
- Java ecosystem के कई developer tools ने अपनी compile-time null tracking बनाई है, लेकिन Java language को बदले बिना, इसलिए syntax ज़्यादातर annotations तक सीमित रहती है और असर डाल सकने वाला व्यवहार भी compile-time checks तक सीमित रहता है
- दूसरी languages type system में nullness track करती हैं, और कई languages default रूप से null-restricted होती हैं तथा explicit null check के बिना null-restricted type में assignment को error मानती हैं
- Java में यह feature optional होनी चाहिए और एक बड़े migration के बिना धीरे-धीरे इस्तेमाल की जा सके
- runtime nullness enforcement को explicit checks या
Objects.requireNonNullcalls से भी लागू किया जा सकता है- लेकिन इसे लगातार लागू करना झंझट भरा है, अतिरिक्त documentation मांगता है, और program readability घटाता है
- fields और arrays जैसे variable storage पर इसे सीधे लागू करने का तरीका नहीं है
- पूर्व-आवश्यकता Flexible Constructor Bodies (Second Preview) है
- इससे constructors
super(...)call से पहले statements चला सकते हैं और instance fields assign कर सकते हैं, जिससे null-restricted field initialization requirement संभव होती है
- इससे constructors
- आगे के काम में ये शामिल हैं
- Null-Restricted Value Class Types (Preview): null-restricted value-class-typed fields और arrays की encoding optimization
- JEP 402: Enhanced Primitive Boxing (Preview): language में implicit boxing conversions के व्यापक उपयोग के दौरान nullness tracking
- JVM class और method specialization (JEP 218 और संशोधन): कुछ type arguments की nullness को reify और enforce करना
- अतिरिक्त संभावित future improvements में standard API के कुछ हिस्सों पर nullness markers लागू करना, bytecode में concise null check representation, null-restricted method parameters के लिए अधिक मजबूत low-level enforcement, और ऐसी language mechanisms शामिल हैं जो कुछ contexts में सभी types को implicit रूप से null-restricted मान लें
1 टिप्पणियां
Hacker News की राय
यह दिलचस्प है कि यह approach कुछ साल पहले C# द्वारा अपनाए गए तरीके से कैसे अलग है। C# में, अगर आप किसी project में nullability चालू करते हैं, तो जब तक किसी variable को स्पष्ट रूप से nullable न बताया जाए, सभी variables non-null घोषित माने जाते हैं। इस proposal में मौजूदा variables व्यावहारिक रूप से तीन में से एक हो जाते हैं: nullable, explicitly nullable, या explicitly non-nullable
Kotlin भी JVM language है, लेकिन C# की तरह, अगर स्पष्ट न किया जाए तो उसे non-null मानता है; हालांकि Kotlin पर backward compatibility का बोझ नहीं है।
lateinit varके जरिए non-nullable type को किसी दूसरे method में initialize होने तक खाली छोड़ा जा सकता है, और initialization से पहले access करने पर dedicated exception फेंकने वाला workaround भी देता हैमैं सोच रहा हूं कि तीन विकल्प क्यों रखे गए हैं। क्या unannotated variables को nullable बनाए रखना और सिर्फ annotated variables को explicit non-null बनाना पर्याप्त नहीं होता? अगर कोई marker न होने पर भी वह अपने आप nullable है, तो nullable घोषित करने की वजह समझ में नहीं आती
मुझे C# वाला तरीका ज्यादा पसंद है, लेकिन इस तरीके का फायदा यह है कि इसे legacy codebase में nullability की सारी समस्याएं हल किए बिना भी इस्तेमाल किया जा सकता है। उलटे, C# nullability की समस्याओं को तुरंत सामने ला देता है, जबकि यह proposal उन्हें अब तक की तरह छिपाए रख सकता है
और “एक method दूसरे method को override कर सकता है, भले ही उसके parameters और return value की null स्थिति मेल न खाए” वाला हिस्सा अजीब है। callback को override/implement करते समय अगर original method ने non-null return तय किया हो और implementation null return कर दे, तो यह footgun बन सकता है
समय की वजह से अभी हमने कुछ key जगहों को छोड़कर सिर्फ annotations चालू करने का रास्ता चुना है, लेकिन जिन जगहों पर conscious decision लिया गया है उन्हें तुरंत देखने के लिए हम JetBrains के
NotNullAttributeऔरCanBeNullAttributeको अभी भी markers के रूप में रखते हैं। दूसरा वाला हटाया जा सकता है क्योंकि nullable के लिए explicit marker है, लेकिन पहले वाले का C# की अपनी feature से नाम clash होता हैउस लिहाज से तीन विकल्प काफी वांछनीय हैं। वजह यह है कि अगर code सैकड़ों हजार lines का हो, तो migration तेजी और आसानी से करना मुश्किल है
दूसरे internal projects में, जिस code को छूते हैं उसके आसपास
#nullable enableडालकर धीरे-धीरे nullability का scope बढ़ा रहे हैं। यह शर्त भी रखी है कि नया code nullable context में होना चाहिए। यह भी पहले से annotated हिस्सों को explicit करने के लिए ठीक है, लेकिन यह तरीका काफी छोटे codebase और team में ही संभव हैString!की तरह exclamation mark से दिखाता है“platform type” शब्द और exclamation mark symbol थोड़े confusing हैं, लेकिन इनके अलावा Kotlin का तरीका काफी अच्छा काम करता है। Kotlin में शुरुआत से nullability थी, इसलिए programmers platform types को सीधे specify नहीं कर सकते, लेकिन JVM या JavaScript जैसे underlying platforms के साथ compatibility के लिए ये अब भी जरूरी हैं, जहां nullability अस्पष्ट होती है
इस approach में default फिर भी reasonable है। Default हमेशा non-nullable होना चाहिए, और जो लोग अलग सोचते हैं उन्होंने Tony Hoare से कुछ नहीं सीखा। साथ ही backward compatibility भी बनी रहती है। Kotlin के लिए यह आसान था, जबकि Java और C# को मौजूदा source code के साथ compatibility भी बनाए रखनी है
Java का तरीका भी ideal नहीं है और C# का भी नहीं। C# का तरीका compiler flag के आधार पर code behavior को काफी बदल देता है, और Java का तरीका default को सबसे खराब विकल्प बना देता है
फिर भी मैं C# की तरफ ज्यादा झुकता हूं। क्योंकि अगर “शायद null हो सकता है” को सबसे आसान विकल्प बना दिया जाए, तो ज्यादातर programmers default के तौर पर वही चुनेंगे। खासकर Java जैसी enterprise-friendly language में ऐसा और भी संभव लगता है। linters और compiler warnings लंबी अवधि में मदद करेंगे, लेकिन लगता है कि ज्यादातर Java code में nullability को ठीक से annotate होने में कई साल लगेंगे। C# users को short term में ज्यादा दर्द होगा, लेकिन explicit nullability के लक्ष्य तक वे शायद काफी तेजी से पहुंचेंगे
https://kotlinlang.org/docs/java-interop.html#null-safety-an...
https://www.infoq.com/presentations/Null-References-The-Bill...
T?का मतलब nullable औरT!का मतलब non-nullable हो, और नए compile होने वाले source में साधारणTका default source file के हिसाब से,package-infofile के हिसाब से, या compiler switch के जरिए globally तय करने के लिए कोई pragma जैसा declaration होबाद के किसी LTS Java release में global default बदला जा सकता था। इससे project migration आसान होता, pragma को automatically insert/update किया जा सकता, और जरूरत हो तो पुराना default भी बनाए रखा जा सकता था
साथ ही अगर मौजूदा JSR-305
@Nonnullannotation को class file में non-nullable type occurrence दिखाने के तरीके के रूप में इस्तेमाल किया जाता, तो पुराने JDK के साथ two-way compatibility भी दी जा सकती थी!symbol न लिखे”compiler flag या module tag जैसा कुछ भी हो तो ठीक लगेगा
फिर भी मुझे लगता है कि एक compiler flag आएगा, जो अलग से specify न होने पर automatically non-nullable assume करेगा
अच्छा लग रहा है। आखिरकार भाषा-स्तर पर हज़ारों गैर-ज़रूरी exceptions और null checks हटाने का तरीका मिल रहा है। हालांकि null-ness को narrow करने वाला automatic conversion कुछ गलत-सा लगता है
proposal के उदाहरण
String? id(String! arg) { return arg; },String s = null;,Object! o1 = s; // NPE,Object o2 = id(s); // NPE,Object o3 = (String!) s; // NPEमें कम-से-कम पहले दो मामले compile error होने चाहिए, ऐसा लगता हैआखिरी वाला explicit है इसलिए थोड़ा अस्पष्ट है, लेकिन बेहतर होगा कि
if (s != null)के अंदर compiler effective type कोString!माने औरString! ss = s;की अनुमति दे। तब error की संभावना नहीं रहेगीसच कहूँ तो आखिरी case के cast से ज्यादा मुझे
Objects.requireNonNull(s)इस्तेमाल करना पसंद है, क्योंकि वह ज्यादा explicit है। हालांकिObjects.unsafeForceNonNull(s)जैसा कुछ भी अच्छा होगा, जो explicit check को bypass करे लेकिन optimization की वजह से रुकने वाले मामलों को ही छोड़ दे। unsafe method हो तो जटिल static analysis जोड़े बिना सीधेrequireNonNullimplement किया जा सकता हैअफसोस, यह सिर्फ runtime पर ही पता चलेगा
उदाहरण के लिए standard library ने साफ कहा है कि कम-से-कम फिलहाल वह null types में migrate नहीं करेगी
package या कम-से-कम file स्तर पर सभी variables को default non-null mark करने का तरीका जरूर चाहिए लगता है। वरना safety के कारण लगभग हर variable पर
T!syntax इस्तेमाल करने की दलील मजबूत होगी, और इससे सिर्फ काफी noise पैदा होगा!symbol लिखने की जरूरत न हो और भाषा यह assert कर सके कि किसी खास context के सभी types implicitly null-restricted हैं”@Nullसे annotation लगाना पड़ता हैसमस्या सिर्फ libraries के साथ interact करने वाली code boundary पर आती है। यह नया syntax भी शायद वैसा ही होगा
“फिलहाल language improvement को standard library पर लागू करना लक्ष्य नहीं है” वाला हिस्सा निराशाजनक है
PHP को मजबूरी में इस्तेमाल करने के अनुभव से, data के बारे में पहले से guarantee की गई properties को विशाल standard library से interact करते समय हर बार उतारना या फिर से चढ़ाना झंझट है
Java को भी ऐसी expressiveness को standard library में और सक्रिय रूप से डालकर first-class citizen बनाना चाहिए
Optionalइस्तेमाल करने वाला legacy code explicit nullable/non-nullable proposal पर बोझ बनता है। लगता है record types भी default non-nullable हो सकते थेसाथ ही दो चरणों में बाँटने से इस feature को preview feature के तौर पर ज्यादा आसानी से release किया जा सकता है, feedback लेने के बाद design को निश्चित रूप से final किया जा सकता है। अगर सब कुछ एक साथ करने की कोशिश करें तो feature को असल में iterate करके सुधारने की गुंजाइश लगभग नहीं बचेगी
Java में यह feature आ जाए तो अच्छा होगा।
T?जैसी language-level explicit optionality ने Kotlin और TypeScript में developer quality of life काफी बढ़ाई है। Java में NullAway जैसे tools हैं, लेकिन वे झंझट वाले हैंमुझे लगता है language-level support
Optional/Maybeसे कहीं बेहतर है। क्योंकि यह code कोmap/flatMapकी रेल पर चढ़ाने के बजाय actual logic पर focus करने देता हैhttps://github.com/uber/NullAway
बस कोई दूसरी JVM language इस्तेमाल कर लेना बेहतर नहीं होगा?
site अभी down है, इसलिए archive link दे रहा हूँ: https://web.archive.org/web/20240802081039/https://bugs.open...
“प्रोग्राम को सभी संभावित
nullvalues को स्पष्ट रूप से handle करने के लिए मजबूर करना लक्ष्य नहीं है, और unhandlednullvalues compile time पर warning हो सकती हैं, लेकिन error नहीं” — यह एक खराब फैसला हैJava ज़्यादातर statically typed language है, फिर इसमें एक और dynamic behavior क्यों डाला जा रहा है, समझ नहीं आता। उम्मीद है कि ऐसी warnings को errors में बदलने का कोई आसान तरीका होगा
nullresponses को handle करने के लिए फिर से लिखना पड़ेगा। इस नए feature के साथ सिर्फ नए types से जुड़े operations पर ही अनिवार्यnullhandling लागू की जा सकती है, इसलिए कुछ भी नहीं टूटेगासभी मामलों में
null/nilhandling को type system द्वारा enforce करने वाली language कहीं बेहतर होती है। लेकिन मौजूदा Java ऐसी language नहीं है। फिर भी यह एक बड़ा improvement होगाअफसोस है कि ये सबक इतनी देर से सीखे जा रहे हैं। default रूप से non-nullable, default रूप से immutable, और default रूप से सबसे narrow scope होना चाहिए
नए design में बहुत बार “safe path पर fall back कराने” के बजाय तुरंत सुविधा को चुना जाता है। Safe defaults के लिए कहीं ज़्यादा सावधान design और user experience चाहिए, लेकिन नतीजा यह हुआ कि लगभग हर language, platform और technology में footguns भर गए। Civil और electrical engineering में नियम-कायदे हैं, लेकिन software हर करीब 30 साल में नई languages और technologies में वही सबक फिर से सीखता है
Java उस तीसरी दुनिया के गांव जैसा है जो यह सीख रहा है कि germs मारने के लिए पानी उबालना पड़ता है
Facebook में मैंने जो काम किया, उसका बड़ा हिस्सा Hack इस्तेमाल करना था। nullability Hack type system का core element है और यह सच में बहुत सारी बेकार errors सुलझा देता है
बेशक इसका मतलब यह नहीं कि कभी unexpected
nullनहीं मिलेगा। क्योंकि यह feature भी language में बाद में जोड़ा गया था, इसलिए PHP roots को reflect करने वाला legacymixedtype अब भी बहुत था, जिसका मतलब असल में कुछ भी हो सकता थापहले, nullable arrays का क्या होगा यह जानना चाहता हूं।
String![]example दिखाता है कि objectnullहो सकता है, लेकिन array खुद का क्या? Java मेंString labels[] = null;पूरी तरह legal है। तो क्या इसेString![]! labels;की तरह declare करना होगा?Hack में
vec $fooका मतलब है किfooभी और elements भीnullनहीं हैं, और?vec $fooमें elements non-null हैं लेकिनfoonullable है। असल में null array इस्तेमाल करने की वजह बहुत कम होती है, इसलिए default null-disallowed होना चाहिए। हालांकि Java में समस्या यह है कि पूरा legacy code nullability assume करता हैProposal के
Object! o1 = s,Object o2 = id(s),Object o3 = (String!) sexamples में लगता है कि 2 और 3 compile errors होने चाहिएआखिर में, Java की casting की तुलना में Hack का
ascoercion operator मुझे ज़्यादा पसंद है। उदाहरण के लिएfoo($b)compile error है,$b as Aअगर null हो तो runtime error देता है, और$a as ?Bअगर B हो तो cast करता है, नहीं तो null return करता हैअंत में सवाल यही बनता है कि क्या Java SDK पर इसे overlay किया जा सकता है, और legacy code में यह कैसा दिखेगा
https://docs.hhvm.com/hack/types/nullable-types
String![]? labels = null;होगालगता है Kotlin की अच्छी चीज़ें अब Java में भी आ रही हैं
फिर भी मैं Kotlin में ही काम करते रहना चाहूंगा, जहां Lombok जैसी चीज़ों से निपटना नहीं पड़ता। Java records अच्छे तो हैं