【雑談】あえて今、20年前のJavaを自由に語る


**※注意
(2021.9.21) 
まずは、私自身がかなり無知であるのに、あたかもJavaやその周辺技術を分かったかのように記事を挙げたことを、お詫びします。
ただし、記事の内容に関しては、原文のまま削除しません。
その理由は、現在の私のように、過去の事実関係があやふやなまま普段の業務に取り組んでいる人を晒すためです。
私自身にとっても、そこから出てくる指摘は学びになるので、助かります。
きちんと理解している方も、初心者の方も、【アンチパターン】として「この記事の著者の認識は良くない、怪しい部分がある」ことを理解して、必要であればさらに追加調査を行い、読み進めるようにお願いします。**

なお、他社技術が入る部分だけは削除させていただきました




# はじめに

「10年前の技術」に関する記事。
こんなテーマなら、さらに20年前の話から始めて、私の思い出話を語ろうかなと思う。

https://qiita.com/official-events/1e99fc384200c38548fd

この記事では、私が知っている時代の**「Java」**を自由に語る。

語ろうとしている年代(1990年代後半)、私は当時小学生であり、当然SEなんて仕事はしていなかったが、密かに**「システムエンジニアになりたい」**という夢を抱いていた。

そんな私にとってJavaは、**「プログラミング言語として学んだ2番目の言語」**であり、
長い期間きちんと独学していた言語でもあるので、思い入れがたくさんある。
当時からしてみれば、**オブジェクト指向**や**ガベージコレクション**、**AWT/SwingなどのGUIライブラリ**~~(なお今は死語)~~は非常に画期的な機能の一つであった。

当時は**「Javaは文法的にもかっちょいいし、Cよりは遅いけど色々ソフトウエアが作れる言語なんだぜ～」**なんて世間の風潮だったわけ。
実際、当時は**Javaアプリケーション**や**Javaアプレット**~~(これも死語だな)~~が当時人気だったFlash並みにWebで量産されていき、人気があった。
そんな今、そんな姿はどこへやら、**既得権益(Oracle社)に飲まれた言語**となっている。

ところで、当時あれほど**「ポンコツ」**と称されていた（Javaとなんとなく似ているけど全く別物の）スクリプト言語**JavaScript**は、今や**「開発者が好む言語No.1」**になる時代。
まさかこんな時代が来るなんて想像もしていなかった。

## 注意

- ここに出てくるコードは、**「20年前～15年前くらいのJavaのコード（を何となく思い出しながら書いたもの）」**であり、化石のようなものだ。まず現代の設計に追いつかないものであるので、決して使用してはならない。
- 歴史に関する詳しい部分は不正確なので、例えば以下の良記事を参照にすること。当時の私は中学生～大学時代で、リアルで仕事しているわけではない。ビジネスや規格競争のような難しいことはようわからずにやってたからな。

https://next.rikunabi.com/tech/docs/ct_s03600.jsp?p=001335

- 本人も当時の状況を他の資料(Wikipediaなど)を使って割と不正確に伝えていますので、「これおかしい」とか「ここもっと調べて欲しい」ってのがあったら是非コメントください。


# 旧き良きJavaの遺産

## 20年前、Javaの黎明期

### Duke

読者は、こいつの存在**「Duke」**を知っているだろうか。
~~ちなみに最近まで名前を知らなかった~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/f435c39d-ef24-d419-5de6-bbcabb9ae014.png)

このマスコットキャラクター、実は既にJDK Beta(1995)の頃には誕生していた。
当然のことながら、よく売れている書籍の中でこいつが描かれていたら、**間違いなくJavaの書籍であることを確実に伝えている**。

### どうやってJavaを勉強したか

私がJavaを勉強したのは、丁度JDK 1.0~1.1くらいの内容をまとめてくれたプログラマーの書籍からである。

今でも間違いなく現存しているホームページに「**浅煎り珈琲 Javaアプリケーション入門**」がある。（~~なお化石~~）

http://msugai.nobody.jp/java/index.html

今でこそ、無料有料問わず色んな分野に対する書籍・Webサイト・動画が多量にある時代であるが、
当時の私からしてみれば、**プログラミングの基本がここまできっちり理解できるコンテンツ**は貴重で、
私にとってのデータアーキテクチャの基礎を今でも支えてくれている。

