<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Java on J2234's log</title><link>https://log.j2234.cc/tags/java/</link><description>Recent content in Java on J2234's log</description><generator>Hugo -- gohugo.io</generator><language>ko</language><copyright>© 2026 J2234</copyright><lastBuildDate>Wed, 15 Apr 2026 04:11:55 +0000</lastBuildDate><atom:link href="https://log.j2234.cc/tags/java/index.xml" rel="self" type="application/rss+xml"/><item><title>가장 괴랄한 Java 문법 - 실전</title><link>https://log.j2234.cc/posts/java-generic-wtf-2/</link><pubDate>Sat, 09 Aug 2025 04:11:16 +0000</pubDate><guid>https://log.j2234.cc/posts/java-generic-wtf-2/</guid><description>&lt;h2 class="relative group"&gt;Intro
 &lt;div id="intro" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#intro" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://log.j2234.cc/posts/java-generic-wtf-1/" &gt;이전글&lt;/a&gt;에서 이어지는 내용이에요.&lt;/p&gt;
&lt;p&gt;이 글에서는, 여러 이벤트를 타입에 따라 처리하는 eventHandler를 만들면서 느꼈던 제네릭에 대한 고민과 해결 방법을 정리할 거에요.&lt;/p&gt;
&lt;hr&gt;

&lt;h2 class="relative group"&gt;기본구조
 &lt;div id="기본구조" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%ea%b8%b0%eb%b3%b8%ea%b5%ac%ec%a1%b0" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;EventPayload
 &lt;div id="eventpayload" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#eventpayload" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;EventPayload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooEventPayload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EventPayload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;FOO&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BarEventPayload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EventPayload&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;BAR&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;이벤트마다 다른 데이터를 담기 위해 최상위 &lt;code&gt;EventPayload&lt;/code&gt; 마커 인터페이스를 만들고, 각 타입별로 구현 클래스를 나눴어요.&lt;/p&gt;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://log.j2234.cc/posts/java-generic-wtf-2/featured.webp"/></item><item><title>가장 괴랄한 Java 문법(feat. &amp;lt;?&amp;gt;)</title><link>https://log.j2234.cc/posts/java-generic-wtf-1/</link><pubDate>Thu, 07 Aug 2025 04:30:11 +0000</pubDate><guid>https://log.j2234.cc/posts/java-generic-wtf-1/</guid><description>&lt;h2 class="relative group"&gt;Intro
 &lt;div id="intro" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#intro" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Java에서 가장 괴랄한 문법을 꼽으면, LLM 3개 모두 제네릭 와일드카드 &lt;code&gt;?&lt;/code&gt; 라고 대답해요.&lt;/p&gt;
&lt;p&gt;사실 공부하면서 봤었지만, 쓸 일 없을 것 같아 넘겼는데…
이벤트 처리 로직 만들다가 결국 마주쳐버렸어요.
이왕 마주친 김에, 확실히 정리할게요.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;del&gt;제네릭 전체를 설명하기엔 이 글이 너무 짧아서?,&lt;/del&gt;
&lt;del&gt;(와일드카드)의 개념만 간단히 짚고 실제로 마주쳤던 문제로 바로 넘어갈게요.&lt;/del&gt;
라고 하고싶었는데, 글이 너무 길어졌어요.&lt;/p&gt;
&lt;/blockquote&gt;&lt;hr&gt;

&lt;h2 class="relative group"&gt;와일드카드란❓
 &lt;div id="와일드카드란" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%ec%99%80%ec%9d%bc%eb%93%9c%ec%b9%b4%eb%93%9c%eb%9e%80" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;공변&amp;amp;불변&amp;amp;반공변
 &lt;div id="공변불변반공변" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%ea%b3%b5%eb%b3%80%eb%b6%88%eb%b3%80%eb%b0%98%ea%b3%b5%eb%b3%80" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;공변(covariant) : A가 B의 하위 타입일 때, &lt;code&gt;T&amp;lt;A&amp;gt;&lt;/code&gt; 가 &lt;code&gt;T&amp;lt;B&amp;gt;&lt;/code&gt;의 하위 타입이면 T는 공변
&lt;code&gt;A ⊂ B → T&amp;lt;A&amp;gt; ⊂ T&amp;lt;B&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;반공변(Contravariant): A가 B의 하위 타입일 때, &lt;code&gt;T&amp;lt;B&amp;gt;&lt;/code&gt;가 &lt;code&gt;T&amp;lt;A&amp;gt;&lt;/code&gt; 의 하위 타입이면 T는 반공변
&lt;code&gt;A ⊂ B → T&amp;lt;B&amp;gt; ⊂ T&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;불변(invariant) : A가 B의 하위 타입이더라도,&lt;code&gt;T&amp;lt;A&amp;gt;&lt;/code&gt; 가&lt;code&gt;T&amp;lt;B&amp;gt;&lt;/code&gt;간에 서브타입 관계가 없으면 T는 불변
&lt;code&gt;A ⊂ B → T&amp;lt;A&amp;gt; ⊄ T&amp;lt;B&amp;gt;, T&amp;lt;B&amp;gt; ⊄ T&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;자바의 제네릭은 기본적으로 불변이에요. 다음 코드는 &lt;code&gt;Integer&lt;/code&gt;가 &lt;code&gt;Number&lt;/code&gt;의 하위 타입이라 괜찮을 것 같지만, 사실 List&lt;Object&gt;와 List&lt;Integer&gt;는 아무 관계가 없기 때문에 컴파일되지 않아요.&lt;/p&gt;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://log.j2234.cc/posts/java-generic-wtf-1/featured.webp"/></item><item><title>Java Virtual Thread가 뭐임?</title><link>https://log.j2234.cc/posts/what-is-java-virtual-thread/</link><pubDate>Tue, 15 Jul 2025 02:20:18 +0000</pubDate><guid>https://log.j2234.cc/posts/what-is-java-virtual-thread/</guid><description>&lt;h2 class="relative group"&gt;Intro
 &lt;div id="intro" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#intro" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Virtual Thread는 자바 19에 Preview로 처음 도입되었고, 21부터는 Stable로 포함된 경량 스레드 기능이에요.&lt;/p&gt;
&lt;p&gt;이 글에선 자바 Virtual Thread가 뭐가 다른지, 어떤 상황에서 쓰면 좋은지 정리할게요.&lt;/p&gt;
&lt;hr&gt;

&lt;h2 class="relative group"&gt;Platform Java Thread(Original)
 &lt;div id="platform-java-threadoriginal" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#platform-java-threadoriginal" aria-label="앵커"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;자바에서, 기존의 Thread는 모두 Platform Thread를 사용했어요. 이는 OS(커널)수준 스레드를 감싸는 레퍼인데, 자바의 &lt;code&gt;new Thread().start()&lt;/code&gt;마다 OS 스레드가 하나 생성된다고 보면 되요.&lt;/p&gt;</description><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://log.j2234.cc/posts/what-is-java-virtual-thread/featured.webp"/></item></channel></rss>