In [3]:
# MASTER ONLY
import re
# imports %%solution, %%submission, %%template, %%inlinetest, %%studenttest, %autotest
%load_ext prog_edu_assistant_tools.magics
from prog_edu_assistant_tools.magics import report, autotest
# ASSIGNMENT METADATA
assignment_id: "NlpIntro"
Write a function that counts the occurrences of bigrams within some given text, and returns this in a dictionary. Each word is separated by a space (' ').
When given an input string
print(count_bigrams('hello there i am a friendly robot saying there i am'))
the function count_bigrams should print the following dictionary:
{
'a friendly': 1,
'am a': 1,
'friendly robot': 1,
'hello there': 1,
'i am': 2,
'robot saying': 1,
'saying there': 1,
'there i': 2,
}
"""
# EXERCISE METADATA
exercise_id: "CountBigrams"
In [4]:
%%solution
def count_bigrams(text):
""" # BEGIN PROMPT
pass
""" # END PROMPT
# BEGIN SOLUTION
words = text.split(' ')
i = 0
bigrams = {}
while i < len(words) - 1:
current_bigram = []
for j in range(i, i + 2):
current_bigram.append(words[j])
concat_bigram = ' '.join(current_bigram)
if concat_bigram in bigrams:
bigrams[concat_bigram] += 1
else:
bigrams[concat_bigram] = 1
i += 1
return bigrams
# END SOLUTION
In [5]:
%%studenttest CountBigramsStudentTest
assert len(count_bigrams('hello there')) == 1
assert count_bigrams('hello there')['hello there'] == 1
assert count_bigrams('yes or yes or')['yes or'] == 2
assert count_bigrams('yes or yes or')['or yes'] == 1
In [6]:
%%inlinetest CountBigramsAutograderTest
try:
count_bigrams
except:
assert False, "Did you define count_bigrams?"
try:
count_bigrams('hello world')
except Exception as e:
assert False, "count_bigrams() returned error: " + str(e)
assert len(count_bigrams('hello')) == 0, 'Are you creating bigrams with less than two words?'
assert 'hello there' in count_bigrams('hello there'), 'Are you joining words back together correctly?'
assert count_bigrams('hello there hello there')['hello there'] == 2, 'Are you correctly counting the bigrams?'
In [7]:
result, log = %autotest CountBigramsAutograderTest
from IPython.core import display
display.display(report(CountBigramsAutograderTest, results=result.results))
assert(result.results['passed'])
In [8]:
# Uncomment and run the following line for autograding your solution:
#Submit('CountBigrams')
Write a function that counts the occurrences of n-grams within some given text, and returns this in a dictionary. These are more general than bigrams, and contain n words each. These can be useful for longer phrases. Each word is separated by a space (' ').
"""
Prints the following dictionary:
{
'i am a': 1,
'robot saying there': 1,
'am a friendly': 1,
'hello there i': 1,
'there i am': 2,
'friendly robot saying': 1,
'saying there i': 1,
'a friendly robot': 1,
}
"""
print(count_ngrams('hello there i am a friendly robot saying there i am'), 3)
# EXERCISE METADATA
exercise_id: "CountNgrams"
In [9]:
%%solution
def count_ngrams(text, n):
""" # BEGIN PROMPT
pass
""" # END PROMPT
# BEGIN SOLUTION
words = text.split(' ')
i = 0
ngrams = {}
while i < len(words) - (n - 1):
current_ngram = []
for j in range(i, i + n):
current_ngram.append(words[j])
concat_ngram = ' '.join(current_ngram)
if concat_ngram in ngrams:
ngrams[concat_ngram] += 1
else:
ngrams[concat_ngram] = 1
i += 1
return ngrams
# END SOLUTION
In [10]:
%%studenttest CountNgramsStudentTest
assert len(count_ngrams('hello there', 2)) == 1
assert len(count_ngrams('hello there', 3)) == 0
assert count_ngrams('yes or yes', 3)['yes or yes'] == 1
assert count_ngrams('yes or yes', 1)['yes'] == 2
In [11]:
%%inlinetest CountNgramsAutograderTest
try:
count_ngrams
except:
assert False, "Did you define count_ngrams?"
try:
count_ngrams('hello world', 3)
except Exception as e:
assert False, "count_ngrams() returned error: " + str(e)
assert len(count_ngrams('hello hello hello', 2)) == 1, 'Are you creating ngrams correctly? Expected to see only a bigram "hello hello" with the input "hello hello hello", but got [%s]' % (",".join(count_ngrams('hello hello hello', 2).keys()))
assert len(count_ngrams('hello there', 3)) == 0, 'Are you creating ngrams with fewer than n words?'
assert count_ngrams('yes yes yes', 1)['yes'] == 3, 'Are you correctly counting the ngrams?'
In [12]:
result, log = %autotest CountNgramsAutograderTest
from IPython.core import display
display.display(report(CountNgramsAutograderTest, results=result.results))
assert(result.results['passed'])
In [13]:
# Use this cell to submit your exercise to autograder. Uncomment the following line:
#Submit('CountNgrams')
In [14]:
#@title MeCabのインストールとインポート
!pip install mecab-python3
In [15]:
# GLOBAL CONTEXT
import MeCab
# 日本語文章をトークン化する関数
def tokenize_japanese(sentence):
tagger = MeCab.Tagger()
text = sentence
node = tagger.parseToNode(text)
words = []
while(node):
if node.surface != "":
words.append(node.surface)
node = node.next
if node is None:
break
return words
In [16]:
# GLOBAL CONTEXT
from math import sqrt
# ベクターのコサイン類似度の計算する関数
# article1とarticle2のフォマットは{word: frequency}
def cosine_similarity(article1, article2):
numerator_sum = 0
# 共通の単語のみの足し算を計算する
for word1 in article1:
for word2 in article2:
if word1 == word2:
numerator_sum += article1[word1]*article2[word2]
# 各ベクターの全ての単語の二乗した出現回数を足し算する
article1_squared_sum = 0
for word in article1:
article1_squared_sum += article1[word]**2
article2_squared_sum = 0
for word in article2:
article2_squared_sum += article2[word]**2
return numerator_sum / (sqrt(article1_squared_sum)*sqrt(article2_squared_sum))
In [17]:
#@title ウィキペディア記事「Python」をpython_article変数に読み込む
python_article = """
Python
Python(パイソン)は、汎用のプログラミング言語である。コードがシンプルで扱いやすく設計されており、C言語などに比べて、さまざまなプログラムを分かりやすく、少ないコード行数で書けるといった特徴がある。
文法を極力単純化してコードの可読性を高め、読みやすく、また書きやすくしてプログラマの作業性とコードの信頼性を高めることを重視してデザインされた、汎用の高水準言語である。
核となる本体部分は必要最小限に抑えられている。一方で標準ライブラリやサードパーティ製のライブラリ、関数など、さまざまな領域に特化した豊富で大規模なツール群が用意され、インターネット上から無料で入手でき、自らの使用目的に応じて機能を拡張してゆくことができる。
またPythonは多くのハードウェアとOS (プラットフォーム) に対応しており、複数のプログラミングパラダイムに対応している。Pythonはオブジェクト指向、命令型、手続き型、関数型などの形式でプログラムを書くことができる。動的型付け言語であり、参照カウントベースの自動メモリ管理(ガベージコレクタ)を持つ。
これらの特性によりPythonは広い支持を獲得し、Webアプリケーションやデスクトップアプリケーションなどの開発はもとより、システム用の記述 (script) や、各種の自動処理、理工学や統計・解析など、幅広い領域における有力なプログラム言語となった。プログラミング作業が容易で能率的であることは、ソフトウェア企業にとっては投入人員の節約、開発時間の短縮、ひいてはコスト削減に有益であることから、産業分野でも広く利用されている。Googleなど主要言語に採用している企業も多い。
Pythonのリファレンス実装であるCPythonは、フリーかつオープンソースのソフトウェアであり、コミュニティベースの開発モデルを採用している。CPythonは、非営利団体であるPythonソフトウェア財団が管理している。その他の実装としては、PyPyやIronPythonなどが有名である。
Pythonは、オランダ人のグイド・ヴァンロッサムが開発した。名前の由来は、イギリスのテレビ局 BBC が製作したコメディ番組『空飛ぶモンティ・パイソン』である。Pythonという英単語が意味する爬虫類のニシキヘビがPython言語のマスコットやアイコンとして使われている。
Pythonはインタプリタ上で実行することを前提に設計している。以下の特徴をもっている:
Pythonの最初のバージョンはAmoeba上で開発された。のちに多くの計算機環境上で動作するようになった。
Pythonには複数の実装が存在する。
Python のリリースは全てオープンソースであり、PSF (Python Software Foundationライセンス)として配布されている。これはGPL互換であるが、GPLと異なり、変更したバージョンを配布する際に変更をオープンソースにしなくてもよい。
元々はAmoebaの使用言語であるABC言語に例外処理やオブジェクト指向を対応させるために作られた言語である。
1991年にヴァンロッサムがPython 0.90のソースコードを公開した。この時点ですでにオブジェクト指向言語の特徴である継承、クラス、例外処理、メソッドやさらに抽象データ型である文字列、リストの概念を利用している。これはModula-3のモジュールを参考にしていた。
1994年1月、Python 1.0を公開した。主な特徴として関数型言語の基本であるラムダ計算を実装、map関数、reduce関数などを組み込んだ。
バージョン1.4ではCommon Lispにある機能とよく似たキーワード引数を導入した。また簡易ながら名前修飾を用いたカプセル化も実装した。
2000年に公開。ガベージコレクションやUnicode、リストを導入した。一躍メジャーな言語となった。多くの機能はHaskellを参考にして導入している。
2.6以降のバージョンには、2.xから3.xへの移植を助ける「2to3 ツール」と「lib2to3 モジュール」を含んでいる。2.xのサポートは2020年までとされている。
2008年、長い試験期間を経てPython 3.0が公開された。
開発初期には、西暦3000年に公開予定の理想のPythonとして、Python 3000と呼んでいた。Py3Kと略すこともある。
しかし2.xとの後方互換性が損なわれている。当初は2.xに比べて3.xが利用できるライブラリ等が著しく少ないという問題点があったが、Djangoなど徐々に3.xに対応したフレームワークやライブラリなどが増えていったこともあり、2016年時点においては新規のプロジェクトについて3.xで開発することが多くなっている。
2015年11月にリリースされたFedora 23や2016年4月にリリースされたUbuntu 16.04 LTSでは、デフォルトでインストールされるPythonのバージョンが2.xから3.xに変更されている。
Pythonには、読みやすく、それでいて効率もよいコードをなるべく簡単に書けるようにするという思想が浸透しており、Pythonコミュニティでも単純で短いコードをよしとする傾向が強い。
Pythonの本体は、ユーザがいつも必要とする最小限の機能のみを提供する。基本機能以外の専門機能や拡張プログラムはインターネット上にライブラリとして提供されており、別途ダウンロードして保存し、必要なツールはこのツールキットからその都度呼び出して使用する。
またPythonでは、Perlの「あることを行うのに1つ以上の方法がある」という哲学とは逆に、ある動作をさせる方法は、基本的に1通りしかないように作られている。そのためPythonのプログラムは、誰が書いてもだいたいどれも同じようなコードになり、作成者以外が見ても動作を把握しやすい。また、Pythonではプログラムの文書化(ソフトウェアドキュメンテーション)が重視されており、言語の基本機能の一部となっている。
インデント(「オフサイドルール」)が特徴的である。
以下に、階乗を題材にC言語と比較した例を示す。
Pythonのコード:
わかりやすく整形されたC言語のコード:
この例では、Pythonと整形されたC言語とでは、プログラムコードの間に違いがほとんど見られない。しかし、C言語のインデントはルール(構文規則上のもの)ではなく、単なるコンベンション(コーディングスタイル)でしかない。そのためC言語では全く同じプログラムを以下のように書くこともできる。
わかりにくいC:
Pythonではインデントは構文規則として決められているため、こうした書き方は不可能である。Pythonではこのような強制を課すことによって、プログラムのスタイルがその書き手にかかわらずほぼ統一したものになり、その結果読みやすくなるという考え方が取り入れられている。これについては賛否両論があり、批判的立場の人々からは、これはプログラマがスタイルを選ぶ自由を制限するものだ、という意見も出されている。
インデントによる整形は、単に「見かけ」だけではなく品質そのものにも関係する。例として次のコードを示す。
間違えたC:
このコードはC言語の構文規則上は問題無いが、インデントによる見かけのifの範囲と、言語仕様によるifの実際の範囲とが異なっているため、プログラマの意図が曖昧になる。この曖昧さは、検知しにくいバグを生む原因になる。
ソースコードを読む際、多くの人はインデントのような空白によって明確に整列されたコードを目安として読み、コンパイラのように構文解析しながらソースを読むものではない。その結果、一見しただけでは原因を見つけられないバグを作成する危険がある。
Pythonではインデントをルールとすることにより、人間が目視するソースコードの理解とコンパイラの構文解析の間の誤差を少なくすることで、より正確に意図した通りにコーディングすることができると主張されている。
Pythonのデータは動的に型付けされる。値自身が型を持っており、変数はすべて値への参照である。
基本的なデータ型として、整数型・多倍長整数型・浮動小数点数型・複素数型・文字列型・Unicode文字列型・論理型、そして関数型がある。多倍長整数型は(メモリの許す限り)無制限の桁数で整数計算が可能である。
さらに組み込みのコンテナ型として、リスト型、タプル型、辞書型(連想配列)のほか、値の重複を許さない集合型(Python 2.3以降)がある。
Python 3.x以降では、整数型が多倍長整数型と統合され、従来の文字列型とUnicode文字列型に代わり、バイト列型と文字列型が導入された。
リスト型および辞書型は内部の値をあとから変えられる(、変更可能)が、タプル型は一度構築したら内部の値は変わらない(、変更不能)。タプル型とリスト型は、多くのプログラミング言語では配列と呼ばれるものに類似している。しかし、Pythonではタプル型は辞書のキーとして使うことができるが、リスト型は内容が変わるため辞書のキーとして使うことはできないという理由から、これら2つの型を区別している。集合型には変更可能なものと変更不能なものの2種類がある。
多くのオブジェクト指向プログラミング言語と同様、Pythonではユーザが新しく自分の型を定義することも可能である。この場合、組み込み型を含む既存の型を継承して新たな型(クラス)を定義する事も、ゼロから全く新しい型を作り出す事も出来る。
Pythonは基本的にメソッドや関数の引数に型を指定する必要がないので、内部で必要とする演算子やメソッドに対応していれば、関数やオブジェクトの設計時点で意図していなかったオブジェクトを引き渡すことも可能である(いわゆるダック・タイピングが可能)。
Pythonはガベージコレクションを内蔵しており、参照されなくなったオブジェクトは自動的にメモリから破棄される。CPythonでは、ガベージコレクションの方式として参照カウント方式とマーク・アンド・スイープ方式を併用している。マーク・アンド・スイープ方式のみに頼っている言語では、オブジェクトがいつ回収されるか保証されないので、ファイルのクローズなどをデストラクタに任せることができない。CPythonは参照カウント方式を併用することで、循環参照が発生しない限り、オブジェクトはスコープアウトした時点で必ずデストラクトされることを保証している。なおJythonおよびIronPythonではマーク・アンド・スイープ方式を採用しているため、スコープアウトした時点で必ずデストラクトされることが前提のコードだとJythonやIronPythonでは正しく動かない。
イテレータを実装するためのジェネレータが言語仕様に組み込まれており、Pythonでは多くの場面でイテレータを使うように設計されている。イテレータの使用はPython全体に普及していて、プログラミングスタイルの統一性をもたらしている。
Pythonでは扱えるデータの全てがオブジェクトである。単純な数値といった基本的なデータ型をはじめ、組み込みのコンテナ型、組み込み関数など、これらは全て統一的な継承関係をもつオブジェクトであり「型」をもっている。これらの組み込み型とユーザ定義型は区別されず、組み込み型を継承したクラスを定義できる。上の「データ型」の項で述べたように Pythonは静的な型チェックを持たないため、Javaのようなインターフェイスという言語上の仕組みは必要とされない。
クラスの継承 () メカニズムでは、複数の基底クラスを持つことができ(多重継承)、導出されたクラスでは基底クラスの任意のメソッドをオーバライド(、上書き)することが可能である。
また、オブジェクトには任意のデータを入れることができる。これらのメソッドやデータは、基本的に、すべてcodice_1であり、codice_2(仮想)である。ただし、先頭にアンダースコアをもつメンバをcodice_3とすることができる。これは単なるマナーであるが、アンダースコアを2つもつ場合は、クラスの外部からメンバの名前を隠された状態(、難号化)とすることでカプセル化を実現できる。また、利用者定義演算子が機能として用意されておりほとんどの組み込み演算子(算術演算子()や添字表記)はクラスインスタンスで使うために再定義することが可能となっている。
Pythonには「電池が付属しています()」の思想があり、プログラマがすぐに使えるようなライブラリや統合環境をあらかじめディストリビューションに含めるようにしている。このため標準ライブラリは非常に充実している。
サードパーティによるライブラリも豊富に存在する。
マイナーなものまで含めると多すぎて収拾がつかない。
Python Package Index (PyPI) と呼ぶ公式のパッケージリポジトリを導入した。
Pythonは当初1バイト単位での文字列型のみ扱い、かな漢字のようなマルチバイト文字をサポートしていなかったが、Python 2.0からUnicode文字型が新たに導入された。
Python 3.0では、文字列型がバイト列型に、Unicode文字列型が文字列型に変更された。従来は文字列の表現方法として2通り(旧文字列型と旧Unicode文字列型)があったが、これを1通り(新文字列型=旧Unicode型)に統一し、旧文字列型は単なるバイト列型として再定義された。これにより、Python 3.0で文字列を扱う際には後述の変換処理を必ず行う必要がある。ファイル入出力などエンコードを明示しなければ標準エンコードを用いて暗黙に行われる場合も多い。これにより多言語の扱いを一貫したものにしている。
Pythonでは文字のバイト列表現(エンコーディング)とUnicodeの内部表現を明確に区別している。Unicode文字はメモリ中に保持される抽象的なオブジェクトであり、画面表示やファイルへの入出力の際には変換ルーチン(コーデック)を介して特定のエンコーディングのバイト列表現と相互変換する。また、ソースコード中の文字コードを認識する機能があり、これによって異なる文字コードで書かれたプログラムの動きが異なるという危険を解消している。
Pythonでは変換ルーチンをモジュールとして追加することで、さまざまなエンコーディングに対応できるようになっている。日本語の文字コード (EUC-JP, Shift_JIS, MS932, ISO-2022-JP) に対応したコーデックも作成されている。Python 2.4からは、日中韓国語用のコーデックが標準でディストリビューションに含まれるようになったため、現在では日本語の処理に問題はほとんどなくなった。ただしGUIライブラリであるTkinterや統合開発環境のIDLEは、プラットフォームにもよるが、まだきちんと日本語に対応していないものもある。
ソースコードの文字コードは、ASCIIと互換性があり、Pythonが対応しているものを使用する。デフォルトエンコーディング以外の文字コードを使う場合は、ソースファイルの 1行目か 2行目に一定の書式でコメントとして記述することになっており、しばしば以下のようにEmacsやVimなどのテキストエディタにも認識可能な書式で記述される(次の例は Emacs が認識できる書式)。
Pythonはおもに欧米の企業でよく使われている。大企業ではマイクロソフトやアップルなどのパッケージソフトウェア企業をはじめ、Google、Yahoo!、YouTube などの企業も利用している。また携帯電話メーカーのノキアでは、S60シリーズでPythonアプリケーションが動く。研究機関では、NASAや日本の高エネルギー加速器研究機構でPythonが使われている。
適応範囲はWebプログラミング、GUIベースのアプリケーション、CAD、3Dモデリング、数式処理など幅広い分野に及ぶ。さらにスクリプト言語としての特性から、従来Perlやシェルスクリプトが用いられることの多かったシステム管理用のスクリプトとして採用しているOSも複数ある。また、多くの異なる言語で書かれたモジュールをまとめるグルー言語としての利用例も多い。実際、多くの商用アプリケーションで Python は組み込みのスクリプト言語として採用されている。
またNumPy、SciPyなどの高速な数値計算ライブラリの存在により、科学技術コンピューティングにもよく用いられる。NumPy、SciPyの内部はC言語で書かれている為に動的スクリプト言語の欠点の一つである速度の遅さを補っている。
Pythonは教育目的で設計されたわけではないが、単純さから子供が最初に学ぶ、プログラミング教育用の言語としても利用が増えている。グイド・ヴァンロッサムはPython設計以前に教育用言語であるABCの開発にかかわり、教育用としての利用について期待感を示したこともあり、方針として非技術者向けといった利用を視野に入れているとされることもある。
私の大好きなPython利用法は、騒ぎ立てずに、言語教育でプログラミングの原理を教えること。それを考えてくれ――次の世代の話だね。-- スラッシュドット・ジャパン『 Guido van Rossum へのインタビュー』
"""
In [18]:
#@title ウィキペディア記事「C++」をcpp_article変数に読み込む
cpp_article = """
C++
C++(シープラスプラス)は、汎用プログラミング言語の一つである。日本語では略してシープラプラ、シープラなどとも呼ばれる。
1983年にベル研究所のコンピュータ科学者のビャーネ・ストロヴストルップが、C言語の拡張として開発した。当時の名前は「」(クラス付きのC言語)だった。拡張はクラスの追加に始まり、仮想関数、多重定義、多重継承、テンプレート、例外処理といった機能が続いていった。
標準規格化がISOとIEC共同で行われており、現在最新のバージョンは、2017年に制定されたISO/IEC 14882:2017、通称「C++17」である。
表現力と効率性の向上のために、手続き型プログラミング・データ抽象・オブジェクト指向プログラミング・ジェネリックプログラミングの複数のプログラミングパラダイムを組み合わせている。アセンブリ言語以外の低水準言語を必要としない、使わない機能に時間的・空間的費用を要しないことが、言語設計の重要な原則となっている。また、静的な型システムを持つ。
ストロヴストルップはプログラミング言語C with Classesの開発を1979年に開始した。彼は大規模なソフトウェアの開発に有用な特徴をSimulaが備えていることに気がついたが、Simulaは実行速度が遅く実用的ではなかった。一方でBCPLは実行速度こそ速かったものの、大規模なソフトウェア開発を念頭に置いた場合にあまりにも低級だった。
これらの事情を鑑みて、ストロヴストルップは当時既に汎用的な言語だったC言語にSimulaの特徴を取り入れることを試みた。この取り組みにあたってはALGOL68 やAda、 CLU、 ML等の言語の影響も受けている。最初はクラスと派生クラス、型検査機構の強化、インライン関数、デフォルト引数の機能を、Cfrontを介してC言語に追加した。1985年10月に最初の商用リリースがなされた。
1983年にはC with ClassesからC++に名称を変更した。この際に、仮想関数と、関数と演算子の多重定義、参照型、codice_1型、ユーザー制御可能な自由領域メモリ制御、型検査機構の改良、BCPL形式(「codice_2」による)の行単位のコメントアウトなどの機能が追加された。1985年には『The C++ Programming Language』の初版が出版された(邦訳『プログラミング言語C++』1988年))。この時点では公式な標準が策定されていなかったために、この本が事実上のリファレンスとなった。1989年C++のヴァージョン2.0として、多重継承と抽象クラス、静的メンバ関数、codice_1メンバ関数、codice_4メンバ等の機能が追加されたものがリリースされた。1990年に『The Annotated C++ Reference Manual (ARM)』(邦訳『注解C++リファレンスマニュアル』)が出版され、将来の標準化の土台となるものを提供した。後に追加された機能にはテンプレートと例外処理、名前空間、新形式のキャスト、ブール型が含まれた。
ARMが事実上の標準として使われた時代が続いたが、標準化が進んだ。C++言語の最初の標準は1998年にISO/IEC 14882:1998として承認された。2003年の改訂版を経て、2011年にメジャーアップデートとして制定されたのがISO/IEC 14882:2011、通称「C++11」である。このバージョンは、元々、非公式に「C++0x」と呼ばれていた。2000年代中に制定され、正式に「C++09」と呼称されることを見越した仮称だったが、2000年代中には実現しなかった。2011年8月10日まで続いた最終国際投票で C++0x は全会一致で承認された。これにより C++0x と呼ばれてきた C++ の次期改正案はついに国際標準になり、C++11と呼べるようになった。また、2014年にはISO/IEC 14882:2014、通称「C++14」が策定された。2018年現在の最新バージョンは2017年に策定されたISO/IEC 14882:2017、通称「C++17」である。2020年にはISO/IEC 14882:2020、「C++20」が策定される予定である。
C++言語の進化に伴い、標準ライブラリもまた進化していった。C++標準ライブラリに最初に追加されたのは、従来のC言語の codice_5 や codice_6 といった関数を置き換えるストリームI/Oライブラリである。また、C++98における標準ライブラリへの追加で最も重要なものはStandard Template Library (STL)である。C++11では、正規表現による検索・置換や複数スレッドでの同時実行、ハッシュテーブル・ハッシュセットの追加などさらなる拡充が続いている。
長年にわたる作業の後、ANSIとISOの合同委員会はC++言語を1998年に標準化した(ISO/IEC 14882:1998)。1998年の標準の公式なリリースから数年間に渡って委員会は不具合の報告を続け、2003年に訂正版を出版した。2003年12月に制定された日本工業規格JIS X 3014:2003(プログラム言語 C++)は、ISO/IEC 14882:2003(E)の日本語への翻訳である。
2007年11月15日に『C++ Technical Report 1』 (TR1)というテクニカルレポートがリリースされた。これは標準の公式な一部ではないが、次のバージョンのC++に含まれると期待される、標準ライブラリへの数多くの拡張を与えた。TR1の内容は、多少の修正を加えてC++11に取り込まれている。
2011年9月1日、C++98以来初の大きな改訂となるISO/IEC 14882:2011が発行された。
2014年8月18日、ISO/IEC 14882:2014(C++14)が投票で承認され、2014年12月15日、公式に出版された。
2017年12月、ISO/IEC 14882:2017(C++17)が公式に発行された。
現在、C++20の仕様策定が進められている。
C++に対しては、今もなお要望が絶えない。特にBoostはC++の方向性の決定に大きく貢献し、さらにC++標準化委員会へ改良すべき点などを意見している。現在はマルチパラダイムプログラミングをより自然に行えるようにすることに力が注がれており、たとえばBoostでは、C++の関数型プログラミングやメタプログラミングの可能性を模索している。
C++11と呼ばれている新しいバージョンのC++標準ではこれらの一部が取り込まれ、今後のC++でもさらなる追加が行われると見られている。
この名称はRick Mascittiの功績で、最初に使用されたのは1983年の12月である。初期の研究期間では、開発中の言語は「C with Classes」と呼ばれていた。最終名は、変数の値を一つ加算する、C言語のcodice_7(インクリメント)演算子からの派生である。また一般的な命名規則での「+」の使用は、機能強化されたコンピュータプログラムを意味する。ストロヴストルップによれば「この名前は、C言語からの変更の革新的な本質を示している」ということである。C+は、より初期の無関係なプログラミング言語の名前である。
ストロヴストルップは著書『The C++ Programming Language』の前文で名前の起源を語り、ジョージ・オーウェルの小説『1984年』の付録から「C++」が連想されるかもしれないと付け加えている。新語法という架空の言語の解説に宛てられた3つの章の中に、科学技術に関する専門用語とジャーゴンの解説に宛てられた「C vocabulary」という章がある。新語法で「ダブルプラス」は最上級の修飾語である。ゆえに新語法で「C++」は「最も極端な専門用語またはジャーゴン」という意味になるだろう。
1992年、Rick Mascittiは名前について非公式に質問されると、彼はおふざけのつもりで命名したという旨の回答をした。彼はこの言語の正式な名称になるとは夢にも思っていなかった。
ビャーネ・ストロヴストルップは著書『(1994)』でC++を設計する際に用いたルールを述べている。
C++のコンパイラがどのようにコードを出力しメモリのレイアウトを決めるのかということについては『Inside the C++ Object Model』(Lippman, 1996)に記載されている。ただしコンパイラが出力するコードの仕様はコンパイラ制作者の裁量に任されている。
1998年に施行されたANSI/ISO C++ 規格は言語仕様とライブラリの2つのパートで構成される。ライブラリ規格の大半はStandard Template Library (STL)とC言語の標準ライブラリの改良版についての内容である。標準規格以外にも様々なライブラリが数多く存在し、リンカを使用することにより、C言語、FORTRAN、Pascal、BASICのような言語を用いて作成されたライブラリを利用できる。規格外のライブラリが利用できるかどうかはコンパイラに依存する。
C++標準ライブラリはC++向けに若干の最適化が施されたC言語標準ライブラリを含んでいる。C++標準ライブラリの大部分はSTLである。 コンテナ(可変長配列やリストなど)、コンテナを配列のように扱えるようにするイテレータ、検索やソートを行うアルゴリズムといった有用なツールが提供されている。さらにcodice_8やcodice_9のような連想配列や、codice_10やcodice_11のようなソート済みコンテナも提供され、これらは全てインターフェイスに互換性がある。テンプレートを用いることにより、あらゆるコンテナ(またはイテレータで定義したシーケンス)に適用できる汎用的なアルゴリズムを記述できる。C言語と同様にライブラリの機能にはcodice_12 ディレクティブを使ってヘッダファイルを読み込むことによってアクセスする。C++には69本の標準ヘッダファイルがあるが、このうち19本については非推奨となっている。
STLは標準規格に採用される前は、ヒューレット・パッカードの(一時はシリコングラフィックスの)商用ライブラリだった。STLは標準規格の単なる一部分に過ぎず規格書にSTLという表記は見られないが、入出力ストリーム、国際化、デバッグ機能、C言語標準ライブラリ等の、STL以外の部分と区別するために、今でも多くの人がSTLという用語を使っている。
大半のC++コンパイラはSTLを含むC++標準ライブラリの実装を提供している。STLPortのようなコンパイラ非依存のSTLも存在する。様々な目的でC++標準ライブラリを独自に実装しているプロジェクトは他にもある。
C++の標準ライブラリは大きく次のように分けられる。多種多様な実行環境が存在することを考慮して、GUIに関するライブラリは標準に含まれていない。
以下に、C++で広く使われていると思われるライブラリを挙げる。
C言語に、オブジェクト指向プログラミングをはじめとする様々なプログラミングパラダイムをサポートするための改良が加えられたものといえる。ただし、他のプログラミング言語と違い、旧来のCと同様に手続き型言語としても扱えるという特徴がある。このことから、C++を"better C"というふうに呼ぶことがある。すなわち、基本的にC言語に対して上位互換性がある。初期のC++はCへのトランスレータとして実装され、C++プログラムを一旦Cプログラムに変換してからコンパイルしていた。
ただし、C++という名称が定まった当初の時期から、C言語とC++との間には厳密な互換性はない。当時、Cとの互換性について議論の末、「C++とANSI Cの間には不正当な非互換性はない」という合意が形成されることとなった。そのため、正当な非互換性を巡って多くの議論が発生した。ただし、まだANSIによるC言語の標準規格も策定途中の時期である。
その後、先祖であるC言語のANSIによる標準規格制定時には、関数のプロトタイプ宣言やcodice_1修飾など、C++の機能がC言語に取り入れられることにもなった。C99の出現により、codice_2コメントなどのC++で使われていた便利な機能が加わってCとC++の互換性が高まる一方、別々に審議し、別の時期に発行していることと、開発対象が必ずしも同じでないために利害関係者が異なることによる違いもある。
次のような多種多様な機能を持っており、言語仕様は大変複雑である。
ここから、よりオブジェクト指向を強化し、「なんでもあり」ではない代わりに分かりやすくスマートな設計を目指した新たな言語(Java、D言語など)が作られることとなった。
C++はC言語およびそのプリプロセッサの構文をほぼ継承している。以下のサンプルはビャーネ・ストロヴストルップの書籍「The C++ Programming Language, 4th Edition」(ISBN 978-0321563842) の「2.2.1 Hello, World!」に記載されている標準C++ライブラリのストリーム機能を用いて標準出力に出力するHello worldプログラムである。
書籍でも明記されているが、codice_15関数で意図的に返り値を返さない手法が使用されている。
C++には四則演算、ビット演算、参照、比較、論理演算などの30を超える演算子がある。メンバーアクセス演算子(codice_16とcodice_17)のような一部の例外はあるが、大半の演算子はユーザー定義によるオーバーロードが可能である。オーバーロード可能な演算子が豊富に揃えられているためC++を一種のドメイン固有言語として利用できる。またオーバーロード可能な演算子はスマートポインタのような先進的な実装テクニックに欠かせないものとなっている。演算子をオーバーロードしても演算の優先順位は変化せず、また演算子のオペランドの数も変化しない。ただし指定したオペランドが無視される可能性はある。
C++には、ジェネリックプログラミングを実現する機能としてテンプレートが存在する。テンプレートにできる対象は、関数とクラスである。テンプレートは型、コンパイル時定数またはその他のテンプレートによってパラメタライズできる。テンプレートはコンパイル時にインスタンス化(実体化・具現化などとも)される。コンパイラは関数やクラスをインスタンス化するためにテンプレート仮引数を特定の値に置き換える。テンプレートはジェネリックプログラミング、テンプレートメタプログラミング、コード最適化などのために利用される強力なツールであるが、一定のコストを伴う。各テンプレートのインスタンスはテンプレート仮引数毎にテンプレートコードのコピーを生成するためコードサイズが肥大化する。コンパイル時に型の情報を削除して単一のテンプレートインスタンスを生成するランタイム型のジェネリクスを実装したJavaなどの言語とは対照的である。
テンプレートとマクロはいずれもコンパイル時に処理される言語機能であり条件に基づいたコンパイルが行われるが、テンプレートは字句の置き換えに限定されない。テンプレートはC++の構文と型を解析し、厳密な型チェックに基づいた高度なプログラムの流れの制御ができる。マクロは条件コンパイルに利用できるが、新しい型の生成、再帰的定義、型の評価などは行えないため、コンパイル前のテキストの置き換えや追加・削除といった用途に限定される。つまりマクロは事前に定義されたシンボルに基づいてコンパイルの流れを制御できるものの、テンプレートとは異なり独立して新しいシンボルを生成することはできない。テンプレートは静的な多態(下記参照)とジェネリックプログラミングのためのツールである。
C++のテンプレートはコンパイル時におけるチューリング完全なメカニズムである。これはテンプレートメタプログラムを用いて実行する前にコンピュータが計算可能なあらゆる処理を表現できることを意味している。
概略すれば、テンプレートはインスタンス化に必要な引数を明確にしなくても記述できるコンパイル時にパラメタライズされる関数またはクラスである。インスタンス化した結果は、テンプレート仮引数に指定した型に特化した形で記述されたコードと全く等価になる。これによりテンプレートは、汎用的かつおおまかに記述された関数及びクラス(テンプレート)と特定の型に特化した実装(インスタンス化されたテンプレート)の依存関係を解消し、パフォーマンスを犠牲にすることなく抽象化できる手段を提供する。
C++はC言語にオブジェクト指向プログラミングをサポートするための改良を加えたものといえる。C++のクラスには、オブジェクト指向言語で一般的な抽象化、カプセル化、継承、多態の4つの機能がある。オブジェクトは実行時に生成されるクラスの実体である。クラスは実行時に生成される様々なオブジェクトのひな形と考えることができる。
なお、C++はSmalltalkなどに見られるメッセージ転送の概念によるオブジェクト指向を採用していない。
カプセル化とは、データ構造を保証し、演算子が意図したとおりに動作し、クラスの利用者が直感的に使い方を理解できるようにするためにデータを隠蔽することである。クラスや関数はC++の基礎的なカプセル化のメカニズムである。クラスのメンバはcodice_18、codice_4、codice_20のいずれかとして宣言され明示的にカプセル化できる。publicなメンバはどの関数からでもアクセスできる。privateなメンバはクラスのメンバ関数から、またはクラスが明示的にアクセス権を与えたフレンド関数からアクセスできる。protectedなメンバはクラスのメンバおよびフレンド関数に加えてその派生クラスのメンバからもアクセスできる。
オブジェクト指向では原則としてクラスのメンバ変数にアクセスする全ての関数はクラスの中にカプセル化されなければならない。C++ではメンバ関数およびフレンド関数によりこれをサポートするが、強制はされない。プログラマはメンバ変数の一部または全体をpublicとして定義でき、型とは無関係な変数をpublicな要素として定義できる。このことからC++はオブジェクト指向だけでなく、モジュール化のような機能分割のパラダイムもサポートしているといえる。
一般的には、全てのデータをprivateまたはprotectedにして、クラスのユーザに必要最小限の関数のみをpublicとして公開することがよい習慣であると考えられている。このようにしてデータの実装の詳細を隠蔽することにより、設計者はインターフェイスを変更することなく後日実装を根本から変更できる
継承を使うと他のクラスの資産を流用できる。基底クラスからの継承はcodice_18、codice_4、codice_20のいずれかとして宣言する。このアクセス指定子により、派生クラスや全く無関係なクラスが基底クラスのpublicおよびprotectedメンバにアクセスできるかどうかを決定できる。普通はpublic継承のみがいわゆる"派生"に対応する。残りの二つの継承方法はあまり利用されない。アクセス指定子を省略した場合、構造体はpublic継承になるのに対し、クラスではprivate継承になる。基底クラスをcodice_24として宣言することもできる。これは仮想継承と呼ばれる。仮想継承は基底クラスのオブジェクトが一つだけ存在することを保証するものであり、多重継承の曖昧さの問題を避けることができる。
多重継承はC++の中でもしばしば問題になる機能である。多重継承では複数の基底クラスから一つのクラスを派生できる。これにより継承関係が複雑になる。例えば"FlyingCat"クラスは"Cat"クラスと"FlyingMammal"クラスから派生できる。JavaやC#では、基底クラスの数を一つに制限する一方で、複数のインタフェースを継承でき、これにより制約はあるものの多重継承に近い機能を実現できる。インタフェースはクラスと異なりメンバ関数を宣言できるのみであり、関数の実装やメンバ変数は定義できない。JavaとC#のインタフェースや抽象クラスはC++の抽象基底クラスと呼ばれる関数宣言のみを持つクラスに相当する。JavaやC#の継承モデルを好むプログラマは、非抽象クラスからのみクラスを派生させる方法を選択できる。この場合は抽象基底クラスのメンバ関数を必ず明示的に定義しなければならず、またこのクラスを継承することはできない。
多態(ポリモーフィズム)はよく多用されているインターフェイスの機能であり、様々な状況下でオブジェクトに異なる振る舞いをさせることができる。
C++は"静的な多態"と"動的な多態"の両方をサポートする。コンパイル時に解決される静的な多態は実行時には考慮されないのに対し、ランタイム時に解決される動的な多態はパフォーマンス的に不利である。
関数のオーバーロードは名称が同じ複数の関数を宣言できる機能である。ただし引数は異なっていなければならない。関数は引数の型や数で区別される。同名の関数はコードの文脈によってどの関数が呼ばれるのかが決まる。関数の戻り値の型で区別することはできない。
関数を宣言する際にプログラマはデフォルト引数を指定できる。関数を呼び出すときに引数を省略した場合はデフォルト引数が適用される。関数を呼び出すときに宣言よりも引数の数が少ない場合は、左から右の順で引数の型が比較され、後半部分にデフォルト引数が適用される。たいていの場合は一つの関数にデフォルト引数を指定するよりも引数の数が異なる関数をオーバーロードする方が望ましい。
C++のテンプレートではより洗練された汎用的な多態を実現できる。特ににより仮想関数のオーバーライドをシミュレートした静的な多態を実装できる。C++のテンプレートは型安全かつ チューリング完全であるため、 テンプレートメタプログラミングによりコンパイラに条件文を再帰的に解決させて実行コードを生成させることにも利用できる。
基底クラスへのポインタ変数及び参照は、正確に型が一致するオブジェクトだけでなく、その派生クラスのオブジェクトを示すことができる。これにより配列やコンテナは複数の型へのポインタを保持できる。ポインタ変数は実行時に値が割り当てられるためこれは実行時の話である。
codice_25は基底オブジェクトから派生オブジェクトへの変換を安全に行うための演算子である(派生オブジェクトから基底オブジェクトへの変換ではキャストは必要ない)。この機能は実行時型情報 (RTTI)に依存している。オブジェクトが特定の派生オブジェクトであることがあらかじめわかっている場合はcodice_26でキャストすることもできる。codice_26は純粋にコンパイル時に解決されるため動作が速くRTTIを必要としない。
基底クラスの関数を派生クラスでオーバーライドした場合、実際に呼び出される関数はオブジェクトの型によって決定される。派生クラスによってオーバーライドでされるのは引数の数や型が同じ関数である。基底クラスのポインタのみが与えられた場合、コンパイラはオブジェクトの型をコンパイル時に特定できず正しい関数を呼び出せないため、実行時にこれを特定する。これをダイナミックディスパッチと呼ぶ。仮想関数や"メソッド"により、オブジェクトに割り当てられた実際の型に従って、最上位の派生クラスで実装した関数が呼び出される。一般的なC++コンパイラは仮想関数テーブルを用いる。オブジェクトの型が判明している場合はスコープ解決演算子を利用して仮想関数テーブルを使わないようにバイパスすることもできるが、一般的には実行時に仮想関数の呼び出しを解決するのが普通である。
標準のメンバ関数に加え、オーバーロードした演算子やデストラクタも仮想関数にできる。原則的にはクラスが仮想関数を持つ場合はデストラクタも仮想関数にすべきである。コンストラクタやその延長線上にあるコピーコンストラクタはコンパイルされた時点でオブジェクトの型が確定しないため仮想関数にできない。しかし、派生オブジェクトへのポインタが基底オブジェクトへのポインタとして渡された場合に、そのオブジェクトのコピーを作らなければならない場合は問題が生じる。このような場合はcodice_28関数(またはそれに準じる物)を仮想関数として作成するのが一般的な解決方法である。codice_28は派生クラスのコピーを生成して返す。
codice_30を関数宣言の閉じ括弧とセミコロンの間に挿入することによりメンバ関数を"純粋仮想関数"にできる。純粋仮想関数を持つクラスは純粋仮想クラスと呼ばれ、このクラスからオブジェクトを生成することはできない。このような純粋仮想クラスは基底クラスとしてのみ利用できる。派生クラスは純粋仮称関数を継承するため、派生クラスのオブジェクトを生成したい場合は全ての純粋仮想関数をオーバーライドして実装しなければならない。純粋仮想関数を持つクラスのオブジェクトを生成しようと試みるようなプログラムは行儀が悪い。
型消去と呼ばれるテンプレートを活用して動的な多態性を実現する手法が存在する。この手法はC++の標準ライブラリでもcodice_31やcodice_32の削除子で採用されている。いずれも、コンストラクタや代入演算子で(一定の条件を満たす)任意のオブジェクトを実引数として渡せるようにすることから多態性を実現している。
C99の制定前、C言語とC++との分かりやすい差異として、codice_2 で始まり改行で終わる、単一行コメントの有無があった。
単一行コメントはもともと、C言語の祖先にあたるBCPLに含まれていた仕様である。現在のC++のコンパイラの多くがC言語のコンパイラとしても使えるようになっているのと同様に、C言語が生まれて間もない頃は、C言語に加えB言語やBCPLのコンパイルができるコンパイラが用いられていた。それらコンパイラは、C言語のソースであってもBCPLと同様に単一行コメントが使用できるよう独自の拡張がなされていたため、
現在ではC99の制定によって正式に単一行コメントがサポートされるようになった。
LALR(1)のような旧式のパースアルゴリズムを用いてC++のパーサを記述することは比較的難しい。その理由の一つはC++の文法がLALRではないことである。このため、コード分析ツールや、高度な修正を行うツール(リファクタリングツールなど)は非常に少ない。この問題を取り扱う方法としてLALR(1)でパースできるように改良されたC++の亜種()を利用する方法がある。GLRパーサのようにより強力でシンプルなパーサもあるが処理が遅い。
パースはC++を処理するツールを作成する際の最も難しい問題ではない。このようなツールはコンパイラと同じように識別子の意味を理解しなければならない。従ってC++を処理する実用的なシステムはソースコードをパースするだけでなく、各識別子の定義を正確に適用し(つまりC++の複雑なスコープのルールを正確に取り扱い)、型を正しく特定できなければならない。
いずれにせよC++ソースコード処理ツールが実用的であるためには、GNU GCCやVisual C++で使われているような、様々なC++の方言を取り扱えなければならず、適切な分析処理やソース変換やソース出力などが実装できなければならない。GLRのような先進的なパースアルゴリズムとシンボルテーブルを組み合わせてソースコードを変換する方法を利用すればあらゆるC++ツールを開発できる。
その言語文法の複雑さゆえ、C++規格に準拠したコンパイラを開発するのは一般的に難しい。20世紀末から何年にも渡りC++に部分的に準拠した様々なコンパイラが作られ、テンプレートの部分特殊化などの部分で実装にばらつきがあった。中でも、テンプレートの宣言と実装を分離できるようにするためのcodice_34は問題のキーワードの一つだった。exportを定義したC++98規格がリリースされてから5年後の2003年前半にが初めてexportを実装した。2004年にBorland C++ Builder Xがexportを実装した。これらのコンパイラはいずれもEDGのフロントエンドをベースにしていた。大半のコンパイラで実装されていないexportは多くのC++関連書籍(例えば""Beginning ANSI C++"", Ivor Horton著)にサンプルが記されているが、exportが記載されていることによる問題は特に指摘されていない。GCCをはじめとするその他のコンパイラでは全くサポートしていない。はC++の標準規格からexportを削除することを推奨していたが、C++98では最終的にこれを残す決定がなされた。結局、C++11では実装の少なさ・困難さを理由に削除された。
コンパイラ開発者の裁量で決められる範囲を確保するため、C++標準化委員会は名前修飾や例外処理などの実装に依存する機能の実装方法を決定しないことに決めた。この決定の問題は、コンパイラが異なるとオブジェクトファイルの互換性が保証されない点である。特定の機種やOSでコンパイラの互換性を持たせ、バイナリレベルでのコード再利用性を高めようとするABIのような非標準の規格もあり、一部のコンパイラではこうした準規格を採用している。
2015年現在のメジャーなC++コンパイラ(gcc,Clang,Intel C++ Compiler,Microsoft Visual C++など)の最新版はC++11規格にほぼ準拠しており、特にClangは2013年4月時点で全機能を実装完了した 。ただしマイナーアップデートとなるC++14を含めると、処理系間でのばらつきは依然として存在する。
C++は基本的にC言語の上位互換であるが、厳密には異なる。C言語で記述された大半のプログラムはC++でコンパイルできるように簡単に修正できるが、C言語では正当でもC++では不正になる部分や、C++とは動作が異なる部分が若干存在する。
例えば、C言語では汎用ポインタcodice_35は他の型へのポインタに暗黙的に変換できるが、C++ではキャスト演算子によって変換を明示する必要がある。またC++ではcodice_36やcodice_37といった数多くの新しいキーワードが追加されたが、移植の際に元のC言語のプログラムでそれらが識別子(例えば変数名)として使われていると、問題になる。
C言語の標準規格であるC99やその後継C11ではこうした非互換性の一部が解決されており、codice_2形式のコメントや宣言とコードの混在といったC++の機能がC言語でサポートされている。その一方でC99では、可変長配列、複素数型の組み込み変数、指示初期化子、複合リテラルといった、C++でサポートしていない数多くの新機能が追加された。C99で追加された新機能の一部はC++11に反映され、次期C++1yに対してもC99やC11との互換性を向上される提案が行われている。また、可変長配列や複素数型などのC99に追加された機能の一部はC11でオプションとなった。
C++で書かれた関数をC言語で書かれたプログラムから呼び出す、あるいはその逆を行なう場合など、C言語のコードとC++のコードを混在させるためにはCリンケージを利用する必要があり、関数をcodice_39で個別に修飾するか、codice_40のブロックの中で宣言しなければならない。また、関数引数や戻り値などのインターフェイスはC言語互換形式に合わせる必要がある。Cリンケージを利用した関数については、C++名前修飾がされず、名前修飾に依存している関数オーバーロード機能は利用できない。
C/C++の相互運用性が確保されていることで、慣れ親しんだC言語標準ライブラリ関数の大半をC++でもそのまま利用し続けることができるということはC++の大きなメリットのひとつである。
"""
In [19]:
#@title ウィキペディア記事「Java」をjava_article変数に読み込む
java_article = """
Java
Java(ジャバ)は、狭義ではプログラミング言語Javaを指す。広義では言語仕様以外にも、仕様が与えられているJavaクラスライブラリやJava仮想マシン、さらにはJDKやJREなどの公式のものをはじめとする、場合によってはサードパーティのものなどを含め曖昧にJavaプラットフォームと総称されるようなものなどのエコシステムなどを指すこともある。構文についてはJavaの文法の記事を参照。
Javaは当初、それ以前のさまざまな言語の良い部分を引き継ぎ、また言語仕様や構文などの複雑さを排除するよう設計された。次のような特徴を持つ。
Javaは組み込みシステムや携帯機器(携帯電話・PHSやPDA・スマートフォン等)のシステムから、企業の情報システムを担う大規模なデータベース、サーバ、スーパーコンピュータまで、多くの分野で使用されている。
プログラミング言語JavaおよびJavaプラットフォームは、1990年代前半当時、サン・マイクロシステムズに居たジェームズ・ゴスリン、ビル・ジョイなどの人々によって設計・開発された。2018年現在はサンを買収したOracleによる管理の他、追加提案などはサン時代から続いているJava Community Process (JCP) というプロセスによって進められる。
Javaに関わる呼称とその意味内容は、文脈に応じていくつか使い分けられている。サン・マイクロシステムズは、「Javaテクノロジ」(Java技術、Java technology)という呼称を使い、一方でJavaのさまざまな技術の形容詞として「Java」の呼称を使ってきた。多くのプログラマは、プログラミング言語の意味で「Java」の呼称を使っている。Javaの実行環境は、Java実行環境(Java Runtime Environment;JRE)と呼ばれる。Java の基本的な開発環境は、Java開発キット(Java Development Kit;JDK)と呼ばれる。
Javaはクラスベースのオブジェクト指向プログラミング言語である(#オブジェクト指向プログラミング)。Java のプログラムは複数のクラスから構成され、プログラムの実行は、各クラスが実体化したオブジェクト群が相互にメッセージをやりとりしながら行われる。Javaでは、継承については実装の単一継承を採用している。ただし1つのクラス(オブジェクト)は複数のインタフェースを実装できる。Java で扱うデータ/オブジェクトの型(データ型)は、強い静的型付けを採用している。Javaのコンパイラおよび実行環境が、型同士の整合性を検査することによって、プログラムが正しく記述されていることや、安全に動作するか検証が可能である。
Javaは例外処理機構を備えており、プログラム実行中に生じた異常(例外)の扱いを、比較的安全な方法で行い、プログラムを読みやすく記述できる。
Javaでは簡潔なメモリモデルを採用しており、プログラマがメモリ(主記憶装置)を管理する負担を軽減する。あらゆるオブジェクトはメモリ内のヒープという領域に割り当てられる。メモリ管理は、Java仮想マシンに統合されたガベージコレクションの機能によって行われる。従来のオブジェクト指向プログラミング言語であるC++では、ヒープ領域に生成したオブジェクトについて、もはや必要が無くなった時に破棄する指示を、プログラマが自分で責任をもって行わなければならなかった。これは、C++プログラマにとっては負担が大きく複雑で間違えやすい作業であり、ソフトウェアの安全性・開発効率・保守性を損なう要因だった。Javaではガベージコレクションの機能があるため、このようなことは無く、プログラマの負担は大きく軽減される。
Javaでは、C/C++のような、整数とポインタの相互変換、配列の要素へのポインタによるアクセス、ポインタ演算といった機能は、基本機能としては提供されていない。ただし、オブジェクトへの参照は内部的にはアドレスである。
Javaではプラットフォーム非依存を目標の一つとし、またバージョン間の互換性に注意して開発が進められている。プラットフォームに依存しない(Javaプラットフォーム自体を除く)アプリケーションソフトウェアの開発と配備を行うことができると主張される。従来のプログラミング言語の多くはプラットフォーム(CPU)に依存したネイティブなコードにコンパイルすることを前提として設計されていたが、Javaはこうした言語と異なり、中間言語(バイトコード)にコンパイルされ、Java仮想マシンで実行されるよう設計された(pコードマシンなど、過去にもあったものだが、)。性能向上のため、Java仮想マシンの成熟した実装では多くの場合、ジャストインタイムコンパイル方式が使われる。
プラットフォーム非依存とバージョン間の互換性の目標は、完全に達成できたわけではなく課題が残っている。
Javaではスレッドを言語仕様で規定しており、マルチスレッドによる並行計算を、従来の言語と比べて簡単に実装できる。なお並行計算は、複数の処理を同時に実行する処理形態である。またスレッドは、プロセスより小さく軽量な処理の単位である。
Javaでは充実したライブラリにより、コンピュータネットワークを活用するソフトウェアを、効率良く開発できる。Javaはその初期のバージョンから、TCP/IP のライブラリを備えていた。分散オブジェクト環境 (Java RMI, CORBA) のソフトウェアの開発も早い時期からできるようになっていた。では、さまざまなネットワークプロトコルの高水準なライブラリが使えるようになっている。W3Cにより標準化された、汎用マークアップ言語のひとつであるXMLで記述された文書を扱うライブラリも早期に実装・標準サポートされた。では、XMLプロセサとXSLTプロセサがJava標準ライブラリに統合され提供されている。充実したネットワーク機能とXML文書を扱う機能を有効に組み合わせることにより、Javaは標準機能だけでも高度なシステムを構築できる言語の一つとなっている。
Javaはセキュリティを考慮して設計されており、サンドボックスモデルに基づいたセキュリティ機構を備えている。セキュリティ機構を正しく実装したJava実行環境を適切に使うことで、遠隔のコンピュータ上にある実行コードを安全に実行できる(Javaアプレット)。
また、名前空間の機構をもつ言語であり、ライブラリおよびアプリケーションに含まれる多数の Java のプログラム(クラスとインタフェース)は、パッケージという階層構造で管理できる。
Javaに対する批判も少なくない。いくつかの批判に対しては、サン(後にはオラクル)やJCPに参加する人々の努力により、Javaの改良が行われている。一方で、。
JavaScript(ECMAScript)は、Javaにちなんで命名されたスクリプト言語である。とはいえ基本構文の一部がC言語系すなわちJavaに似ているだけであり、またクラスベースではなくプロトタイプベースのオブジェクト指向言語であるため、言語仕様的な共通点は少ない。
表記は"J"のみが大文字の「Java」が正しい。「JAVA」は正式な表記ではない。
この節では次の構成でJavaの歴史と近況を説明する。
Javaプラットフォームおよびプログラミング言語Javaは、1990年12月にサン・マイクロシステムズが1つの内部プロジェクトを立ち上げたことから始まった。この内部プロジェクトでは、C++ / Cの代替となるプログラミング言語を開発した。この言語は、プロジェクトで Greenオペレーティングシステム (Green OS) と共に、同OSの標準言語として開発された。この言語は、1992年頃プロジェクト内ではOakと呼ばれていたが、後にJavaの呼称に変更されることになる。呼称変更の理由は、Oakはすでに別の会社が商標として使っていたからである。
1990年頃、サンのエンジニア、パトリック・ノートンは、自社のプログラミング言語C++とCのアプリケーションプログラミングインタフェース(API)と開発ツールに不満を募らせていた。その頃、NeXTが注目を浴びていたことがきっかけとなって、ノートンはサンでプログラミング環境の開発の仕事をすることになった。NeXTワークステーションと、その環境であるNEXTSTEPでは、主力の言語としてObjective-Cが開発されていた(余談になるが、その「直系の子孫」に当たるのは、macOSおよびiOSと、Swiftである)。こうした経緯のなかで「ステルスプロジェクト」が始まった。
ステルスプロジェクトには、始まってすぐにジェームズ・ゴスリンとマイク・シェルダンが参加し、プロジェクトの名称は「グリーンプロジェクト」に変更された。プロジェクトには他のエンジニアたちも参加し、彼らはアメリカ合衆国カリフォルニア州メンローパーク市サンドヒルロードの道沿いにある小さなオフィスで作業を始めた。プロジェクトの目的は、次世代の家電製品のための新しいプログラミング言語を設計し、その処理系を開発することだった。サンはこの分野が重要な市場になると予測していた。
プロジェクトチームでは当初はC++を検討していたが、いくつかの理由から却下された。理由は、当時の彼らの目的が、家電製品すなわち組み込みシステムだったからである。組み込みシステムでは、利用できるコンピュータ資源が少ないという制約がある。彼らはC++ではコンピュータ資源を食いすぎると判断した。またC++は複雑なプログラミング言語であり、C++を使うプログラマは注意していても間違いを犯しがちである。
C++にはガベージコレクションの機能が無い。ガベージコレクションが無いということは、プログラマが自分でオブジェクトの寿命(生存期間)を管理しなければならないことを意味する。プログラマが自分でオブジェクトの寿命を管理することは、冒険的で間違いやすい作業である。
プロジェクトチームは、いくつかの重要な機能についてC++の移植性が乏しいことも問題であると考えた。
このプロジェクトでの重要な機能とは、セキュリティおよび分散コンピューティング、マルチスレッドであり、これらの機能が、プラットフォームに依存せずに使える必要があった。このような事情で、彼らはあらゆる機器に容易に移植できるプラットフォームが必要であると認識するようになった。
一方で、サンの別のエンジニア、ビル・ジョイは、ゼロックスのパロアルト研究所でAltoというワークステーション試作機のために開発されたプログラミング言語・MesaとCの良いとこどりをした新しいプログラミング言語を構想していた。ジョイは "Further" という名前で呼ばれる論文を書き、自社でC++に基づいたオブジェクト指向環境を開発するべきであることを進言した。まずジェームズ・ゴスリンがC++を改変し拡張することを試みた。ゴスリンはこの拡張版C++を、"C++ ++ --"と名付けた。しかしゴスリンは、すぐにこの拡張版C++の開発を中止して、全く新しいプログラミング言語を開発する方針を採ることにした。ゴスリンはこの新しい言語にOakという名前をつけた。この名前の由来は、ゴスリンのオフィスのすぐそばにオークの木が立っていたことによる。
プロジェクトチームは残業までして作業を続け、1992年の夏までに新しいプラットフォームを、Green OS、Oak言語、ライブラリ、ハードウェアによって部分的なデモンストレーションができるようになった。1992年9月3日の最初のデモンストレーションでは、チームは Star7という携帯情報端末機器を開発することに力点をおいていた。この機器の名称の由来は、電話機能が "*7" とボタンを押すことで有効になることによる。
この機器は、グラフィカルなインタフェースを備え、"Duke" という名前の知的な仮想代理人が利用者を支援した。同年11月、サンはグリーンプロジェクトを分離して完全子会社のFirstPerson, Incを設立した。それにともないチームはパロアルトに引っ越した。FirstPersonチームは、高度にインタラクティブな機器に関心を持っていた。そのおりタイム・ワーナーがケーブルテレビのセットトップボックスのRFP (Request For Proposal) を公表していた。そこでFirstPersonチームは自分たちの目標を変更し、タイム・ワーナーの RFP に応じてセットトップボックスの提案を提出した。しかし、FirstPersonは入札でシリコングラフィックス(SGI)に負けた。その後に3DO社のセットトップボックスの案件もあったが、契約には至らなかった。FirstPersonはテレビ業界では利益を出すことができず、サンはFirstPersonを解散してチームを自社に戻した。
1994年の6月から7月にかけて、ジョン・ゲージと、ジェームズ・ゴスリン、ビル・ジョイ、パトリック・ノートン、ウェイン・ロジン、エリック・シュミットの間で、3日間かけてブレインストーミングを行い、プロジェクトチームはウェブの世界に主眼を置くという方針変更を行う。彼らは、革新的なウェブブラウザであるNCSA Mosaicの出現を目の当たりにし、ウェブを含むインターネットの世界は、ケーブルテレビの世界に劣らず、高度にインタラクティブな媒体に発展しつつあると認識するようになった。Oakを使ったプロトタイプとして、ノートンはWebRunnerという小さなウェブブラウザを開発。このウェブブラウザの名称は後に HotJava と変更される。ウェブページにJavaアプレットという小さなJavaプログラムを埋め込んでおいて、ウェブブラウザHotJavaでそのページにアクセスすると、HotJava上でアニメーションの表示やマウスによるインタラクティブな操作ができた。
同年、チームはOakの名称をJavaに変更する。変更の理由は、商標を調べて、"Oak" という名前がすでにビデオカードアダプタの製造会社 (Oak Technology) によって使われていたことが判明したからである。Javaという名称は、一部のチームメンバーがよく出入りしていた近くのコーヒーショップで命名されたという。
この名称が、何かの頭字語であるかどうかについては、よく分かっていない。
1994年10月に、HotJavaとJavaプラットフォームが、サン・マイクロシステムズの幹部社員の前でデモンストレーションされた。そして1994年内に Java 1.0a(アルファ版)がダウンロードできるようになる。
JavaとHotJavaが最初に公的な場で公表されたのは、1995年5月23日のSunWorldカンファレンスだった。サンは、ウェブブラウザHotJava中で、Javaアプレットにより、ウェブページ内でアニメーションの表示やマウスによるインタラクティブな操作が可能であることをアピールした。カンファレンスでアナウンスを行ったのは、サンの技術部長ジョン・ゲージである。このカンファレンスではまた、ゲージのアナウンスに関連する、当時のネットスケープコミュニケーションズの上級副社長マーク・アンドリーセンによるアナウンスが人々を驚かせた。それは、ネットスケープが自社のウェブブラウザであるNetscape NavigatorにJavaの実行機能を追加する予定だというものだった。このアナウンスにより業界の耳目を集める話題となった。
1995年秋にはJava 1.0のベータ版が公開された。1996年1月9日にサンは、JavaSoft部門を立ち上げた。その2週間後に、最初の正式バージョンであるJava 1.0がリリースされた。
Javaの最初のバージョンが公開されてから現在までの動向を、いくつかの側面から述べる。なお、Javaの開発元であるサン・マイクロシステムズはこの間の2010年1月にオラクルにより買収されており、Javaに関する権利も同社に移転している。
Javaアプレットは、WWWブラウザで動作するJavaプログラムであり、クライアントサイドのウェブアプリケーションの実装方法のひとつとして広く使われている。いくつかの有力な競合が存在する。競合技術の代表としてMicrosoft ActiveXおよびAdobe Flashが挙げられるが、これらはいずれも衰退している。
なお、Javaの最初の普及期であった20世紀末の頃には圧倒的なシェアを持っていた、Microsoft Windows 95上でのInternet Explorerが、Javaアプレットを使用したページを表示しようとする際に、VMの起動のために、数十秒〜数分間操作を受け付けなくなったことが(なお、起動してしまえば実際には高性能だったのだが)、「Javaは重い」という風評の根源である。その後は、携帯端末等を含めれば、Windowsのシェアが圧倒的という状況が順調に消滅したため、IEのシェアが圧倒的ということも無くなり、一方でそのような風評のせいで、Javaの利用先としてサーバサイドが注力されたこともあり、遅いなどと言われることもほとんどなくなった。
簡単でインタラクティブなアニメーション用には、JavaアプレットよりもGIF89aやAdobe Flashを採用する事例が多い。この分野においては、ではAjaxも普及しつつある。Ajaxアプリケーションの作成に欠かせないJavaScriptの開発では、Java開発で一般的に用いられているほどドキュメントや技術が成熟した標準ライブラリ、サードパーティーライブラリ、IDE、単体テストツールなどの開発環境がないが、Java開発環境を利用してJavaScriptによるAjaxウェブアプリケーションを開発するツールとしてGoogle Web Toolkitを用いることができる。GWTコンパイラはJavaソースコードをバイトコードの代わりにJavaScriptにコンパイルし、ブラウザのJavaScript解釈エンジンをあたかもJVMのように活用することを可能にする。これによりJavaを用いてブラウザ上で動作するデスクトップアプリケーションと遜色ないウェブアプリケーションを作成することが可能となっている。HTML5によって導入されるデータベースのWeb Storage、ファイルAPI、クライアントハードウェアの位置情報を得るジオロケーション、JavaScriptをマルチスレッドで起動するWeb workerなどのクライアント側技術はJavaScriptによる呼び出しを前提としている。GWTやサードパーティのGWTライブラリはHTML5APIのJavaラッパーを提供しており、開発者は複雑なクライアント側プログラムをJavaのIDEでデバッグ、テストしながら開発し、最適化されたJavaScriptにコンパイルして実行させることができる。2011年Adobe社は携帯向けのFlash開発を断念し、HTML5にクライアント側技術の焦点を変更した。携帯機器を含めると2012年現在ではFlashよりもJavaScriptが普及してはいるが、Flashほど充実した開発環境やライブラリはない。アプレットはFlashよりも普及していない。GWTはJavaScriptの普及度とJavaの充実した開発環境の両方を用いることができるため、Java経験者のリッチクライアント作成ツールとしてアプレットに取って代わる存在となりうる。
以上のように、ネットワーク越しにダウンロードしたアプリケーションをその場で実行する、というような場合に不可欠なのは、サンドボックスと呼ばれる一種の仮想化環境である、という事実はJavaが設計された当初から(あるいは、それ以前の先駆的な事例から)基本的に何ら変わるものではない。そのためのJava以外のものとしては、インタプリタベースのJavaScriptの他、バイトコード(あるいはネイティブコードの安全な実行)を指向したものとしてはNaCl (PNaCl)や、WebAssemblyがある。
現在、ウェブのサーバ側において、Java技術 (Java EE) は広く使われている。多くのウェブサイトが、Javaサーブレット (Java Servlet) やJavaServer Pages (JSP) などのJava EE技術を使って動的にページを生成するウェブを構築している。Javaサーブレットは2000年前後から急速に広く使われるようになり、現在では多くのウェブアプリケーション(動的なウェブページ)がサーブレットとして稼動するようになっている。
サン・マイクロシステムズが開発したJavaサーブレット技術を簡単に説明する。必ずしも厳密な説明ではない。
サンがJavaサーブレット技術を開発した1990年代末当時、ウェブアプリケーションの開発には、次に述べるようないくつかの問題があった。
Javaサーブレットはこれらの問題をある程度解決することができる技術だった。
デスクトップ環境においては、スタンドアロンのJava (Java SE) のアプリケーションソフトウェア(Javaアプリケーション)は、これまではあまり多く使われていなかったが、近年はいくつかのソフトウェアが広く使われるようになっている。近年になって使われるようになってきた理由としては、次のことが挙げられる。
広く使われているJavaのソフトウェアとしては、NetBeansおよびEclipse SDKの統合開発環境や、LimeWireやAzureusのようなファイル共有クライアントのソフトウェアなどがある。また数学ソフトウェアMATLABにおいても、ユーザインタフェースのレンダリングと計算機能の一部を実現するために使われている。多くの Java のSwingやSWTのウィジェット・ツールキットを使ったアプリケーションが、現在も開発されている。
このように、近年はデスクトップ上でJavaアプリケーションを使う事例が増えつつあるものの、従来は次に述べるいくつかの理由のためにあまり使われてこなかった。
一部のソフトウェア開発者は、情報技術はウェブを基盤としたモデルが主流となっており、スタンドアロンアプリケーションは流行遅れであり、新しいプログラミング技術は優れたウェブアプリケーションを開発することに充てられている、と思っていた。この見解については、ソフトウェア技術者の間で賛否が分かれている。
現在では、リッチクライアントやWeb 2.0の登場により新たなパラダイムが生まれようとしている。すなわちウェブを基盤としたウェブアプリケーションとスタンドアロンアプリケーションの融合である。ウェブアプリケーションをAjaxや Java Web Start、Adobe Flash などと組み合わせることにより、Web2.0時代に見合ったより洗練されたアプリケーションを開発することができる。
一昔前、ほとんどの パーソナルコンピュータ (PC) のユーザは、何ら問題なくウェブおよびデスクトップ環境上でJavaアプリケーションを実行できていた。かつて多くのPCメーカーは、自分たちが製造・販売するWindows PCにJava実行環境 (JRE) を同梱していた。アップルのmacOSや、多くのLinuxディストリビューションでも、Java実行環境を同梱していた。今では追加インストールが必要である。しかしながらパーソナルコンピュータにおいてJavaアプリケーションは殆ど使われなくなってしまっているので、マイクロソフトが2001年頃以降にJava実行環境をWindowsに同梱していないことの影響は小さい。
2001年頃にマイクロソフトによるJava実行環境をWindowsに同梱することを止めたという行動は、サン・マイクロシステムズが同社を「品質の低い」Java実行環境を同梱してきたとして告訴したことが契機となった。マイクロソフトがそれまでWindowsに同梱してきたJava実行環境向けに開発されたJavaプログラムは、他のプラットフォームのJava実行環境で動かない可能性があった。
しかし近年では、Javaアプリケーションパッケージ自体にJava実行環境を同梱する事例が少なくない。その背景にはJavaアプリケーション開発者の判断がある。Javaアプリケーションが想定どおりに機能するよう、Java実行環境のバージョンの違いによる非互換性に基づく不具合を避けるために、PCに同梱されているJava実行環境を使わないという判断である。
現在では、Javaアプレットは動作対象のJava実行環境のバージョンを認識することができる。また、バージョン間の互換性も プログラミング言語の中では高い水準にあり、上位互換性についてはJava SE 1.3以降は大きな問題はほぼおきにくくなっている。さらにJava Web StartではデスクトップにインストールされているJavaのバージョンを確認してアップデートできるならアップデートし、それだけでなくJava Web Start対応アプリケーションをもアップデートしようとする。そのため古いバージョンのJava実行環境を使っているマシンがあったとしても、自動アップデートされるためにそう難しい問題は起きない。
組み込みシステム向けのJava(Java ME)も広く使われている。
携帯機器(携帯電話・PHSやPDA・スマートフォン等)にJavaの実行環境が実装されるケースが多い。Java環境はこれら携帯機器全般に広く普及している。一方、SymbianおよびBREWは携帯電話や(日本的定義での)スマートフォンを主なターゲットとし、Javaと競合している。
Java MEでは、BREWとは異なり、開発者がライセンス料を支払わずに、プログラムを開発することができる。Java MEはSymbianより広く普及している。その理由は、Java MEがSymbianより広範な携帯機器、特に廉価なモデルで動作するからである。こうした事情からサードパーティによりOpera miniのようなフリーのJavaソフトウェアを開発することができるようになった。
携帯機器のJava MEプログラムは、サンドボックスのもとで動くため、多くの開発者が特別な配慮をせずにプログラムを開発しても、安全に実行できる。携帯機器のJava技術が多様化するに伴い、異なるメーカーの携帯機器でもJavaプログラムが動くよう、携帯機器のためのJava技術の標準が必要となった。携帯機器のためのJava MEの標準がMobile Information Device Profile (MIDP) である。最初の標準はMIDP 1で、小さい画面を想定したものであり、音声機能は無く、プログラムサイズは32kBまでという制限があった。後のMIDP 2の標準では、音声機能を備え、プログラムサイズの制限は64kBまでと緩和された。携帯機器の設計の進歩は標準化よりも急速であるため、一部のメーカーは、MIDP 2標準の最大プログラムサイズなどいくつかの制限を、意図的に緩和して携帯機器を開発している。
携帯機器におけるJava MEの競合技術について簡単に述べる。
世界的な動向としては、
また、2001年にはソニーのコンシューマゲーム機 PlayStation 2 にJava 仮想マシンが搭載される予定と発表され話題になった。
Java は、JDK(Java Development Kit; Java開発キット)1.0 以来、数度のメジャーバージョンアップを経ている。バージョンアップに伴い、多くのクラスとパッケージが標準ライブラリに追加されてきた。プログラミング言語JavaおよびJavaプラットフォームは、高い水準でバージョン間の互換性を保ちつつ発展してきている。
J2SE 1.4から、Javaの開発はJCP (Java Community Process) という標準化プロセスで行うようになっている。JCPでは、JSRs (Java Specification Requests) という文書群により、Javaに対する追加機能やJavaプラットフォームに対する変更の提案と規定を行う。
また、J2SE 1.3以降では開発コードネームとして、メジャーバージョンには動物の名前が、マイナーバージョンには昆虫の名前が付けられる傾向がある。
言語仕様は JLS(Java Language Specification; Java言語仕様)により規定する。JLSはJSR 901の管理下にある。
バージョンアップの過程で、言語仕様の変更だけでなく、標準クラスライブラリにおいても大きな変更が加えられている。JDK 1.0では標準ライブラリは約200クラス / インタフェースだったが、Java SE 6では4000以上のクラス / インタフェースとなっている。SwingやJava 2Dのような全く新しいAPIが追加された。その一方で、もともとJDK 1.0から存在していたクラスのメソッドの多くが、J2SE 5.0での使用は推奨されないようになっている。
最初のバージョン。プレスリリース (英語)
いくつかの重要な機能が追加された。プレスリリース (英語)
コードネームPlayground。このバージョンから呼称がJava 2に変更され、J2SE 5.0までこの呼称が使われる。またエディション名がJDKから "J2SE" (Java 2 Platform, Standard Edition) に変更された。この J2SE の名称により、J2EE (Java 2 Platform, Enterprise Edition) および J2ME (Java 2 Platform, Micro Edition) の基となるエディションであることが明確化された。プレスリリース (英語)
コードネームKestrel。プレスリリース (英語) 新機能の概要(日本語)
コードネームMerlin。このバージョンは、JCP (Java Community Process) の下で開発された最初のJavaプラットフォームである。プレスリリース(英語) 新機能の概要(日本語)
コードネームTiger。JSR 176 のもとで開発された。J2SE 5.0 では、言語仕様に大きく拡張が加えられ、多くの新しい言語機能が追加された。プレスリリース(英語) 新機能の概要(日本語)。もともとは J2SE 1.5 という名称だったが、この名称はすでに内部的なバージョン番号として使われていた。またマーケティング上の理由もあった。
この例では、codice_7という変数名のコレクションオブジェクト内の、各codice_8オブジェクトを反復して繰り返し処理する。各codice_8オブジェクトにはループサイクルごとにcodice_10という変数名をつける。各ループサイクルで、codice_10に対してcodice_8型で定義されているcodice_13メソッドを呼び出す。拡張forループはJSR 201で規定された。
コードネームMustang。JSR 270のもとで開発された。Java SE 6においては、サンは命名方針を変更して、"J2SE" からJava SEに変更し、バージョン番号から ".0" の部分を廃止している。
Java SE 6 Update 10が2008年10月22日にリリースされた。Update 8と9が省略され、7の次が10となった。Javaの動作速度が改善され、アプリケーションやアプレットの起動を高速化するJava Quick Starterが搭載され、Javaのインストールを高速化する、Java Kernelが搭載された。JavaアプレットやJava Web Startの起動を容易にするための、配備ツールキットが公開された。
コードネームはDolphinである。2006年に開発が始まった。元々は2008年春にリリースされる見通しであったが、何度かリリース予定が変更された。2007年8月の時点では2009年1月をリリース目標としていたが、2008年12月、ジェームズ・ゴスリンは、「私の勝手な憶測だが」という注意書き付きで、2010年6月以降のリリースを予測し、2009年11月には2010年9月以降のリリース予定に変更された。2010年9月に、これ以上の延期を避けるため、大きな言語仕様の改訂などの部分は Java SE 8 に先送りし、Java SE 7 を2011年中頃に、Java SE 8を2012年終わり頃に提供するという目標を立て、結局2011年7月28日にリリースした。Java SE 7は、オラクルによるサン買収後、初のメジャーリリースである。
Java SE 7に追加された項目は以下のとおりである。
以下の項目を Java SE 8 に追加。2014年3月4日に JSR 337 にて仕様が規定された。JDK 8 は2013年9月9日にリリース予定だったが、2013年4月18日にリリースの延期が発表になり2014年3月18日にリリースされた。CLDC, CDC を統合した Java ME 8 は2014年4月30日にリリースされた。
当初搭載予定だった、以下の機能はJava SE 9に延期となった。
また、搭載予定だった以下の機能は廃止 (withdrawn) になった。
Java SE 9 は Java SE 8 リリース3年後の2017年9月21日にリリースされた。。言語レベルでのモジュール化のサポート (Project Jigsaw, JSR 294) などを追加した。
Java SE 10 はJava SE 9 リリース半年後の2018年3月20日にリリースされた。ローカル変数型推論などの機能が追加されている。
OracleによるJDKの無償配布はこのバージョンが最後。
Java SE 11以降はオープンソース版のOpenJDKが無償版という扱いになり、Oracle JDKは有償サポート契約を結んだ顧客にのみ配布される形になるという。
Java SE 11 には以下の機能が追加予定。
Project Valhalla
Project Panama
Javaの主な特徴を述べる。
Javaを開発する上では、5つの目標があった。
ネットワーク機能および遠隔コンピュータの実行コードの実行を実現するために、場合によっては、Javaプログラマは、CORBAやInternet Communications Engine、OSGiのような拡張機能を使う。
Javaはクラスベースのオブジェクト指向プログラミング言語である。Javaのプログラムは複数のクラスから構成され、プログラムの実行は、各クラスが実体化したオブジェクト群が相互にメッセージをやりとりしながら行われる。Javaでは、実装の単一継承を採用し、一つのクラスが複数のインタフェースをもつことができる。クラスとは、オブジェクト指向においてオブジェクトの設計図にあたるものである。オブジェクトについては後述する。継承とは、既存のクラスを基にして、そのクラスの機能を引き継いだ新しいクラスを定義できることをいう。Javaでは実装の多重継承は採用していない。Javaでは一つのクラスが複数のインタフェースをもてるため、一つのクラスに複数の役割をもたせることができる。
Javaで扱うデータ / オブジェクトの型(データ型)は、強い静的型付けを採用している。静的型付けにより、Javaのコンパイラおよび実行環境が、型同士の整合性を検査することによって、プログラムが正しく記述されていることや、安全に動作することの検証が可能である。
Javaのデータ型には、参照型 (reference type) と基本型(プリミティブ型、primitive type)の2種類がある。Javaのオブジェクトはすべて参照型である。Javaの基本型は、単純な構造のデータ(数値、論理値、文字 など)のための型である。Javaの標準ライブラリは、基本型の値をオブジェクトとして扱えるようにするためのラッパクラスを提供している。近年のJava (J2SE 5.0) からは型の扱いに改良が加えられている。
Javaの特徴の一つであるオブジェクト指向プログラミングは、プログラミングおよびプログラミング言語設計の手法をいう。Javaはオブジェクト指向プログラミング言語である。オブジェクト指向の概念に対しては、多くの解釈がなされてきた。一般には、オブジェクト指向を特徴づける重要な考え方は、ソフトウェアで扱うさまざまな種類のデータについて、データとそのデータに関連する手続きを一体化するように、ソフトウェアを設計することである。こうして、データとコードは、オブジェクトと呼ばれる実体に一体化される。オブジェクトとは、状態(データ)と振る舞い(コード)がひとかたまりとなったものと考えることができる。
Javaでは、オブジェクトの設計図であるクラスに定義する振る舞いを「メソッド」と、状態を「フィールド」(インスタンス変数)と呼ぶ。
オブジェクト指向以前の技術での本質的な問題点は、プログラムにおいて、状態と振る舞いが分離されていたことである。
オブジェクト指向に基づいて、これまで分離されていた状態と振る舞いを、オブジェクトに一体化することは、ソフトウェアシステムの設計において堅牢な基盤となる。オブジェクト指向を有効に活用することにより、大規模なソフトウェア開発プロジェクトを管理することの困難さが軽減され、ソフトウェアの品質が向上し、失敗するプロジェクトの数を減らすことができる。
オブジェクト指向のもう一つの目標は、汎用的なオブジェクトを開発することで、プロジェクトをまたがってソフトウェアをより再利用可能にしていくというものである。たとえば、汎用的な「顧客」オブジェクトは、別のプロジェクトにおいても、理論的にはほぼ同一の手続き群を備えるであろう。大きな組織において、その組織の複数のプロジェクトが機能的に共通する基盤層をもつ場合は、なおさらソフトウェアの再利用が重要となる。こうしたことから、ソフトウェアオブジェクトは、さまざまなシステムに組み込み可能であるように、汎用性を備えていることが望ましい。こうすることで、ソフトウェア業界は、既存のしっかりテストされたオブジェクトコンポーネントを活用してプロジェクトを進めることができ、開発期間を大幅に短縮することができる。
一方で、ソフトウェアの再利用性を高めるということには、実践においては、2つの大きな困難を伴う。
いくつかのオープンソースコミュニティでは、再利用に伴う問題を軽減するために、オブジェクトやクラスライブラリの開発者に、自分たちが開発した汎用的で再利用可能な開発物についての情報を広報する手段を提供している。
Javaのもう一つの特徴はプラットフォームに依存していないことであり、これは、Javaのプログラムがさまざまなハードウェアやオペレーティングシステム上で必ず同じように動く、ということを意味する。一度Javaのプログラムを作成すれば、そのプログラムはどのプラットフォーム上でも動くのである。近年では、Java実行環境を構成するJava仮想マシンに高速化の技術が導入され、プラットフォームに依存したプログラムと同水準の実行性能を実現している。
Javaのプラットフォーム非依存は、次のようにして実現されている。
また、実際にはJavaコンパイラの実装として、ソースコードから直接にプラットフォームのハードウェアにネイティブなオブジェクトコード(機械語コード)を生成するものがある。このようなJavaコンパイラの実装としてはGNUプロジェクトのGNU Compiler for Java (GCJ)などがある。この場合、中間言語のバイトコードを生成するという段階は省かれる。しかしこの方法で生成されるJavaの実行コードは、コンパイル時に指定したプラットフォームでしか動かない。
Javaの実行コード(バイトコード)を生成する手段としては、プログラミング言語Javaでプログラムを書くことが標準的なやり方である。Javaのバイトコードの実行は、Java仮想マシンという仮想マシンの環境上で行われる。Java仮想マシンは実行時にバイトコードをネイティブコードに変換する。なお、Javaのバイトコードを生成する他の方法としては、現在ではRuby(JRuby)や Groovy 、Kotlin 、Jabaco 、Python(Jython)などのプログラミング言語でプログラムを書くこともできる。
サン・マイクロシステムズのJavaのライセンスは、すべてのJava実行環境の実装は「互換性」を備えるべきであることを要求していた。このことに関連して、サン・マイクロシステムズとマイクロソフトとの間で法的な争いが起こったことがあった。この法的な争いは、サンが、マイクロソフトのJava実行環境の実装について次のように主張したことによる。
サンは訴訟を起こして勝訴し、約2000万ドルの違約金の支払いを受けた。また裁判所は、マイクロソフトに対してサンのライセンス条件に従うことを命じた。この決定を受けて、マイクロソフトは自社のOSであるWindowsにJava実行環境を同梱しない方針を採った。また近年のバージョンのWindowsでは自社のウェブブラウザであるInternet ExplorerでJavaをサポートしないようにした。その結果、Internet ExplorerでJavaアプレットを動かすためには、別途にプラグインが必要となった。しかし、サンなどの企業は、近年のバージョンのWindowsのユーザが、無償でJava実行環境を利用できるようにした。そのため、ほとんどのWindows PCのユーザは、何ら問題なくウェブおよびデスクトップ上でJavaアプリケーションを実行できる。
最初期のJava実行環境の実装では、Javaプログラムの実行速度が遅かったが、近年では大きく改善されて、高速に実行できるようになった。最初期のJava実行環境のJava仮想マシンの実装は、移植性を実現するためにインタプリタとして動作する仮想マシンを採用した。こうした初期のJava実行環境の実装では、Javaプログラムの実行速度がCやC++のプログラムと比べて遅かった。そのため、Javaプログラムの実行速度は遅いという評判が広まった。近年のJava実行環境の実装では、いくつかの技術を導入することにより、以前と比べて、Javaプログラムをかなり高速に実行できるようになった。
Javaプログラムを高速に実行するために使われる技術を説明する。
Java の移植性(プラットフォーム非依存)がどの程度実現できているかについては、議論の対象となっている。技術的には移植性とは実現が難しい目標である。多くのプラットフォームにおいて同一に動作するJavaプログラムを作成することは、可能である。しかし実際には、Javaを利用できるプラットフォームによってはちょっとしたエラーが発生したり、微妙に異なる動作をする事例が多い。こうしたことから一部の人々は、サン・マイクロシステムズのJavaの売り文句であった "Write once, run anywhere"(一度コードを書けば、どの環境でも動く)をもじって "Write once, debug everywhere"(一度コードを書けば、どの環境でもデバッグが必要)と皮肉をいわれることがある。
しかし、Javaのプラットフォーム非依存は、サーバ側や組み込みシステムのアプリケーションに関しては、非常に成功している。サーバ側 (Java EE) では、Java のサーブレット、Webサービス、EJB (Enterprise JavaBeans) などの技術が広く使われている。組み込みシステムの分野においても、組み込みシステム向けの Java環境 (Java ME) を使ったOSGiを基にした開発が広く行われている。
Javaはガベージコレクション機能を備えており、これを備えていない従来の多くの言語と比較して、プログラムの開発生産性と安定性が高く、プログラマの負担が完全に解消されるわけではないものの、大きく軽減される。近年のJavaでは世代別ガベージコレクションというより効率的な技術を導入している。
ガベージコレクションを備えていないC++やその他の言語の場合、プログラマが適切にメモリの管理をしなければならない。オブジェクト指向プログラミングをするプログラマは一般に、Javaと同様メモリ内のヒープにオブジェクトを格納する領域を割り当てる。そしてオブジェクトがもはや必要なくなった場合に、必ず明示的にオブジェクトを削除する指示を記述して、そのオブジェクトが使っていたメモリ領域を解放しなければならない。メモリ管理が不十分なプログラムでは、メモリリークが発生する可能性がある。メモリリークとは、不適切な指示などで、解放されなかったメモリ領域が累積していき、利用できるメモリの量が減っていくことで、気付かないうちに大量のメモリを消費してしまう問題が起こり得る。他にも、メモリ領域を解放する際に、解放の指示を重複して行ってしまい、プログラムの実行を不安定にするなどのケースがあり、悪くすると異常終了してしまうこともある。
ガベージコレクション機能は、このような潜在的な問題の多くを未然に防ぐことができる。プログラマは任意の時点でオブジェクトを生成することができ、Java実行環境は生成されたオブジェクトのライフサイクルを管理する責任を持つ。
プログラム(オブジェクト)は、他のオブジェクトへの参照を持ち、そのオブジェクトのメソッドを呼び出すことができる。他のオブジェクトへの参照とは、低水準の視点で述べると、メモリ内のヒープという領域上に確保されたそのオブジェクトを指すアドレスのことである。
オブジェクトがどこからも参照されなくなった場合、Javaのガベージコレクション機能が自動的にその「到達不可能なオブジェクト」を削除し、そのメモリ領域を解放することで、解放し忘れた未解放メモリが累積していき利用できるメモリ量が減っていくメモリリークを防ぐ。
ただしJavaのガベージコレクション機能は、メモリリークの問題を完全に解消するわけではない。プログラマが、自分のプログラムでもはや必要のないオブジェクトへの参照を保持し続けた場合は、やはりメモリリークが発生する可能性がある。
別の表現で述べると、Javaでは、メモリリークは概念的に高い水準においては、発生する可能性が残っているということである。概念的に低い水準においては、ガベージコレクションが正しく実装されたJava仮想マシンを使えば、メモリリークが発生する可能性は無くなった。全体として、Javaのガベージコレクション機能により、C++の場合と比べると、オブジェクトの生成と削除は、より簡潔になり、潜在的に安全になり、また多くの場合は高速になっている。
C++においても、Javaと同等のメモリ管理の高速性と効率性を実現することは可能ではあるが、先に述べた通り、複雑な作業で間違いやすく、完璧に行おうとすれば開発期間が非常に長くなり、開発したソフトウェアはかなり複雑で難解になる。たとえば、C++で特定のクラスを対象として、高速実行およびメモリ利用の断片化の最小化を、高水準で達成できるメモリ管理モデルで設計開発する技法があるが、こうした技法は複雑である。
ガベージコレクションの機構は、Java仮想マシンに組み込まれており、開発者からは、事実上隠蔽されている。開発者は、場合にもよるが、ガベージコレクションがいつ起こるか意識しなくて良い。というのも多くの場合、ガベージコレクションの実行は、プログラマが自分で書いたコードによって明示的に起こる何らかの挙動と、必ずしも関連しているわけではないからである。
Javaでは充実したライブラリにより、コンピュータネットワークを使うソフトウェアを、効率良く開発できる。Javaの初期のバージョンから、TCP/IP (IPv4) のライブラリを備えており、ネットワークでソケット通信を行うソフトウェアを簡単に実装できた。分散オブジェクト環境のソフトウェアの開発も早い時期からできるようになった。Java RMIもしくはCORBAの分散オブジェクト技術を標準で使うことができる。近年では、標準、拡張その他のライブラリにより、さまざまなネットワークプロトコルを高水準で扱えるようになっている。
現在ではIPv6も扱えるようになりつつある。
XML文書を扱う技術とネットワーク機能を有効に組み合わせることにより、高度なシステムやサービスを構築できるようになっている。
Javaでは初期のバージョンから遠隔のコンピュータ上にある実行コード(Javaアプレット)を安全に実行できるよう設計されていた。
Javaは、パッケージという名前空間の機構を持つ言語であり、ライブラリおよびアプリケーションソフトウェアに含まれる多数の Java のプログラム(クラスとインタフェース)を、パッケージの階層構造に分類・整理することができる。名前空間の機構を持たない言語と比べて、多数のクラスとインタフェースの管理が容易となり、クラスとインタフェースの命名についても、既存のクラス/インタフェースとの名前の衝突回避を考慮する労力が、大きく軽減される。
Java のバイトコードには複数の実行形態があると考えることができる。ただしいずれのバイトコードも、Java実行環境 (JRE) の下で実行されるという点では、同じと考えることもできる。
構文は、CおよびC++から多くを引き継いでいる。このため、設計当時には割合として多かった、CやC++しか書けないプログラマにも習得しやすいと、。Javaが設計された1990年代中旬以前は、Cのプログラマが多く、またオブジェクト指向プログラミング言語の中では、C++は広く使われてきた言語の一つだった。
なお、JavaではC++と違って名前空間レベルの関数(メソッド)および変数(フィールド)の宣言および定義を許可しておらず、必ず何らかのクラス定義の中に記述することが特徴である。この特徴は後発のC#も踏襲している。
次の節以降では、Hello worldプログラムで、Javaプログラムの例を示して説明する。
Hello worldプログラムとは、"Hello, world" という文字列をディスプレイなどの出力装置に出力する簡単なソフトウェアプログラムである。プログラミング言語の初学者向けのプログラム例としてよく使われる。
なお先に述べた通り、Javaには複数の実行形態があると考えることができるので、以降では、それぞれの実行形態におけるHello worldプログラムを例示する。
コマンドライン環境で動くスタンドアロンのJavaアプリケーションの例を示す。Javaでは、他のプログラミング言語と同様に、コマンドライン環境で動くプログラムを簡単に開発できる。
このプログラムについて説明する。
グラフィカルユーザインタフェース (GUI) 環境で動く Swingを使ったスタンドアロンのJavaアプリケーションの例を示す。Swingは、Java SEの高度なGUIのウィジェット・ツールキットのライブラリである。
Javaアプレットは、他のアプリケーションに埋め込まれるプログラムである。多くの場合は、ウェブブラウザに表示されるウェブページに埋め込まれる。
Javaサーブレットは、サーバ側のJava EEの構成要素であり、クライアントから受けた要求 (request) に対する応答 (response) を生成する。現在、多くの場合はウェブブラウザから要求を受け、応答としてXHTML / HTMLのウェブページを動的に生成する。
Javaプラットフォームの構成を説明する。
Java実行環境 (JRE; Java Runtime Environment) は、Javaプラットフォームに配置されたJavaアプリケーションを実行するために必要な、ソフトウェアである。標準クラスライブラリやJava仮想マシンなどから構成される。
エンドユーザは普通、Javaソフトウェアパッケージやウェブブラウザプラグインの利用を通じてJREを使う。オラクル / JCPをはじめ複数の団体や企業により、 さまざまなプラットフォーム向けに、多くの JRE の実装が開発・提供されている。
JREの他、オラクル / JCPなどの団体・企業は、Java開発キット (JDK) と呼ばれるJREのスーパーセットの実装を開発・提供している。JDKは、Javaプログラムの開発を支援する基本的なソフトウェアであり、多くの開発ツールが含まれている。
Java実行環境は、標準クラスライブラリとJava仮想マシン、およびいくつかのファイルとソフトウェアから構成される。
Java開発キット (JDK; Java Development Kit) は、オラクル / JCP をはじめ複数の団体や企業により開発・提供されている、Javaプログラムの開発を支援する基本的なソフトウェアである。Javaが世に出て以来、広く使われてきたJavaの開発ツールである。javac、javadoc、デバッガなどを含む多くの開発ツールが含まれている。また、完全なJava実行環境 (JRE) を同梱している。
Javaプログラムを実行するだけであれば、Java実行環境が導入されていれば充分で、Java開発キットを導入する必要は無い。
Java開発キット (JDK) の呼称は、これまでに何度か変更されている。
広く使われているプラットフォームなどに対しては、複数の団体や企業が独自にJREやJDKの実装を開発・提供している。独自の最適化技術を適用したり、特定の用途に特化した最適化、あるいは異なるライセンスを採用するなど、それぞれ特徴がある。
オラクルおよびいくつかの団体が、オープンソースもしくはフリーソフトウェアのライセンスで利用できる、Java仮想マシンおよびJRE 、JDKの実装を開発している。
サン / JCPはJava発表時からJava仮想マシンおよび標準ライブラリの仕様を公開しており、Java標準クラスライブラリのソースコードもJDKの一部として提供していた。しかしソースコードの改変は下記のOpenJDKリリースまでライセンスで認めていなかった。そのため、サンの実装とは別に、オープンソースもしくはフリーソフトウェアでかつサンの実装と互換性のあるJava標準クラスライブラリとJava仮想マシンが開発された。また、2006年にサンはライセンスの方針を変更し近い将来オープンソースにする意向を表明し、2007年5月8日にJava SE 6をOpenJDKとして GNU General Public License にてリリースした。
GNU Classpathは、2007年3月現在、J2SE 1.4のライブラリの99%以上を実装し、J2SE 5.0では95%以上を実装している。
またOpenJDKにはIBMが協力している。
GNUプロジェクトがGNU Interpreter for JavaおよびGNUコンパイラコレクション (GCC) のJava版であるGNU Compiler for Javaを出している。GNU Compiler for Javaはahead-of-timeコンパイラを搭載しており、Javaのソースコードやバイトコードをネイティブマシンコード(Windowsの場合はexeファイル)に変換できる。クラスライブラリはGNU Classpathを使っており、1.4のほとんどの部分が対応しており、5.0の部分も実装が進んでいる。
Windows環境では、GCJはMinGW (Minimalist GNU for Windows) もしくはCygwinを使って実行できる。Cygwinの場合は、対象がライセンスがGPLのソフトウェアに限られるが、MinGWの場合は商用含め、すべてのソフトウェアで利用できる。
米Excelsior社がExcelsior JETというahead-of-timeコンパイラを販売している。Java SE 用に書かれたプログラムを Windowsのネイティブマシンコードであるexeファイル(実行ファイル)に変換できる。起動の高速化やアプリケーションの難読化を実現する。
Windowsにて、配布、実行しやすくするために、Javaのjarファイルをexeファイル(実行ファイル)でラッピングするツールがある。以下が、その一例である。
Java Web Startには、適切なバージョンのJREをインストールする機能があるが、そもそも、JREがインストールされていない場合は、それが不可能である。JSmoothなどでは、ラッピングされたexeが、必要なJREがインストールされていないことを検出した時は、JREをダウンロードして、インストールする機能を持つ。また、上記3つすべてにおいて、JREを同梱して、同梱したJREを使ってアプリケーションを実行する機能を持つ。
また、通常のJavaアプリケーションでは、Windowsのタスクマネージャには、java.exeやjavaw.exeと表示され、Javaのアイコンが表示されるが、自前のexeファイル名と自前のアイコンを表示する機能を持つ。
さらに、上記のいくつかは、アプリケーションの2重起動を防止したり、アプリケーションをWindowsサービス(NTサービス)化する機能を持つ。
サンが特定のOSに特化した機能を提供することを嫌がっていたため、これらの機能が不足しており、それを補うために、exeパッケージ化が存在する。
オラクルとJCPは、さまざまな環境に対応するため、3つのJavaプラットフォームのエディションを規定している。JavaのAPIの多くは分類され各エディションに割り当てられている。
エディションごとに実行環境と開発環境がある。Java実行環境 (JRE) は、Java仮想マシンと標準ライブラリの実装から構成される。JDK 1.1のバージョンまでは、Java SEに相当するエディションのみが提供されていた。3つのエディションが規定されたのは、JDK 1.1の次のバージョンからである。オラクル / JCPが規定しているエディションを次に示す。
Java API に含まれるクラスは、パッケージと呼ばれるグループに分類される。各パッケージは、相互に関連するインタフェース、クラス、例外を含む。Java の各エディションでどのような機能が使えるかについては、それぞれのエディションの項目 (Java SE, Java EE, Java ME) を参照のこと。
JavaのAPIセットは、オラクルと他の個人や企業・団体が共同で、JCP (Java Community Process) プログラムに沿って管理している。このプロセスに参加する人々が、Java APIの設計と開発に関わっている。このプロセスのあり方については、議論の対象となっている。
2004年より、IBMとBEAシステムズ(後にオラクルが買収)は、Javaの公式のオープンソース実装を作る動きを、公的に支援している。2006年まで、サンはこうした動きに対しては拒否する立場をとってきたが、方針を変えて自社とJCPによるJavaの実装をオープンソースにする意向を表明し実行に移し始めている。
Javaの標準機能に対する拡張機能は、多くの場合、codice_113パッケージに属する。こうした拡張機能は、Java SEの Java開発キット (JDK) や Java実行環境 (JRE) には含まれない。Java の拡張機能や関連技術は、プログラミング言語Javaと密接に連携する。主なJavaの拡張機能と関連技術を示す(いくつかの拡張機能は近年のJava SE標準ライブラリに統合された)。
現在、Javaプラットフォームの将来のバージョンや機能は、JCP (Java Community Process) の標準化プロセスのもとで開発されている。JCPのメンバになることで、Java技術の将来のバージョンや機能の定義に関与することができる。JCPには、IBM、ボーランド、富士通、Apacheソフトウェア財団、ヒューレット・パッカード など、さまざまな個人、団体、企業がメンバとして参加している。
JCPは、Javaプラットフォームに追加する仕様や技術を、JSRs (Java Specification Requests) という文書群に記述する。
プログラミング言語JavaとJavaコアAPIに関わるいくつかの JSRs を示す。
Javaアプリケーションを開発するための開発ツール(開発用ソフトウェア)をいくつか示す。次に示すツール以外にも、数多くのツールが開発・提供されている。
Javaプログラムを開発できるいくつかの統合開発環境 (IDE) を示す。
Javaに対しては、優れた技術だと評価する人々がいる一方で、批判も少なくない。Javaは、ソフトウェアに関する複雑さを管理する問題に対して、革新的な方法を提供するという目標の下で、開発された。多くの人々は、Java技術は、この期待に対して満足できる答えを提供したと評価している。しかしJavaにも欠点が無いわけではない。Javaは、どのようなプログラミング作法にも適応しているわけではない。また、どのような環境や要件にも普遍的に適応しているわけではない。
Javaに対する批判を大まかに記述する。
Javaの初期のバージョンでは、CやC++などのネイティブにコンパイルする言語と比べて、とても実行が遅くメモリの消費が激しいとして、批判されることが多かったが、のバージョンでは改善されてきている。近年のJava仮想マシンで採用しているジャストインタイムコンパイラや動的再コンパイルの実行性能は、従来の言語のネイティブコンパイラとほぼ同じ水準の実行性能かそれ以上を達成することがある。これは頻繁にメモリアクセスを行うプログラムにおいてJavaのガベージコレクションの技術が、Cのmallocやfreeよりも高い性能を発揮できることによる。こうした事情から、Javaの実行性能については、議論の対象となっている。
ルックアンドフィールに関して、JavaのSwingのツールキットを使ったグラフィカルユーザインタフェース (GUI) を備えたアプリケーションの既定のルックアンドフィールが、従来のネイティブなアプリケーションとは大きく異なるため、エンドユーザの人々にとってJavaのGUIアプリケーションはなじみにくいと批判されることがある。Javaではプラグイン可能なルックアンドフィールの機構を備えており、サンは Windows、macOSおよびMotifの各ルックアンドフィールのクローンを提供した。そのため、Swingの既定のルックアンドフィールではなく、プラットフォームネイティブと同様のルックアンドフィールでJavaのアプリケーションを動かすよう指定することができる。しかしエンドユーザにとってこの指定方法は簡単ではないと指摘されることがある。
言語の設計(デザイン)に対する批判をいくつかの側面から述べる。
Javaの設計者は、他のプログラミング言語では備えているいくつかの機能をJavaから排除した。利便性より言語設計の簡潔さを優先した結果だが、こうした設計上の判断については賛否が分かれている。
また、Javaは、Smalltalkのように「純粋な」オブジェクト指向プログラミング言語ではないとして、設計の一貫性のなさを批判されることがある。たとえばJavaには、プリミティブ型という、クラス型(参照型)ではないものがある。Javaの設計者は、実行性能上の理由から、意図的にプリミティブ型をJavaに導入した。例えば、codice_3型などの組み込み型がプリミティブ型に相当する。codice_3型の値はオブジェクトではなく、これをクラス型のオブジェクトとして扱うには、ラッパーであるcodice_116クラス型への変換(ボクシング)が必要になる。J2SE 5.0以降ではオートボクシングにより、プリミティブ型と、それに対応するボックスクラス型の間のやりとり(変数への代入や値の参照など)は、コンパイラによって自動的に行われるようになり、ソースコード上の煩雑さは軽減されたが、本質的に同じものを指すはずのデータ型が複数存在するという矛盾を依然として抱えたままである。
一方で、C++のように名前空間レベルのメソッドやフィールドを定義できず、必ずクラス定義が必要であることから、クラスを定義する側も利用する側も記述量が肥大化しがちである。J2SE 5.0 では、メソッドとフィールドのstaticインポートを行えるようになり、クラス修飾なしでstaticメンバーを利用できるようになった。しかしstaticインポートを不用意に使うとソースコードを判読困難にする可能性がある。サン / JCPはstaticインポートを適切に使用するガイドラインを合わせて公開した。
なお、C#はDelphiの設計思想を取り入れた言語であり、登場当初からプロパティをサポートしている。演算子オーバーロードについても、C++より限定的ではあるがサポートされる。そのほか、Javaで問題視されていたプリミティブ型の扱いやジェネリクスなどに対して、C#は独自の解決策を提示している。
一般に、Javaプログラムを実行する際、-classpathオプションを使用するか、環境変数のクラスパス (CLASSPATH) を必要に応じて適切に設定する必要がある。クラスパスを指定すると、既定のカレントディレクトリという設定が上書きされる。したがって、クラスパスを変更するソフトをインストールするなど設定を変えられた場合は、Java実行環境は正しくJavaプログラムを実行することができなくなることがある。このため Javaを使い始めた人々は、クラスパスについて戸惑うことがある。サンは-classpathオプションを指定する方法を推奨していた。
Javaは高い移植性と互換性を実現するべく開発されており、ある程度の水準まで達成しているが、課題が残っている。Javaのバージョン間の下位互換性・上位互換性が完全ではないことが問題として議論の対象になっている。Javaでは高い移植性を保っているため、一部のプラットフォームにしかない独自の機能はJavaからは使えない。
サン・マイクロシステムズは複数のJava認定資格を主催していた。オラクルによる買収後、一部資格は変更されている。ただし、買収前に以下の資格を取得した者は買収後も有効資格である。
現行はオラクルが以下のJava認定資格を主催している。これらのうちOracle認定Java EE 6 Enterprise JavaBeansディベロッパ以外の試験はサン・マイクロシステムズが主催していた試験の、それぞれ略号の "OCJ" を "SJC" に変更したものに対応する位置付けにある。
認定試験に不合格だった場合、その試験日を含めて14日以内は同一試験を受験することができない。
"""
In [20]:
%%solution
def get_ngrams(words, n):
""" # BEGIN PROMPT
pass
""" # END PROMPT
# BEGIN SOLUTION
i = 0
ngrams = {}
while i < len(words) - (n - 1):
current_ngram = []
for j in range(i, i + n):
current_ngram.append(words[j])
concat_ngram = ' '.join(current_ngram)
if concat_ngram in ngrams:
ngrams[concat_ngram] += 1
else:
ngrams[concat_ngram] = 1
i += 1
return ngrams
# END SOLUTION
In [21]:
%%studenttest GetNgramsStudentTest
assert get_ngrams(['I', 'am', 'fine', 'today'], 4) == {"I am fine today": 1}
assert get_ngrams(['I', 'am', 'fine', 'today'], 3) == {"I am fine": 1, "am fine today": 1}
In [22]:
%%inlinetest GetNgramsAutograderTest
try:
get_ngrams
except:
assert False, "get_ngrams is not defined?"
assert get_ngrams(['a'], 1) == {'a': 1}, 'get_ngrams does not work on a single word input: "a"'
assert get_ngrams(['a', 'b'], 1) == {'a': 1, 'b': 1}, 'get_ngrams does not count single words correctly'
assert get_ngrams(['a', 'b'], 2) == {'a b': 1}, 'get_ngrams does not count bigrams correctly'
assert get_ngrams(['a', 'b', 'c'], 2) == {'a b': 1, 'b c': 1}, 'get_ngrams does not count bigrams correctly'
assert get_ngrams(['a', 'a', 'a'], 2) == {'a a': 2}, 'get_ngrams does not count bigrams correctly'
try:
assert get_ngrams(['a', 'b'], 3) == {}, 'get_ngrams does not count single words correctly'
except Exception as e:
assert False, 'get_ngrams seems to have an index violation: ' + str(e)
In [23]:
%%submission
def get_ngrams(words, n):
n += 1
i = 0
ngrams = {}
while i < len(words) - (n - 1):
current_ngram = []
for j in range(i, i + n):
current_ngram.append(words[j])
concat_ngram = ' '.join(current_ngram)
if concat_ngram in ngrams:
ngrams[concat_ngram] += 1
else:
ngrams[concat_ngram] = 1
i += 1
return ngrams
In [128]:
result, log = %autotest GetNgramsAutograderTest
from IPython.core import display
display.display(report(GetNgramsAutograderTest, results=result.results))
assert(result.results['passed'])
In [ ]:
# Uncomment and run the following line for autograding your solution:
#Submit('GetNgrams')
# EXERCISE METADATA
exercise_id: "CountArticleNgrams"
以下のセルにcount_article_ngrams(article, n)を実装しましょう。articleは日本語の記事のテキストで、nはn-gramのnです。
戻り値python dictionary(辞書)にならなければなりません。キーはn-gram, 値はn-gramの頻度です。記事を単語に分けるために以上に定義された
tokenize_japaneseを使いましょう。
例えば、
count_article_ngrams('ウィキペディアを読みましょう!', 2)
以下の辞書を返さなければなりません
{'ウィキペディア を': 1, 'を 読み': 1, '読み ましょ': 1, 'ましょ う': 1, 'う !': 1}
In [ ]:
# EXERCISE CONTEXT
# Make sure we have a working get_ngrams implementation in the context of this test.
def get_ngrams(words, n):
i = 0
ngrams = {}
while i < len(words) - (n - 1):
current_ngram = []
for j in range(i, i + n):
current_ngram.append(words[j])
concat_ngram = ' '.join(current_ngram)
if concat_ngram in ngrams:
ngrams[concat_ngram] += 1
else:
ngrams[concat_ngram] = 1
i += 1
return ngrams
In [ ]:
%%solution
# Python, C++, Javaの記事からn-gramsを計算し、そのngramの出現回数ベクター
from collections import defaultdict
def count_article_ngrams(article, n):
""" # BEGIN PROMPT
pass
""" # END PROMPT
# BEGIN SOLUTION
ngram_count_dict = defaultdict(int)
for line in article.replace('。','\n').split('\n'):
sentence_tokens = tokenize_japanese(line)
sentence_ngrams = get_ngrams(sentence_tokens, n)
for ngram in sentence_ngrams:
ngram_count_dict[ngram] += 1
return ngram_count_dict
# END SOLUTION
In [131]:
%%studenttest CountArticleNgramsStudentTest
assert count_article_ngrams('ウィキペディアを読みましょう!', 2)=={'ウィキペディア を': 1, 'を 読み': 1, '読み ましょ': 1, 'ましょ う': 1, 'う !': 1}
In [ ]:
%%inlinetest CountArticleNgramsAutograderTest
try:
count_article_ngrams
except:
assert False, 'count_article_ngrams is not defined'
try:
res = count_article_ngrams('ウィキペディアを読みましょう!', 2)
except Exception as e:
assert False, 'count_article_ngrams returned error %s on input "ウィキペディアを読みましょう!"' % str(e)
assert 'ウィキペディア を' in res, "Did you extract bigrams correctly? With input 'ウィキペディアを読みましょう!' expected to see 'ウィキペディア を' in the bigram list, but only got [%s]" % ",".join(res.keys())
assert res=={'ウィキペディア を': 1, 'を 読み': 1, '読み ましょ': 1, 'ましょ う': 1, 'う !': 1}, "Have you run the test?"
In [ ]:
# Uncomment and run the following line for autograding your solution:
#Submit('CountArticleNgrams')
# EXERCISE METADATA
exercise_id: "NgramBasedArticleSimilarity"
以下のセルにngram_based_article_similarity(article1, article2, n)の関数を定義しましょう。article1とarticle2は日本語の記事のテキストです。nはn-gramのnです。
ヒント: count_article_ngramsとcosine_similartityを使いましょう。
実行例:
ngram_based_article_similarity("日本語が難しい", "日本語が難しい", 1) == 1.0
ngram_based_article_similarity("日本語が難しい", "日本語が優しい", 1) == 2/3
In [132]:
# EXERCISE CONTEXT
# make sure we have a correct implementation of count_article_ngrams and cosine similarity in context of the test
from collections import defaultdict
def count_article_ngrams(article, n):
ngram_count_dict = defaultdict(int)
for line in article.replace('。','\n').split('\n'):
sentence_tokens = tokenize_japanese(line)
sentence_ngrams = get_ngrams(sentence_tokens, n)
for ngram in sentence_ngrams:
ngram_count_dict[ngram] += 1
return ngram_count_dict
def get_ngrams(words, n):
i = 0
ngrams = {}
while i < len(words) - (n - 1):
current_ngram = []
for j in range(i, i + n):
current_ngram.append(words[j])
concat_ngram = ' '.join(current_ngram)
if concat_ngram in ngrams:
ngrams[concat_ngram] += 1
else:
ngrams[concat_ngram] = 1
i += 1
return ngrams
In [133]:
%%solution
def ngram_based_article_similarity(article1, article2, n):
""" # BEGIN PROMPT
pass
""" # END PROMPT
# BEGIN SOLUTION
article1_ngrams_count = count_article_ngrams(article1, n)
article2_ngrams_count = count_article_ngrams(article2, n)
return cosine_similarity(article1_ngrams_count, article2_ngrams_count)
# END SOLUTION
In [137]:
%%studenttest NgramBasedArticleSimilarityStudentTest
assert abs(ngram_based_article_similarity("日本語が難しい", "日本語が難しい", 1) - 1.0) < 0.1
assert abs(ngram_based_article_similarity("日本語が難しい", "日本語が優しい", 1) - 2.0/3.0) < 0.1
In [ ]:
%%inlinetest NgramBasedArticleSimilarityAutograderTest
assert abs(ngram_based_article_similarity("日本語", "日本語", 1) - 1.0) < 0.1
assert abs(ngram_based_article_similarity("日本語が", "日本語が", 1) - 1.0) < 0.1
assert abs(ngram_based_article_similarity("日本語が難しい", "日本語が難しい", 1) - 1.0) < 0.1
assert abs(ngram_based_article_similarity("日本語が", "日本語が", 2) - 1.0) < 0.1
assert abs(ngram_based_article_similarity("日本語が難しい", "日本語が優しい", 1) - 2.0/3.0) < 0.1
assert abs(ngram_based_article_similarity("日本語が難しい", "日本語が難しい", 3) - 1.0) < 0.1
In [ ]:
# Uncomment and run the following line for autograding your solution:
#Submit('NgramBasedArticleSimilarity')
In [0]:
cpp_up_to_n_grams = defaultdict(int)
python_up_to_n_grams = defaultdict(int)
for n in range(1, 10):
similarity_score = ngram_based_article_similarity(cpp_article, python_article, n)
if similarity_score == 0:
break
print("{}-grams cosine similarity (Python vs C++): {}".format(n, similarity_score))
for index in range(10):
cpp_article_ngrams = sorted(count_article_ngrams(cpp_article, n).items(), key=lambda x:x[1], reverse=True)
if n >2:
cpp_up_to_n_grams.update(cpp_article_ngrams)
python_article_ngrams = sorted(count_article_ngrams(python_article, n).items(), key=lambda x:x[1], reverse=True)
if n >2:
python_up_to_n_grams.update(python_article_ngrams)
print("{}\t|\t{}".format(cpp_article_ngrams[index], python_article_ngrams[index]))
print("up-to-10-grams cosine similarity (Python vs C++): {}".format(cosine_similarity(cpp_up_to_n_grams, python_up_to_n_grams)))
In [0]:
java_up_to_n_grams = defaultdict(int)
python_up_to_n_grams = defaultdict(int)
for n in range(1, 10):
similarity_score = ngram_based_article_similarity(java_article, python_article, n)
if similarity_score == 0:
break
print("{}-grams cosine similarity (Python vs Java): {}".format(n, similarity_score))
for index in range(10):
java_article_ngrams = sorted(count_article_ngrams(java_article, n).items(), key=lambda x:x[1], reverse=True)
if n >2:
java_up_to_n_grams.update(java_article_ngrams)
python_article_ngrams = sorted(count_article_ngrams(python_article, n).items(), key=lambda x:x[1], reverse=True)
if n >2:
python_up_to_n_grams.update(python_article_ngrams)
print("{}\t|\t{}".format(java_article_ngrams[index], python_article_ngrams[index]))
print("up-to-10-grams cosine similarity (Python vs Java): {}".format(cosine_similarity(java_up_to_n_grams, python_up_to_n_grams)))
In [0]:
java_up_to_n_grams = defaultdict(int)
cpp_up_to_n_grams = defaultdict(int)
for n in range(1, 10):
similarity_score = ngram_based_article_similarity(java_article, cpp_article, n)
if similarity_score == 0:
break
print("{}-grams cosine similarity (Java vs C++): {}".format(n, similarity_score))
for index in range(10):
java_article_ngrams = sorted(count_article_ngrams(java_article, n).items(), key=lambda x:x[1], reverse=True)
if n >2:
java_up_to_n_grams.update(java_article_ngrams)
cpp_article_ngrams = sorted(count_article_ngrams(cpp_article, n).items(), key=lambda x:x[1], reverse=True)
if n >2:
cpp_up_to_n_grams.update(cpp_article_ngrams)
print("{}\t|\t{}".format(java_article_ngrams[index], cpp_article_ngrams[index]))
print("up-to-10-grams cosine similarity (C++ vs Java): {}".format(cosine_similarity(java_up_to_n_grams, cpp_up_to_n_grams)))
In [0]:
#@title ウィキペディア記事「栃木県」をtochigi_article変数に読み込む
tochigi_article = """
栃木県
栃木県(とちぎけん)は、日本の都道府県の一つ。関東地方北部に位置する。県庁所在地は宇都宮市。県内には日光国立公園が立地し、日光・那須などの観光地・リゾート地を有する。
関東地方北部に位置する県で、人口は約198万人。境界部に海岸線を有しない内陸県である。県内の地域区分は概ね宇都宮市、鹿沼市、下野市、真岡市、さくら市などを中心とする県央、小山市、栃木市、佐野市、足利市など国道50号沿線の県南、那須野が原に広がる那須塩原市、大田原市、那須町や県北西部を占める日光市を中心とする県北に分類される。
地勢は、北部から北西部にかけて奥羽山脈、日光連山、足尾山地が連なり、標高1500m - 2500m程の急峻な山岳が連なっている。これらの山々から流れ出る鬼怒川、那珂川、渡良瀬川等諸河川が関東平野の北端を形成し、更に北に進むと那須野が原に至り、県北の町並みが広がる。
県土のほぼ中央に宇都宮市が立地し、人口は県全体の4分の1に当たる約50万人が集中している。そのほかは、県南の小山市、栃木市、足利市、佐野市、県北の那須塩原市が10万人以上の人口を抱えている。県南に人口の多い市が連なる。
産業は、農業、工業、商業、観光業のバランスがとれ、それぞれ盛んである。
農業は、平野部が米や麦の産地、那須野が原などの高原部(那須高原)が酪農地、畜産地となっているほか、いちごやかんぴょうなどの特産物も生産されている。
工業は、東北自動車道・国道4号と北関東自動車道・国道50号を軸とする地域に、北関東工業地域、及び、関東内陸工業地域(本県の場合は両者の定義に当てはまる)が広がり、第二次世界大戦中に軍需産業が集積した宇都宮市では、機械工業や金属工業、食品・飲料工業が、真岡市、上三川町、芳賀町では自動車関連産業(日産自動車系、本田技研工業系)が、那須塩原市、大田原市ではタイヤ製造や精密機械工業(医療機器、写真用レンズ製造)がそれぞれ発達している。また、県南では、食品・飲料工業や機械工業、機械・自動車部品等の中小規模の工場が広く立地するほか、伝統的に繊維産業が盛んである(結城紬、足利銘仙)。
商業は、宇都宮市における小売業が発達し、ほか工業地域では卸売業も盛んである。
観光業は、日光・鬼怒川エリアや、那須・塩原エリアで盛んで、日光市の鬼怒川温泉、川治温泉、湯西川温泉、日光湯元温泉、那須町、那須塩原市の那須温泉郷、塩原温泉郷のような、飛鳥時代や奈良時代からの古い歴史を持つ名湯。東照宮・日光二荒山神社・輪王寺の二社一寺で構成される世界遺産、日光の社寺。いろは坂に華厳の滝、中禅寺湖や戦場ヶ原など、風光明媚な奥日光の景勝地。皇室の御用邸や那須岳、殺生石に代表される別荘地や牧場、温泉が広がる那須高原と豊かな自然や文化に育まれた名所を有している。これらの地域は日光国立公園の指定地域内にあり、自然保護などの施策も執られている。日光市の一部には尾瀬国立公園に指定された地域も存在する。
茨城県や群馬県と共に北関東を構成する。
人口は、約198万人で全国第18位、(本県に近い人口規模の県としては、岐阜県の約204万人、群馬県の約197万人、福島県の約193万人、岡山県の約192万人等が挙げることができる)。面積は6,408.28 kmで全国第20位(関東地方最大の面積)、東西約84 km・南北約98 km。県庁所在地の宇都宮市は、東京から約100 km、JR東北新幹線で約50分強の位置にあり、中核市の指定を受けている。
地形的には東部の八溝山地、北部から西部にかけての那須連山・下野山地(高原山・日光連山・帝釈山地)・足尾山地の山岳地帯と、県中央部の那珂川・鬼怒川・渡良瀬川の沿岸平野部の3地域に大別される。
東部の八溝山地は標高600 - 1,000 mの阿武隈高地に続く比較的なだらかな山地が連なる。
北部から西部にかけての山岳地帯は日光国立公園、尾瀬国立公園(帝釈山、田代山湿原周辺)に指定されており、日光・鬼怒川・川治・塩原・那須などの観光地がある。北部には奥羽山脈(那須火山帯)に連なる那須連山・高原・男体・日光白根山などの諸火山がある。日光連山他の険しい山岳地帯は、標高2,000 m以上の山脈が関東の北限を形成し、瀑布や湖沼が点在している。また、諸河川の源にもなっており、鬼怒川は中央部を、渡良瀬川は群馬県との県境を流れ利根川に合流し、那珂川は八溝地域から東折し茨城県に入り、ともに太平洋に注いでいる。
南部・東部は、そのほとんどが関東平野の一端で、首都圏の一角として市街化が進んでいる。
群馬県や茨城県や福島県の隣接自治体と深いつながりを持つ県内市町がある一方で、埼玉県との隣接に関しては、渡良瀬遊水地により飛び地状態になっている栃木市藤岡町下宮地区とのみ、自動車用道路で行き来可能である。事実上、自動車や鉄道で埼玉県に入る場合、群馬県か茨城県を経由しなければならない。栃木県と埼玉県を結ぶ主要幹線の国道4号、東北本線、東北新幹線は茨城県、同じく東北自動車道、東武伊勢崎線、東武日光線は群馬県を経由して埼玉県に入る。
なお、この地区は栃木県・埼玉県・群馬県の3県境が交差する地点が畑の中に存在し、看板が設置されている。山間部や河川上で3県が交差する地点はあるが、平地にあるのは珍しい。
中南部地域は関東平野の中北部に立地し、南端部には渡良瀬川と思川、利根川、また田川と鬼怒川のそれぞれ合流点があり、茨城県、群馬県、埼玉県と境界を接している。一方、県北西部地域は奥羽山脈の南端部に位置し、山岳地域となっており、北東部は低山地で那珂川が縦断して開析が進んだ八溝山地とともに茨城県境を形成しているが、北西部は関東地方屈指の山岳地帯であり、標高2,000メートル以上の山並みが続き群馬県および福島県との境界を形成している。特に日光連山は標高2,300メートル以上の峻険な独立峰を複数有し、空気の澄んだ日には関東南部からも遠望できる。この日光連山と八溝山地の北部接点付近に立地する那須岳は関東の最北端であり、福島県との境を成す。
気候は太平洋側気候を呈し、山間部では冬季の降雪、また平地部では同じく冬季の乾燥と夏季の雷を特徴とする。全県で夏季多雨多湿、冬季少雨乾燥を呈し、年間降水量は山間部で多く奥日光では2,000mmを超すが、平地部では少なく県南部では1,200mm程度である。
2017年度時点で日光地域、県南地域、県東地域、県央地域、那須地域の5地域区分の場合と河内地区、上都賀地区、南那須・芳賀地区、下都賀地区、那須・塩谷地区、安足地区の6地域区分が存在する。
嘗ては3地域に10の広域市町村圏があった(2005年1月の県央・県北・県南3地域区分参考資料)。
以下の14市5郡11町がある。町はすべて「まち」と読む。県内に村は無い。ただし、平成の大合併以前には“村”があり、その時はすべて「むら」と読んでいた。
都市雇用圏(10%通勤圏)の変遷
歴史的には古墳時代、毛野川(けぬのかわ)(現在の鬼怒川)流域一帯には「毛野国」が成立し、これを上下に分かって「下毛野国(しもつけぬのくに)」「下野国(しもつけのくに)」が成立し、唐名では「野州(やしゅう)」と称する。現在でも「下野(しもつけ)」の呼称が広く使われている。
近世には豊臣政権による仕置が行われ、壬生氏、小山氏ら中世以来の氏族は領地を没収されるが、宇都宮氏や大関・大田原両氏の那須衆は豊臣政権に臣従し旧領を安堵されたほか、鎌倉公方の名跡を継ぐ喜連川氏や成田氏などが領地を得た。天正18年(1590年)には徳川家康が関東に移封され、下野は豊臣系大名と徳川領国の接点に位置する。なお、豊臣政権下での1597年(慶長2年)には宇都宮氏が改易されている。
豊臣秀吉没後の豊臣政権では五大老の家康と五大老の上杉景勝、五奉行の石田三成が対立し、慶長5年5月に家康は景勝討伐のため会津出兵を行う。三成は家康の出兵中に上方において挙兵し、家康は小山において上片へ引き返し、関ヶ原の戦いにおいて三成方を撃破する。家康が江戸に徳川幕府を開くと、中世以来の有力豪族は相次いで下野から姿を消し、県域は幕府直轄領や旗本領に細分化され、徳川家の譜代大名や旗本が支配するようになった。
江戸時代の幕藩体制においては宇都宮藩、壬生藩、烏山藩、黒羽藩、大田原藩、佐野藩、足利藩、吹上藩、高徳藩、喜連川藩の諸藩が成立し、福原家の佐久山陣屋、芦野家の芦野陣屋、那須家の福原陣屋、大田原家の森田陣屋など交代寄合の陣屋による領内統治が行われた。
下野国は江戸から奥州へ向かう結節点に位置し、近世には日光道中や奥州街道、壬生通りなど街道や脇往還、が整備され、小山宿や今市宿などの宿駅も整備された。また、利根川水系の渡良瀬川や思川、鬼怒川などの河川交通網も整備され、河岸が設置され舟運が行われた。
日光(日光市)は幕府の聖地として、東照宮をはじめとする華麗な建物が作られ、特別に保護・崇敬された。
近世期には日光山麓をはじめ各地で新田開発・用水開削が進むが、それに伴い秣場を巡る争論や水論も発生した。
江戸時代後期に入ると、今の栃木県域は、地域社会の著しい疲弊・荒廃と、急激な人口減少に見舞われることになる。人口推計によれば、江戸中期の享保6年(1721年)から、江戸後期の天保5年(1834年)までの約1世紀の間に、下野国の総人口は、約56万人から、61.1%の約32万人まで減少し、1世紀で約4割の人口減少という、事実上の人口崩壊状態となっている。同時期、日本の総人口は、度重なる飢饉にも関わらず、約10%の伸び(110.3%)を見せており、とりわけ飢饉が深刻であったとされる、東北太平洋側の陸奥国でも、1.5割弱の人口減少(86.1%)に抑えていることから考えても、江戸後期における、下野国の際立った荒廃ぶりが伺える。
このような状態の中で、二宮尊徳は農村のたて直しを図るため、桜町(現在の真岡市旧二宮町)の旗本領の復興につとめ、以後各地で報徳仕法と呼ばれる改革事業を実施した。
明治時代には「栃木」の表記に揺れがあった。「栃」は中国でクヌギ(櫟)を意味する漢字「櫔」(lì)を簡略化したと考えられ、「櫔木」の表記もあった。また、1871年の廃藩置県の後は「橡木」の表記が使われる例もあったが、「杤木」の表記が主であった。旁の「万」は、下側を「力」とつくる例もあった。1881年(明治14年)ごろより、「栃木」の表記が見られるが、旁は「櫔」に従って「厂」の中に「万」が主である。「厂」の中の「万」の部分は下側を「力」とつくる例や「丂」とつくる例もあった。「厂」の1画目を右から書く字形が生まれたのは昭和中期以降である。なお、中国語の文書で「櫪」や「枥」を使う例もみられるが、主に飼い葉桶を意味する字であり、誤りである。
栃木県の都市は、主に北部山岳地域から流れ出る鬼怒川、那珂川、渡良瀬川等の諸河川が太平洋に向かう流路帯の沖積平野と河岸段丘部に発達している。県域のほぼ中央に位置する宇都宮市は、北西部の山地部と中南部の平野部から成り、市街地はこの山地部と平野部の境界部に形成されている。
このほか、渡良瀬川、田川、鬼怒川、那珂川、思川などの河川中流域には、それぞれ足利市、下野市、真岡市、那須烏山市、鹿沼市、栃木市、小山市といった中規模都市が発達している。
衆議院の小選挙区が5。参議院では、全県で1区を構成。
2008年(平成20年)度の県民総生産は7兆9901億円である。国のGDPと比較しても、過半数の国よりも大きな規模を有している。主要産業は、宇都宮市のほか上三川町、小山市、大田原市、真岡市、栃木市、足利市、鹿沼市、矢板市などに代表される内陸型近代工業で、これらは北関東工業地域の一部を形成している。ほか、農業も盛んであり、県北から流出する河川の豊かな水を利用した産業地帯で、米作が盛んなほか飲料工業も発達している。那須塩原市や大田原市、宇都宮市は国内有数の米産地となっているほか、那須塩原市では酪農も盛んであり、国内生乳生産量は北海道に次いで高い。ほか、真岡市や鹿沼市などを中心にいちごの栽培が盛んであり、壬生町や鹿沼市のかんぴょうとともに県の特産品となっている。商業は宇都宮市で盛んで、県内年間商品販売額の約半分が宇都宮市で占められており、県内第一の商業都市となっている。観光産業も盛んで、日光市や那須塩原市、足利市の歴史・自然遺産(日光の社寺、足尾銅山跡、足利学校跡、中禅寺湖、華厳滝、鬼怒川温泉、那須岳、那須高原、塩原温泉など)、宇都宮市の餃子やカクテル、ジャズ、茂木町のツインリンクもてぎ、栃木市の蔵の街なども観光資源となっている。
県庁所在地の宇都宮市は全国屈指の米産地であるほか、県の年間製品販売額の約半分を占め、工業生産額も県内市町村最大となっており、県内最大の農商工業都市となっている。
ちなみに、かんぴょうは栃木県が99%を生産し、残りは茨城県が生産している。
県内のほぼ中心を南北に東京と東北地方を結ぶJR東北新幹線、JR宇都宮線(東北本線)、東北自動車道、国道4号が南北に走る。
また宇都宮を中心にして放射線状に県内各地へと路線が伸びている。宇都宮を基準にして各方向への主要路線は次の通り。
このほかに東西を結ぶ路線は、県南部では茨城県、群馬県両県間を結ぶ北関東自動車道やJR両毛線、JR水戸線、国道50号など。県北部では、国道400号などがある。
南北方向には、県東部では国道294号など。県西部には東京から直通する鉄道路線の東武日光線、東武鬼怒川線、野岩鉄道会津鬼怒川線が走る。
栃木県内に空港は存在しない。最寄りの空港は成田国際空港(千葉県成田市)・東京国際空港(東京都)国際空港に限らない場合は茨城空港(茨城県)、福島空港(福島県)
放送対象地域は関東広域圏に属する。栃木県域放送のとちぎテレビ・NHK宇都宮放送局のほかに、NHK放送センター(教育テレビ)と在京キー局5局(日本テレビ・テレビ朝日・TBS・テレビ東京・フジテレビ)が県内全域が放送区域になっている。また、とちぎテレビのみならずNHK・キー局ともに県内各地に中継局を置いている。
※JRN系列のTBSラジオ、NRN系列の文化放送・ニッポン放送も放送対象地域になっている。
1994年(平成6年)、栃木市の栃木コミュニティ放送に免許が交付されたことがあるが(JOZZ3AA-FM:FM蔵の街)、経済的な問題もあり免許を取り下げたため、コミュニティ放送局は2015年10月までない状態が20年近く続き、新規の開局の機運はなく、全国で唯一コミュニティ放送の無い都道府県「空白県」であったが、2015年(平成27年)1月27日、栃木ケーブルテレビ(運営・ケーブルテレビ株式会社)が運営するとちぎシティエフエム(JOZZ3CB-FM)に予備免許が交付され、栃木県にもコミュニティ放送が開局の見通しとなった。
ゆるきゃら・ご当地キャラ
"""
In [0]:
#@title ウィキペディア記事「鳥取県」をtottori_article変数に読み込む
tottori_article = """
鳥取県
鳥取県(とっとりけん)は中国地方の日本海側にあり、山陰地方の東側を占める県である。同県は全国で面積は7番目に小さく、人口は最も少ない。県庁所在地は鳥取市。
国土地理院の全国都道府県市区町村別面積調によると、鳥取県の面積は平方キロメートルである。
国土地理院地理情報によると鳥取県の東西南北それぞれの端は以下の位置で、東西の長さは125.41km、南北の長さは61.79kmである。
鳥取県は県内ほぼ全域が日本海側気候で、豪雪地帯となっている。春と秋は好天の日が多く、夏は南風によるフェーン現象で猛暑日となることもあるが平野部でも熱帯夜は少ない。冬は曇りや雨、雪の日が多いが、平野部の1月平均気温は4℃台と東京郊外や名古屋、京都と同じくらいであり冷え込みは厳しくない。米子などの西部沿岸部は平年の最深積雪は20cm程度と比較的雪は少ないが、東へ行くほど降雪/積雪量は多くなり、鳥取市では中心部でも平年で40cm以上の最深積雪を観測する。東部ではJPCZ(日本海寒帯気団収束帯)の影響を受けやすい鳥取市や岩美町などの沿岸部のほうが智頭町などの内陸部よりも降雪量が多くなることがある。
特に大山周辺の内陸山地は山陰一の豪雪地帯となっており、冷え込みも厳しく−15°C以下にまで下がることもある。
県域はかつての因幡国、伯耆国に相当し、4市・5郡・14町・1村がある(町はすべて「ちょう」、村は「そん」と読む)。現在は東部・中部・西部の3つに区分するのが一般的で、鳥取市を中心とする東部は旧因幡国、倉吉市を中心とする中部と米子市や境港市を中心とする西部は旧伯耆国。旧因幡の東部に対して、同じ伯耆であった西部と中部を総称して中・西部と二区分にすることもある。
鳥取平野を中心とする旧因幡国の区域に相当し、鳥取砂丘や白兎海岸などの景勝地がある。県庁所在地で県唯一の施行時特例市でもある鳥取市は、液晶工場などが立地する工業都市でもある。
面積:km、
推計人口:人、
人口密度:人/km
旧伯耆国の東部、倉吉平野を中心とする区域。白壁土蔵群で知られる倉吉市を中心とし、三朝温泉、はわい温泉、東郷温泉といった温泉地も多い。
面積:km、
推計人口:人、
人口密度:人/km
かつての伯耆国西部、米子平野や日野川流域を含む地域。中国地方最高峰で日本百名山の一つ・大山(1,729m)があり、古来から隣県島根の旧出雲国地域との結びつきが強い。
面積:km、
推計人口:人、
人口密度:人/km
府県予報区は「鳥取県」。一次予報区分は2区分、「市町村等をまとめた地域」は5区分。二次予報区分は鳥取市以外は市町村単位で、鳥取市のみ北部・南部の2つに分かれている。
「鳥取」の語は『古事記』『日本書紀』の垂仁天皇に「鳥取造(ととりのみやつこ)」、「鳥取部(ととりべ)」が見える。
『古事記』には、大和朝廷が諸国に鳥を捕らえさせ、これを税として納めるように命じていたという一節があり、当時、沼や沢の多い湿地帯であった鳥取平野で水辺に集まる鳥などを捕らえて暮らしていた狩猟民族が、大和に政権ができてからその支配体系に組み込まれ、「鳥取部」として従属するようになり、そこからこの地が「鳥取」と呼ばれるようになったとされる。
『日本書紀』垂仁天皇二十三年九月から十一月の条にかけて「鳥取」の起源説話が見える。誉津別王子(ほむつわけのみこ)が成人しても言葉が喋れないことを天皇が憂いていた時、大空を白鳥が飛んでいるのを見つけ「是何物ぞ」と発した。天皇、喜びて、その鳥の捕獲を命じた。天湯河板挙(あまのゆかわたな)が鳥を追いつづけ各地を巡り、ついに出雲の地(現;島根県安来地方だという説が有力)で捕獲に成功した。この功績から「鳥取造」の称号(姓:かばね)を拝命した。『記』にも同類の説話が見えるが、結末が違っている。
『和名類聚抄』の因幡国邑美(おうみ)郡の五郷の一つに鳥取がある。この郷名は上述の垂仁天皇の王子本牟智和気御子(ほむちわけみこ)のために設置された鳥取部に由来する。この辺り一帯が沼地で、全国の白鳥伝説との関連が取り上げられている。文書のうえでは、天慶3年(940年)の因幡国高草郡東大寺領高庭庄坪付注進状(東南院文書)に「主張鳥取高俊」(郡司と推定)の署名が初見である。(参考文献 内藤正中他『鳥取県の歴史』山川出版社 2003年)
山陰道:因幡国・伯耆国
大山裾野丘陵から後期旧石器時代の黒曜石製と安山岩製のナイフ形石器や削器、彫器・掻器が見つかっている。今から約2万3千年前以降のものと推測される。また、旧石器終わり頃の黒曜石製細石刃と呼ばれる石器が発見されている。このように遺物は少数ながら発見されているが、県内からは人が生活した遺跡はまだ発見されていない。
因幡国では西軍方の宮部長熈、垣屋恒総、木下重堅が改易され、代わって亀井茲矩、池田長吉、山崎家盛の3大名が統治した(関ヶ原の戦い以前から鹿野城主であった亀井氏に関しては加増、それ以外の大名は転封)。
伯耆国においても吉川広家、南条元忠が西軍方として改易・転封処分となり、中村忠一が入部した。慶長14年(1609年)に中村忠一が急死すると、その翌年には加藤貞泰、市橋長勝、関一政の3大名に分割された。この時、河村郡・久米郡は幕府直轄領となり、山田直時・伊丹康勝が代官として派遣された。また、慶長19年(1614年)には里見忠義が倉吉に配流され、久米郡の一部4,000石が与えられた。
その後、元和4年(1618年)、池田光政が鳥取城に入部し、因伯2国からなる鳥取藩が成立した。このほか、鹿奴藩・若桜藩の2つの新田藩があった。
また、伯耆国汗入郡の大山寺は僧・豪円の活躍によって慶長15年(1610年)、徳川秀忠より寺領3,000石が認められた。この大山寺領は西伯耆一帯に散在し、18ヵ村が大山寺本坊西楽院の管掌下に置かれた。大山寺は鳥取藩士とは別の大山侍と呼ばれる武士を登用し、寺領支配に携わらせた。
鳥取県の人口は全国で最も少ない。また全国どの政令指定都市と比較しても少なく、政令指定都市以外で最大の千葉県の船橋市や、鹿児島県の県庁所在地の鹿児島市よりも少ない。2010年(平成22年)の国勢調査で588,418人と35年ぶりに60万人を下回った。
ただし、面積も小さいことから人口密度で見ると168.5人/kmと37位で、鹿児島県・長野県のそれと近い。
衆議院の小選挙区が2。参議院では、鳥取県選挙区として全県で1区を構成していたが、2016年の第24回参議院議員通常選挙より、島根県選挙区と合区され、鳥取県・島根県選挙区となり、島根県とともに1区を構成する合同選挙区が創設された。
鳥取県の行政機関は、鳥取県庁のほか、地方機関として総合事務所等が置かれている。なお、鳥取市・岩美町・若桜町・智頭町・八頭町については本庁が担当する。伯耆町(旧溝口町)は2005年(平成17年)4月1日に日野総合事務所から西部総合事務所へ、鳥取市(河原町・用瀬町・佐治町)は2007年(平成19年)4月1日に八頭総合事務所から東部総合事務所へ、それぞれ移管された。2013年(平成25年)4月1日に東部・八頭の各総合事務所が本庁に集約、日野総合事務所が西部総合事務所日野振興センターとなった。2018年(平成30年)4月1日の鳥取市の中核市移行に伴い、東部福祉保健事務所・東部生活環境事務所が鳥取市に移譲され、鳥取市保健所となった(管轄区域は変更なし。岩美町・若桜町・智頭町・八頭町についても、鳥取県からの事務委託により鳥取市に移譲)。
地方債の残高
人口が日本国内で一番少ない小さな県であるため、県内総生産(名目GDP)も2008年4月から2009年3月までのベース(平成20年度の統計)で1兆9927億円と、47都道府県では最も小さく、世界の中では国内総生産 (GDP) のランクが90位程度の国と同程度である。なお、これを一人当たりで見ると和歌山県・岩手県のそれに近い。また、一人当たり県民所得は230.4万円であり、全国平均の83.7%である。これは熊本県・鹿児島県のそれに近い。
スターバックスが未出店である唯一の県だったが、2015年5月23日に、同店の鳥取県1号店が鳥取市の鳥取駅南口付近に開業した。これにより、スターバックスは47都道府県全てに店舗を構えることになった。その後、イオンモール鳥取北内にも出店している。
スイカ、松葉ガニ、らっきょう、二十世紀梨など全国的に有名。米や野菜、果物などもバランスよく生産されている。
鳥取県警察本部の管轄にある。2005年(平成17年)4月1日に再編が行われ、以下の9警察署が置かれている。
おおむね兵庫県境~島根県境までの海岸線に沿った旧山陰道のルートに沿って走る幹線(鉄道の山陰本線や国道9号線)が県内主要都市(もしくはその付近)を通り、鳥取・米子・倉吉の各都市近辺から中国山地・山陽方面へルートが分岐する構造になっている。
()のないものは県内のみを走る路線。
日ノ丸自動車、日本交通の2社があり、県内の路線バスや県内各都市と県外を結ぶ高速バスを運行。
どんぐりコロコロは日本交通の運行、はまるーぷバスは日ノ丸自動車の運行、他3つは日本交通・日ノ丸自動車の共同運行。
全国で最もバス利用者が少ない。
松江市内に松江道路が開通した1998年(平成10年)4月17日以降、長らく「日本で唯一都道府県庁所在都市に高速道路がない県」であったが、2004年(平成16年)11月1日に山陰自動車道青谷インターチェンジのある青谷町を編入合併したため解消された。
鳥取県・島根県の県域民放各局は互いの県に乗り入れて放送を実施している。詳しくは電波相互乗り入れ#鳥取・島根両県の民放相互乗り入れ放送の項を参照。局名の後の( )内は局所在地。
※他に、鳥取県に系列局を持たないANN(テレビ朝日)系列が、取材拠点としてテレビ朝日米子支局・テレビ朝日鳥取支局を置いている。
鳥取県の方言は、東部と西部で大きく異なる。東部(因幡)の因州弁は兵庫県北部の但馬弁と共通した特徴を持ち、東山陰方言に分類される。中部(東伯耆)の倉吉弁は、伯耆でありながら因州弁に近い特徴を持つ。一方、西部(西伯耆)の方言は島根県東部の出雲弁と共通した特徴を持ち、雲伯方言に分類される。
"""
In [0]:
for n in range(1, 10):
similarity_score = ngram_based_article_similarity(tottori_article, tochigi_article, n)
if similarity_score == 0:
break
print("{}-grams cosine similarity (鳥取県 vs 栃木県): {}".format(n, similarity_score))
print("鳥取県\t | \t栃木県")
for index in range(10):
tottori_article_ngrams = sorted(count_article_ngrams(tottori_article, n).items(), key=lambda x:x[1], reverse=True)
tochigi_article_ngrams = sorted(count_article_ngrams(tochigi_article, n).items(), key=lambda x:x[1], reverse=True)
print("{}\t|\t{}".format(tottori_article_ngrams[index], tochigi_article_ngrams[index]))