### 家電とJava

実は開発当初、Javaは**IoTの先駆け**だったことをご存知だろうか？

Javaは、当時として堅牢性を考慮した設計であり、同時にWeb技術への拡張性を兼ね合わせているため、
これをWebSocketを使ってHTTP/HTTPS/FTPプロトコルなどに接続してしまえば、あら不思議**IoTモジュールの完成**、そんな未来を描いた言語だったのだ。

Web技術の中心となった現代のJavaであるが、Javaは、元々**家電の制御のために作られた技術**であった。
それは、当時C++はあまりにも柔軟性がありすぎて制御の安定性に問題があり、現代ほど電気製品の制御に向いている技術ではなかったためである。

そこで、JavaはC++の概念を整備して堅牢性を重視して設計された。

Javaの概念は型制約の厳しさを残してC#に引き継がれている。

### Java仮想マシン(JVM)と互換性

Java仮想マシンという概念も、現在で言うところの**クロスプラットフォーム開発**や**Virtual Desktop、Dockerなどの仮想化環境**の考え方のベースとなる素晴らしいものであった。

https://www3.cuc.ac.jp/~miyata/classes/prg1/02/2way.html

一般に、プログラムの実行される方式は**インタープリタ方式**と**コンパイラ方式**がある。

- インタープリタ方式は、人間の書いたコードをそのまま実行する方式
- コンパイラ方式は、人間の書いたコードを機械語に変換する方式

インタープリタ方式が現在の多数の高級言語に該当し、
コンパイラ方式の代表格がC++であることは言うまでもない。

そして、そのJavaは、どちらの方式でもない**中間コード方式**を取っていた。
これは**コンパイルするときに、Java仮想マシン(JVM)に理解できる形式で変換する**ものであり、
それで生成された中間言語は、JVMが責任を以て実行するので、**どのような環境でも実行出来る強み**があったのだ。

当然、家電のような組込み用途においても、このような設計が活用できるのが有意義には違いない。


### Swing

GUIに関しても規格化が行なわれるような流れとなっていて、Javaにおいては**Swing**と呼ばれるライブラリが並んだ。
当時としては**Look&Feelに配慮された綺麗なGUIで、JVMの性質上どのようなプラットフォームでも動く**のが強みだった。

実際、Swingの画面とmfcの画面を比較してもらえれば分かると思う。
mfcはC++でWindowsでしか書けないのに、よくも悪くもWindows的なGUIであるのに対し、Swingはこれがあらゆるプラットフォームで動くんだからすごいすごいってなると思う。

**Swing**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/fb94fcd2-8f5c-0ad3-b1a4-c22ab94e1f54.png)

https://ja.wikipedia.org/wiki/Swing

### GUIの規格化とレイアウトマネージャー

さらに、このSwingとはちょっと違う話題だが、**レイアウトマネージャの概念**も、Javaをユニークにする一つの概念であった。

実はレイアウトマネージャに関してはきちんと対応したC#フレームワークは、**WPFまで存在しない**のだ。
つまり、当時のWindowsアプリケーションはほぼ例外なく**絶対座標系で**GUIを表示していた。
現在でもこの絶対座標系を禁止するような正式な解決策はなく、**私もWindowsアプリ捨ててブラウザ使いたい**って気持ちになってしまう。~~WPFめんどくせえんだよなあ~~

そしてそのWPFも難しすぎるってんで、それをHTMLとJavaScriptで記載してアプリケーションを作れるようにした**electron.js**が割といま元気であるけれども、こうした時代に来るまでMicrosoftで作られた製品が**ユニバーサルデザインを意識した設計**になることはなかったのである。
(**tkinterやQtを見ていると、もしかすると当時でもユニバーサルデザインに対応したものはあったかもしれませんが。**)

特に、以下のような**GridBagLayout**と呼ばれるレイアウトは難しかったが非常に便利であった。

https://a4dosanddos.hatenablog.com/entry/2015/10/29/015240

HTMLで言うところの

```html
<table>
 <tr>
  <td colspan=2>AA</td><td>BB</td>
 </tr>
 <tr>
  <td>1</td><td>2</td><td>3</td>
 </tr>
</table>
```

に対応している機能なのだが、多少その仕組みが複雑とは言えどのようなレイアウトも再現出来たのには一定の効果があったように思える。

