<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Old Post on Trevor's Blog</title><link>http://mings.in/en/tags/old-post/</link><description>Recent content in Old Post on Trevor's Blog</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Sun, 12 Mar 2017 09:00:00 +0800</lastBuildDate><atom:link href="http://mings.in/en/tags/old-post/index.xml" rel="self" type="application/rss+xml"/><item><title>Kotlin Null Safety</title><link>http://mings.in/en/posts/kotlin-null-safety/</link><pubDate>Sun, 12 Mar 2017 09:00:00 +0800</pubDate><guid>http://mings.in/en/posts/kotlin-null-safety/</guid><description>How to eliminate null pointer exception in Kotlin?</description><content:encoded><![CDATA[<h1 id="kotlin-null-safety">Kotlin Null Safety</h1>
<blockquote>
<p>Kotlin&rsquo;s type system is aimed to eliminate <code>NullPointerException</code>&rsquo;s from our code. The only possible causes of NPE&rsquo;s may be</p>
<ol>
<li>An explicit call to throw <code>NullPointerException()</code></li>
<li>Usage of the <code>!!</code> operator that is described below</li>
<li>External Java code has caused it</li>
<li>There&rsquo;s some data inconsistency with regard to initialization (an uninitialized <code>this</code> available in a constructor is used somewhere)</li>
</ol>
</blockquote>
<h3 id="variables">Variables</h3>
<p>As mentioned above, there&rsquo;re the only 4 ways to cause a NPE. And there&rsquo;re nullable and non-nullable types in Kotlin&rsquo;s System. So when you define a variable, you must tell Kotlin whether the variable is nullable or not.</p>
<ol>
<li>
<p>Non-nullable variable
You can define non-nullable variables as following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">var</span> <span class="py">b</span><span class="p">:</span><span class="n">String</span> <span class="p">=</span> <span class="s2">&#34;abc&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">var</span> <span class="py">a</span><span class="p">:</span><span class="n">Int</span> <span class="p">=</span> <span class="mi">10</span>
</span></span></code></pre></div><p>Once you want to assign a <code>null</code> to a non-nullable variable,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="n">b</span> <span class="p">=</span> <span class="k">null</span>
</span></span><span class="line"><span class="cl">    <span class="n">a</span> <span class="p">=</span> <span class="k">null</span>
</span></span></code></pre></div><p>the compiler will throw you an error. The Kotlin system prevent nullable value in the compile stage.</p>
</li>
<li>
<p>Nullable variable
If you want to define a variable which can be set as <code>null</code>, please code as following.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">var</span> <span class="py">b</span><span class="p">:</span><span class="n">String</span><span class="p">?</span> <span class="p">=</span> <span class="s2">&#34;abc&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">var</span> <span class="py">a</span><span class="p">:</span><span class="n">Int</span><span class="p">?</span> <span class="p">=</span> <span class="mi">10</span>
</span></span></code></pre></div><p>Now both of them can be set as <code>null</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="n">b</span> <span class="p">=</span> <span class="k">null</span>    <span class="c1">// ok
</span></span></span><span class="line"><span class="cl">    <span class="n">a</span> <span class="p">=</span> <span class="k">null</span>    <span class="c1">// ok
</span></span></span></code></pre></div></li>
</ol>
<h3 id="nullable-check">Nullable check</h3>
<p>The Kotlin system will tell you an error if you want to call a method from a nullable variable.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="n">b</span><span class="p">.</span><span class="n">length</span><span class="p">.</span>  <span class="c1">// compile error
</span></span></span></code></pre></div><p>You must check <code>b</code> whether it is null or not.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">b</span> <span class="o">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">b</span><span class="p">.</span><span class="n">length</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></div><p>It&rsquo;s a Java style way, is there a new method to handle this in Kotlin. Absolutely, yes. There&rsquo;s a new and safe operator, <code>?.</code>, to be used in this state.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">val</span> <span class="py">a</span> <span class="p">=</span> <span class="n">b</span><span class="o">?.</span><span class="n">length</span>
</span></span></code></pre></div><p>It&rsquo;s safe and never throws the <code>NullPointerException</code>. It will return a <code>null</code> for  this invocation and never really call the <code>length</code> method. Isn&rsquo;t a easy way to handle nullable variable?</p>
<blockquote>
<p>If you want the Java&rsquo;s style to handle exception, just use <code>!!</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">  <span class="k">val</span> <span class="py">a</span> <span class="p">=</span> <span class="n">b</span><span class="o">!!</span><span class="p">.</span><span class="n">length</span>
</span></span></code></pre></div><p>The above code may throws a <code>NullPointerException</code> during the runtime.</p>
</blockquote>
<p>There&rsquo;s also another example from kotlin&rsquo;s official site:</p>
<blockquote>
<p>Safe calls are useful in chains. For example, if Bob, an Employee, may be assigned to a Department (or not), that in turn may have another Employee as a department head, then to obtain the name of Bob&rsquo;s department head (if any), we write the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="n">bob</span><span class="o">?.</span><span class="n">department</span><span class="o">?.</span><span class="n">head</span><span class="o">?.</span><span class="n">name</span>
</span></span></code></pre></div><p>Such a chain returns a <code>null</code> if any of the properties in it is null.</p>
</blockquote>
<p>To perform a certain operation only for non-null values, you can use the safe call operator together with <code>let</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">val</span> <span class="py">listWithNulls</span><span class="p">:</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">String</span><span class="p">?&gt;</span> <span class="p">=</span> <span class="n">listOf</span><span class="p">(</span><span class="s2">&#34;A&#34;</span><span class="p">,</span> <span class="k">null</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span><span class="n">item</span> <span class="k">in</span> <span class="n">listWithNulls</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">     <span class="n">item</span><span class="o">?.</span><span class="n">let</span> <span class="p">{</span> <span class="n">println</span><span class="p">(</span><span class="k">it</span><span class="p">)</span> <span class="p">}</span> <span class="c1">// prints A and ignores null
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="elvis-operator-">Elvis Operator (<code>?:</code>)</h3>
<p>You definitely meet the following issue: return the string&rsquo;s length if non-null and just return <code>-1</code> when it&rsquo;s <code>null</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">val</span> <span class="py">l</span><span class="p">:</span> <span class="n">Int</span> <span class="p">=</span> <span class="k">if</span> <span class="p">(</span><span class="n">b</span> <span class="o">!=</span> <span class="k">null</span><span class="p">)</span> <span class="n">b</span><span class="p">.</span><span class="n">length</span> <span class="k">else</span> <span class="p">-</span><span class="mi">1</span>
</span></span></code></pre></div><p>Now there&rsquo;s new operator.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="k">val</span> <span class="py">l</span> <span class="p">=</span> <span class="n">b</span><span class="o">?.</span><span class="n">length</span> <span class="o">?:</span> <span class="p">-</span><span class="mi">1</span>
</span></span></code></pre></div><p>or</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl">    <span class="n">bob</span><span class="o">?.</span><span class="n">department</span><span class="o">?.</span><span class="n">head</span><span class="o">?.</span><span class="n">name</span> <span class="o">?:</span> <span class="s2">&#34;No Name&#34;</span>
</span></span></code></pre></div><p>If the expression to the left of <code>?:</code> is not null, the elvis operator returns it, otherwise it returns the expression to the right. Note that the right-hand side expression is evaluated only if the left-hand side is null.</p>
<p><em><strong>Note that, since throw and return are expressions in Kotlin, they can also be used on the right hand side of the elvis operator. This can be very handy, for example, for checking function arguments:</strong></em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">fun</span> <span class="nf">foo</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">Node</span><span class="p">):</span> <span class="n">String</span><span class="p">?</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">val</span> <span class="py">parent</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">getParent</span><span class="p">()</span> <span class="o">?:</span> <span class="k">return</span> <span class="k">null</span>
</span></span><span class="line"><span class="cl">    <span class="k">val</span> <span class="py">name</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">?:</span> <span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s2">&#34;name expected&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="safe-cast">safe cast</h3>
<p>Regular casts may result into a ClassCastException if the object is not of the target type. Another option is to use safe casts that return null if the attempt was not successful:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">val</span> <span class="py">a</span> <span class="p">=</span> <span class="n">Animal</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="k">val</span> <span class="py">dog</span><span class="p">:</span> <span class="n">Dog</span><span class="p">?</span> <span class="p">=</span> <span class="n">a</span> <span class="k">as</span><span class="p">?</span> <span class="n">Dog</span>
</span></span></code></pre></div><h3 id="collections-of-nullable-type">Collections of Nullable Type</h3>
<p>If you have a collection of elements of a nullable type and want to filter non-null elements, you can do so by using filterNotNull.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="k">val</span> <span class="py">nullableList</span><span class="p">:</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Int</span><span class="p">?&gt;</span> <span class="p">=</span> <span class="n">listOf</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">val</span> <span class="py">intList</span><span class="p">:</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Int</span><span class="p">&gt;</span> <span class="p">=</span> <span class="n">nullableList</span><span class="p">.</span><span class="n">filterNotNull</span><span class="p">()</span>
</span></span></code></pre></div>]]></content:encoded></item></channel></rss>