<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-12-15T15:09:34+08:00</updated><id>/feed.xml</id><title type="html">sheep shoop</title><subtitle>math imposter in cs</subtitle><entry><title type="html">On Bridge Methods</title><link href="/jekyll/update/2025/12/14/bridge-methods.html" rel="alternate" type="text/html" title="On Bridge Methods" /><published>2025-12-14T00:15:05+08:00</published><updated>2025-12-14T00:15:05+08:00</updated><id>/jekyll/update/2025/12/14/bridge-methods</id><content type="html" xml:base="/jekyll/update/2025/12/14/bridge-methods.html"><![CDATA[<p>This post was initially on the Ed forums for <a href="https://nus-cs2030s.github.io/2526-s1/">CS2030S</a>.</p>

<p>I first created this write-up after a consultation with the professor on this topic of bridge methods. In the end, it was on the final exam for 10% of the total marks.</p>

<h1 id="motivation">Motivation</h1>

<p>Consider the following piece of code:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="no">A</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="no">B</span><span class="o">();</span>
        <span class="n">a</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">A</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="no">T</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"T"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">String</span> <span class="n">str</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"String"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>The code outputs <code class="language-plaintext highlighter-rouge">String</code> as the output. This is to be expected when we substitute <code class="language-plaintext highlighter-rouge">String</code> into <code class="language-plaintext highlighter-rouge">T</code>. Then, since the method signatures for <code class="language-plaintext highlighter-rouge">A::foo(String)</code> and <code class="language-plaintext highlighter-rouge">B::foo(String)</code> are the same, we can use the <code class="language-plaintext highlighter-rouge">@Override</code> annotation on <code class="language-plaintext highlighter-rouge">B::foo(String)</code> without error.</p>

<p>At compile time, the dynamic binding process first finds the most specific method (only one choice here) for <code class="language-plaintext highlighter-rouge">foo</code> in <code class="language-plaintext highlighter-rouge">A</code>, which is <code class="language-plaintext highlighter-rouge">foo(String)</code>. At runtime, the method in the run-time type of the target is invoked, that is, <code class="language-plaintext highlighter-rouge">B::foo(String)</code>.</p>

<p>Using generics means there will be type erasure at compile-time. What would our code look like then? Suppose that bridge methods don’t exist.</p>

<p>Code after type erasure (no bridge methods):</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="no">A</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="no">B</span><span class="o">();</span>
        <span class="n">a</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">A</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"T"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">String</span> <span class="n">s</span><span class="o">){</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"String"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>The code with generics and the code with type erasure call different methods (<code class="language-plaintext highlighter-rouge">B::foo(String)</code> and <code class="language-plaintext highlighter-rouge">A::foo(Object)</code> respectively) and have different outputs. How do we make the two outputs the same? Enter bridge methods.</p>

<h1 id="bridge-methods">Bridge methods</h1>

<p>The solution that Java presents is to add extra code during type erasure. Since it is a method added by the compiler (and not us), it is called a synthetic method. A bridge method is specifically “a synthetic method that the compiler generates in the course of type erasure” <a href="#references">[2]</a>.</p>

<p>Using the example of the code above, the actual code after type erasure looks something like:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="no">A</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="no">B</span><span class="o">();</span>
        <span class="n">a</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">A</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"T"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span><span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">String</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"String"</span><span class="o">);</span>
    <span class="o">}</span>
    
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">o</span><span class="o">){</span>
        <span class="c1">//we shouldn't need instanceof check</span>
        <span class="c1">//because compiler generates after</span>
        <span class="c1">//checking the generics code</span>
        <span class="k">this</span><span class="o">.</span><span class="na">foo</span><span class="o">((</span><span class="nc">String</span><span class="o">)</span> <span class="n">o</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>At compile time, the dynamic binding process first finds the most specific method (only one choice here) for <code class="language-plaintext highlighter-rouge">foo</code> in <code class="language-plaintext highlighter-rouge">A</code>, which is <code class="language-plaintext highlighter-rouge">foo(Object)</code>. At runtime, the method in the run-time type of the target is invoked, that is, <code class="language-plaintext highlighter-rouge">B::foo(Object)</code>. Within <code class="language-plaintext highlighter-rouge">B::foo(Object)</code>, we see that all it really does is to forward the invocation to <code class="language-plaintext highlighter-rouge">B::foo(String)</code>.</p>

<p>The methods called and outputs of the generic code and the type erasure code now match.</p>

<p>Bridge methods are generated “when a type extends or implements a parameterized class or interface and type erasure changes the signature of any inherited method.” <a href="#references">[2]</a></p>

<p>Crucially, methods do not have to be overridden for a bridge method to be generated for it. It just has to have a different signature after type erasure.</p>

<h1 id="creating-errors">Creating errors</h1>

<p>In <a href="#references">[1]</a>, they give an example of something that could go wrong. In the context of <code class="language-plaintext highlighter-rouge">A</code> and <code class="language-plaintext highlighter-rouge">B</code>:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="no">A</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="no">B</span><span class="o">();</span> <span class="c1">//this code uses raw types</span>
        <span class="n">a</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">A</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="no">T</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"T"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">String</span> <span class="n">s</span><span class="o">){</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"String"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Running the code above results in a <code class="language-plaintext highlighter-rouge">ClassCastException</code>. Consider the type erasure equivalent:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="no">A</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="no">B</span><span class="o">();</span> 
        <span class="n">a</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">A</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"T"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span><span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">String</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"String"</span><span class="o">);</span>
    <span class="o">}</span>
    
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">o</span><span class="o">){</span>
        <span class="c1">//we shouldn't need instanceof check</span>
        <span class="c1">//because compiler generates after</span>
        <span class="c1">//checking the generics code</span>
        <span class="k">this</span><span class="o">.</span><span class="na">foo</span><span class="o">((</span><span class="nc">String</span><span class="o">)</span> <span class="n">o</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>The same runtime error occurs. Without bridge methods, there would have been no error. Our two codes are consistent in being wrong, so there is no unexpected behaviour. The compiler casts without checking in the type erasure code to mimic the generic code in error.</p>

<p>Another type of error that could occur is that the bridge method cannot be generated:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="no">A</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="no">B</span><span class="o">();</span>
        <span class="n">a</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">A</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="no">T</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"T"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">o</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">//this will not compile</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>This is a compile error. Two methods cannot have the same signature without overriding the other. However, this is exactly what would happen in our type erasure code with a potential bridge method and <code class="language-plaintext highlighter-rouge">B::foo(Object)</code>. Hence, the compilation will fail. The code would have looked like:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="no">A</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="no">B</span><span class="o">();</span>
        <span class="n">a</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">A</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"T"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="no">A</span> <span class="o">{</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">o</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">//from original code</span>
    <span class="o">}</span>
    <span class="kt">void</span> <span class="nf">foo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">o</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">//bridge method</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Both the generic code and the type erasure code must both compile without error for the program to be run. Since the type erasure code is generated from the generic code, if Java cannot generate the type erasure code, then it will refuse to compile the generic code.</p>