また、同じGUIをカードを切るように前後ろに配置する**CardLayout**と呼ばれるレイアウトも便利であった。
これも、現在のHTML5では**インライン**で代用される概念だと思うが、こういうのがデフォルトについていたJavaはレイアウトの考え方に対しても素晴らしい部分があったと思う。

### アプレットとFlash

この時代を象徴するJavaで出来たものと言えば**アプレット**であるだろう。
けれど、実はJavaの中でアプレットは初期の頃はJavaの目玉技術として採用されていたものの、2017年にはもはや表示されなくなるなどの憂き目に遭っている。

それでも、当時はすごかったのだ。**個人のHPにJavaアプレットが大量に生成された。**
今ではJavaScriptを使えば容易にゲームくらい作れる時代(~~私にそんな力はないが~~)だが、当時流行したFlash同様、**JavaはプラグインをHTMLに埋め込む形式として流行した**。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/f01f2a7b-bb83-6122-27ba-a4b943d96e55.png)

https://www.amazon.co.jp/%E6%A5%BD%E3%81%97%E3%81%8F%E5%AD%A6%E3%81%B9%E3%82%8BJava%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%BB%E3%82%A2%E3%83%97%E3%83%AC%E3%83%83%E3%83%88-I%E3%83%BB-BOOKS-%E6%9D%91%E5%B1%B1-%E8%A6%81%E5%8F%B8/dp/4777511618

↑のような本が山ほどあった時代だったわけです

Javaアプレットの最大の強みは、**JVMが責任もってブラウザの動きを管理してくれたこと**になる。
今でこそ**フロントエンド**⇔**バックエンド**という用語は一般的なものになっているが、当時こうしたゲームを作ろうと思ったら**プラグインを埋め込む方式**が主流なのであった。つまり基本はフロントエンド側で完結するスタイルなのである。

そんなアプレットのHTMLは、どこでもこんな感じに書籍に書いてあったわけだ。

```html
<html>
<title>Java Applet</title>
<body>
<applet src="myapplet.class" width=640 height=480>
</applet>
</body>
</html>
```

**この書き方自体、今のJavaScriptのHTML5に通ずるところがある**。

もちろんこんな感じでプラグインのプログラムを1個だけ設置するなんてのはないのだが、idやname、classを使って上手いこと識別子を与えて、そこに表示したいプログラムをダイレクトに組み入れる考え方は似通っているのだ。

### Javaはモバイル開発の元祖

Javaといえば、Androidのモバイルアプリケーションの分野で未だに現役であるが、既にもうこの時代から**「携帯に使おうか」**の流れはあったのだ。**本当、Javaは恐ろしい子**。

当時のモバイルフレームワークは多数あったが、有名どころは

- CLDC 
- MIDP(Mobile Information Device Profile) : Vodafone, au ezアプリ用途
- Doja : Docomo i-modeアプリ用途

などであろう。

~~Vodafoneという単語自体が懐かしいな。私は結構長年まで、Vodafoneユーザであった。~~

https://k-tai.watch.impress.co.jp/cda/article/keyword/25327.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/103d5b53-3362-6532-6a9e-766b15b43915.png)


私の記憶では、自分自身の演習の目的でMIDPを頻繁に使っていたので、それを思い出すためにソースコードがどんな感じだったか紹介すると、
WebではAppletと言うように、MIDPでは**MIDlet**と呼ばれるオブジェクトクラスを定義する。

~~めっちゃ懐かしいコードだと本気で思った（）~~

Javaにおいて、結構Appletが基本で派生したモバイル開発は多いのかなと印象。
また、このことで**Appletで学んだ知識がそのまま大体Javaアプリ開発に活かせる**のも大きなメリットだった。

一方、下記にもあるようにMIDletからオーバーライドしたメソッドでしか処理が出来ないので、**設計に対する自由度はさすがに現代と比べるとかなり劣る**。
Appletは、**ブラウザのプラグイン**に埋め込んでいたのでその範囲の中では自由度が高かったのですが、モバイルアプリは**「モバイルアプリの一つのウィジェット」**だけが切り出されているせいで、出来ることが少なくて**「使いにくいな～」**という印象はどうしても残った。
またご存知のように、昔のガラケーは**画像容量が少ない**！ゲームとか作ろうとすると、画像リソースの問題にも限界が・・・。

```java

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class HelloMIDlet extends MIDlet implements CommandListener {
  public HelloMIDlet() {
    ...(GUI初期化処理)...
  }

  public void startApp() {
    ...(動作start時の処理 MIDletのオーバーライド)...
  }

  public void pauseApp() {
    ...(Pause時の処理 MIDletのオーバーライド)...
  }

  public void destroyApp(boolean unconditional) {
    ...(終了時の処理 MIDletのオーバーライド)...
  }

  public void commandAction(Command c, Displayable s) {
    ...(GUIで登録したEventListenerの処理 CommandListenerから継承)...
  }
}

```

https://allabout.co.jp/gm/gc/80736/2/


### javadocでドキュメント作成を簡単化

この記事をまとめている最中、重要なトピックである**javadoc**のことを触れるのを忘れていた。
~~本当、書けば書くほどJavaのネタが出てくる。それだけ将来性が期待されていた言語なんだろうなって思う~~

https://docs.oracle.com/javase/jp/8/docs/api/

Javaを少しでもやっていれば、このAPI仕様書には必ずお世話になっているはずだ。
しかし、私の過去においては若干これはトラウマだ。
継承の概念も少しずつ学んでいく時期だったので、**分からないクラスはとにかく索引から探す！！！**なんていう無謀な作業に取り組んでいた記憶がある。
当時はひたすら検索をかけまくったので、**Ctrl+F**はショートカットキーとして覚えろと言わなくても体が覚えてしまった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/12c5d6d6-3e3f-9122-65e0-16025c1419eb.png)
↑こんなところから探せとか言われたらマジで発狂する（なお現実）

さてこのjavadocも、ソースコード管理上、大変画期的な仕組みである。
Sun Microsystems社の社員は、この膨大なJavaのライブラリに一つ一つWebページを用意し、機能説明を準備しただろうか？
しかも**リリース期間が1~2年**という状況で。

**当然そんなことはしないわけで、ソースコードにコメントの型を決めてそれを自動生成していたのだ。**

javadocでマニュアルに追記する場合、例えばこんな感じで書いたりする
(外部サイトより引用)

```java

public class Sample01{
  /**
   * サイズの設定
   * @param width 幅
   * @param height 高さ
   */
  public void setSize(int width, int height){

  }
}

```

https://www.javadrive.jp/javadoc/comment/index1.html

そしてコンパイルするときに、javac -d Sample01.javaなどと書いて実行すると、先ほどのAPI仕様書が自動生成されるのだ。

この考え方は特に**Javaのプログラマーにとって本気で感動させられる仕様**であった。
（もちろん現在では割と日常的なものであるのだが）
**API仕様書の作成の作業が一つ減り、コードレビューする際もこのjavadocを吐き出せばレビューが出来るのが素晴らしい。**

### Collection Framework

Collection FrameworkはC++のSTLを真似したものであるが、これもJavaでは独自の仕様となった。
実際、JavaのSTLで採用されている**Vector**はC++をベースに設定された可変長配列であり、基本になっているようである。

ところが、当時Javaはジェネリクスが存在しなかった。
一応、可変長配列として有名な**ArrayList**なんか

```java
ArrayList list = new ArrayList();
```

と書いていたのだが、型指定の難しさは課題にあったのだ。それで2005年のJ2SE 5.0以降のアップデートでジェネリクスが生まれていた。

ちなみにそういう面では、他言語とは多少出遅れている面もあったと思われる・・・と思いきや、全く同じ時期の2005年にC# 2.0が出来たのだが、**この時点でC#はジェネリクスに対応していたようだ**。
私の中では、C#でジェネリクスを積極的に扱えるようになったのは、LINQが誕生するC# 3.0だったように思える。

### 革命的な文法 (1) インスタンスを渡す

インスタンスの概念は、C++の左辺値参照が基本となっている。そしてその左辺値参照はどうも1988年に構想され導入されたもので、この概念自体はC++がベースとなっているようだ。

http://icarus.cs.weber.edu/~dab/cs1410/textbook/6.Functions/reference.html

しかし、C++の左辺値参照には**「インスタンス」**の概念はなく、実体がどこかにいなければそのデータは無効となる。