<h1 id="references">References</h1>

<p><a href="https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html">[1] Java Tutorial on Bridge Methods</a></p>

<p><a href="https://angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ103">[2] “What is a bridge method?” and “Under what circumstances is a bridge method generated?”</a></p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[This post was initially on the Ed forums for CS2030S.]]></summary></entry><entry><title type="html">Welcome to Jekyll!</title><link href="/jekyll/update/2025/12/12/welcome-to-jekyll.html" rel="alternate" type="text/html" title="Welcome to Jekyll!" /><published>2025-12-12T00:15:05+08:00</published><updated>2025-12-12T00:15:05+08:00</updated><id>/jekyll/update/2025/12/12/welcome-to-jekyll</id><content type="html" xml:base="/jekyll/update/2025/12/12/welcome-to-jekyll.html"><![CDATA[<p>You’ll find this post in your <code class="language-plaintext highlighter-rouge">_posts</code> directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run <code class="language-plaintext highlighter-rouge">jekyll serve</code>, which launches a web server and auto-regenerates your site when a file is updated.</p>

<p>Jekyll requires blog post files to be named according to the following format:</p>

<p><code class="language-plaintext highlighter-rouge">YEAR-MONTH-DAY-title.MARKUP</code></p>

<p>Where <code class="language-plaintext highlighter-rouge">YEAR</code> is a four-digit number, <code class="language-plaintext highlighter-rouge">MONTH</code> and <code class="language-plaintext highlighter-rouge">DAY</code> are both two-digit numbers, and <code class="language-plaintext highlighter-rouge">MARKUP</code> is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.</p>

<p>Jekyll also offers powerful support for code snippets:</p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">print_hi</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">"Hi, </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="n">print_hi</span><span class="p">(</span><span class="s1">'Tom'</span><span class="p">)</span>
<span class="c1">#=&gt; prints 'Hi, Tom' to STDOUT.</span></code></pre></figure>

<p>Check out the <a href="https://jekyllrb.com/docs/home">Jekyll docs</a> for more info on how to get the most out of Jekyll. File all bugs/feature requests at <a href="https://github.com/jekyll/jekyll">Jekyll’s GitHub repo</a>. If you have questions, you can ask them on <a href="https://talk.jekyllrb.com/">Jekyll Talk</a>.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.]]></summary></entry></feed>