```cpp:参照渡し(C++)
// originalはSomeClass型の実体のあるデータ
// 参照は常に実体を持たないといけない。
SomeClass& obj_ref = original;
```

またインスタンスに近い概念であるポインタは、nullptrを許容するのでそれが制御上の問題に繋がる。

```cpp:ポインタ渡し(C++)
// nullptrが許容されてしまう
SomeClass* obj_ref = nullptr;

// つまり、途中でこのような処理がなければ実行時例外が起きる
if( obj_ref == nullptr) {
 ...(処理)...
}

// originalはSomeClass型の実体のあるデータ
// 参照は常に実体を持たないといけない。
obj_ref = &original;
```

ところで、Javaのルールに基づいて**インスタンス**を発明したことで、抜本的にこの問題が解決されているのだ。
つまり、インスタンスはそこでは常に参照を渡し続けると出来るのだ。

```java:インスタンスを渡す
SomeClass obj = new SomeClass();

// ☆ obj2を生成するときに、objを参照渡し
SomeClass2 obj2 = new SomeClass2(obj);
```

---

だが私の印象だが、これが原因で、**当時、C言語/C++を中心に開発してきたエンジニアは、JavaやC#、objective-Cなどのオブジェクト指向型の言語で挫折する傾向が強かったように思う。**
☆の部分で、まさかobjが変更される可能性があるとは思うまい。C++の言語的には、

```cpp
SomeClass2* obj2 = new SomeClass2(obj);
```

と書かれりゃ、

```cpp
class SomeClass2 {
 public:
  SomeClass2(SomeClass obj) {
   ...(処理)...
  }

  ...(以下省略)
};
```
と勘違いする人と、

```cpp
class SomeClass2 {
 public:
  SomeClass2(const SomeClass& obj) {
   ...(処理)...
  }

  ...(以下省略)
};
```
と何となく意識づけ出来る人と分かれてしまうからだ。

その対策として、C#では**値クラス**が導入されたり、C++でも構造体とクラスは別の役割をするように調整されたりしたわけだが、私の印象ではバリバリポインタを使ってくるエンジニアほど、ここのところは弱いという印象があった。
一つの障壁になってしまっていたのが、悲しい。


### 革命的な文法 (2) インタフェースとポリモーフィズム

また、Javaにおいて**インタフェースクラス**も重要な文法表現である。

C++では、**多重継承**がサポートされている。

```cpp
class SubClass : public SuperClassA, public SuperClassB {
 ...(実装)...
};
```

この多重継承の最大の利点は、様々なクラスの型変換を許容することにある。このように書けば、

```cpp
// originalはSuperClassAで生成されたオブジェクト
auto obj1 = dynamic_cast<SuperClassA*>(original);
```

と書くことを許容するが、このdynamic_castはSuperClassB*に対してはnullptrを返却する。

それをJavaでは、

- 一般的なクラスの多重継承は禁止とする。
- 多重継承はインタフェースのみ許容し、インタフェースに存在するメソッドは全て抽象化され、オーバーライドしないといけない。

のルールを追加した。このようにしたことで、

```java

interface IntarfaceA {
 ...(実装)...
}


interface IntarfaceB {
 ...(実装)...
}

public class SubClass extends SuperClass implements InterfaceA, interfaceB {
 ...(実装)...
}
```

と書けるようになり、さらにポリモーフィズムに破綻せずに、

```java
// originalはSubClass型のインスタンス
interfaceA obj_a = original;
interfaceB obj_b = original;
```

とする記載を許容することが出来たのだ。

こうすることでの最大のメリットは、オブジェクト指向の基本的な考え方である**is-a関係を破綻させていないところにある。**
GoFのデザインパターンも、is-a関係あってこそ成立するものである。**デザインパターンがオブジェクト指向の基礎教材となり、色々なデータ構造を表現できるようになったのは言うまでもない。**

これは大きなポイントであり、古きJavaを語る上で**マルチスレッド**や**EventListener**を使うときに重要な部分となった。


### EventListener型の発明　～ Delegate型との大きな違い ～

このEventListenerを聞くのは、現在では一部のJavaScriptネイティブでやっている人しかいないと思われるが、これも非常に画期的な仕組みだった。どう画期的かと言うと、**イベントリスナークラス**を定義してそのGUIに登録するだけでイベントの挙動を表せてしまうわけだ。

確かに、この仕組みはややこしいものであったが、このことにより**イベントを共通のオブジェクト化する考え方**が一般的になったのもある。
GUIに**ActionListener**と呼ばれるインタフェースを用意しておき、**そのインタフェースを継承したクラスを開発者が作り、それを登録する**。

例えば同期のC#ではこうした設計をするとき、delegateを採用するだろう。Windows Formsの例であるが

```C#
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      MessageBox.Show("ボタンがクリックされました！");
    }
  }
```

という感じで、あくまでデザインビューワの中にbutton1_Clickを仕込ませて構成する。
ここで、フォームに存在するボタンGUIは別にメソッド**OnClick**を用意しておき、実際はdelegateで**button1_Clickを実行するように仕事を投げる**。

この仕組みは一見快適で、逆に**Windowsアプリケーションの仕組みが楽すぎて、他のフレームワークに移行できない人が増えている原因になっている**のだが、もう一つ大きな問題を抱えている。

それは**「Formの実装の中に処理が潜んでしまうこと」だ**。
つまりこうしたコードを書いてしまうと、MVPパターンで言うところの**フォームのViewの中に、ボタンイベントであるPresenterの処理が混在してしまう**。

技量がなくモジュール分割の習慣がついていないエンジニアなら、**下手したらそのPresenterの中にModelとViewを一緒にごちゃ混ぜにして書く惨事すら招く**のだ。もはやそんな状況では、MVPモデルなんて言うものは存在しないだろう。

それをJavaではEventListenerの形式で回避していて、

```Java:リスナークラス
class MyActionListener implements ActionListener {
 MyApplet applet;

 public MyActionListener(MyApplet applet) {
  this.applet = applet;
 }

 //ActionListener インタフェースの実装
 public void actionPerformed(ActionEvent e) {
  ...(Modelの処理やViewのプロパティに該当する値を変更する)...
 }
}
```

```Java:GUIクラス
public class MyApplet extends Applet {
 private Button btnBlue;
 private MyActionListener actionListener;

 ... (略)...

 public void init() {
  btnBlue = new Button("blue");
  actionListener = new MyActionListener(this);

  btnBlue.addActionListener(eh);
 }
}

```

こうすることで、少なくとも(Viewの一部＋Modelの一部の処理)をListenerが、(Viewの処理)をAppletが担ってくれるようになるので、
設計が分かっていれば少しは上手く出来るようになる。

**ただ、多分MVPモデルをきちっと意識して設計した人がいたかはかなり怪しい。解説書を読んでもそういうことには触れなかった。**
**実際、WPFが出てからMVVMに対する布教が進んできたという印象があるので、**当時のプログラマーも要素分割の概念があったかはちょっと分からない。~~私は(当時)あくまでホビーユースだったから~~

# 10年前の自分に伝えたいこと

実は、こうした20年前の技術があったり、色々と画期的な設計を目指したJavaであったが、ある時期からそのJavaをやるのをやめたのであった。

その理由のきっかけは色々あるが、

- **Java 6からのアップデートがあまり行われなかったこと**
- **プラグインを使う方法がセキュリティセーフではなかったこと**
- **Oracle社の買収**~~

などが挙げられる。

まあ、アルゴリズムの分野に関して言えばJavaで作られた成果物を結構見るし、それなりに上手く動くので、**教育的な部分に関しては**それなりに使えた面はあったけれど、既に当時から限界な感じはちょっと見えていたのであった。

また、Javaを躍進させた**モバイル開発**の業界は確かに今も堅調だと思うのだけど、
少なくともPCを中心にやっていく私の世界だと、当面手を引かないといけない状況になっていたのも事実だ。

それが現在、安定期も終わり徐々に衰退期に近づいているような。

**Oracle社が(アップデートを重ねることで)独自のDBシステムと共に既得権益化したこと**、
**openjdkはGPL化され、Javaで書いたコード以外のライセンス汚染が問題になること**

を誰が想像しただろうか？

もし、私が10年前の自分にいえるとすれば、
**「今すぐモバイル開発にさらに時間を集中させるか、C++の制御技術やパターン認識の知識をもっと深めろ」**
と言っているかもしれません。