モジュール java.base
パッケージ java.net

クラスURI

java.lang.Object
java.net.URI
すべての実装されたインタフェース:
Serializable, Comparable<URI>

public final class URI extends Object implements Comparable<URI>, Serializable
URI (Uniform Resource Identifier)参照を表します。

後述するいくつかの小さな変更を除けば、このクラスのインスタンスは、「RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax」で定義され、「RFC 2732: Format for Literal IPv6 Addresses in URLs」で修正されたURI参照を表します。 リテラルIPv6アドレス形式ではスコープIDもサポートされます。 スコープIDの構文や使用方法については、ここを参照してください。 このクラスは、コンポーネントからまたは文字列形式を解析してURIインスタンスを作成するためのコンストラクタ、インスタンスの各種コンポーネントにアクセスするためのメソッド、およびURIインスタンスを正規化、解決、相対化するためのメソッドを提供します。 このクラスのインスタンスは不変です。

URI構文とコンポーネント

最高位レベルの文字列形式のURI参照(以降は単に「URI」とする)の構文は次のとおりです。
[スキーム:]スキーム固有部分[#フラグメント]
ここで、角カッコ[...]はオプションのコンポーネントを表し、文字:#はその文字自体を表します。

絶対 URIはスキームを指定し、絶対でないURIは相対と呼ばれます。 また、URIは不透明であるか階層的であるかによって分類されます。

不透明 URIは、スキーム固有部分がスラッシュ(「/」)で始まらない絶対URIです。 不透明URIはそれ以上解析されません。 不透明URIの例を次に示します。

  • mailto:java-net@www.example.com
  • news:comp.lang.java
  • urn:isbn:096139210x

階層 URIは、スキーム固有部分がスラッシュで始まる絶対URI、または相対URI (スキームを指定しないURI)です。 階層URIの例を次に示します。

http://example.com/languages/java/
sample/a/index.html#28
../../demo/b/index.html
file:///~/calendar

階層URIは、構文に従ってさらに解析されます。

[スキーム:][//機関][パス][?クエリー][#フラグメント]
ここで、:/?、および#はその文字自体を表します。 階層URIのスキーム固有部分は、スキームとフラグメント・コンポーネントの間の文字で構成されます。

階層URIの機関コンポーネントが指定されている場合、その機関コンポーネントはサーバー・ベースまたはレジストリ・ベースです。 サーバー・ベース機関は、よく知られている構文に従って解析されます。

[ユーザー情報@]ホスト[:ポート]
ここで、@:はその文字自体を表します。 現在使用されているURIスキームのほとんどはサーバー・ベースです。 このように解析されない機関コンポーネントは、レジストリ・ベースと見なされます。

階層URIのパス・コンポーネントは、スラッシュ(「/」)で始まる場合は絶対と呼ばれ、そうでない場合は相対と呼ばれます。 絶対である階層URIまたは機関を指定する階層URIのパス・コンポーネントは常に絶対です。

URIインスタンスには、全部で次の9つのコンポーネントがあります。

URIのコンポーネントの説明: スキーム、スキーム固有部分、機関、ユーザー情報、ホスト、ポート、パス、クエリー、フラグメント
コンポーネント
スキームString
スキーム固有部分String
機関String
ユーザー情報String
ホストString
ポートint
パスString
クエリーString
フラグメントString
指定されたインスタンスでは、どの特定のコンポーネントも未定義定義済みであり、個別の型の値を持ちます。 未定義の文字列コンポーネントはnullで表され、未定義の整数コンポーネントは-1で表されます。 文字列コンポーネントは、値として空の文字列を持つよう定義できます。これは、そのコンポーネントが未定義であることと同等ではありません。

特定のコンポーネントがインスタンスで定義されるかされないかは、表現されるURIの型により異なります。 絶対URIにはスキーム・コンポーネントがあります。 不透明URIにはスキーム、スキーム固有部分、およびおそらくフラグメントがありますが、その他のコンポーネントはありません。 階層URIには、常にパス(ただし空の場合あり)およびスキーム固有部分(少なくともパスを含む)があり、さらにその他のコンポーネントのいずれかがある場合があります。 機関コンポーネントが存在していてサーバー・ベースである場合、ホスト・コンポーネントは定義されます。ユーザー情報とポート・コンポーネントは定義される場合もあります。

URIインスタンスの操作

このクラスでサポートされる主要な操作は、正規化解決、および相対化です。

正規化は、階層URIのパス・コンポーネントから不要な「.」および「..」セグメントを削除するプロセスです。 「.」セグメントは単に削除されます。 「..」セグメントは、「..」以外のセグメントが先行する場合にだけ削除されます。 正規化は不透明URIには影響しません。

解決とは、あるURIを別のベース URIに基づいて解決する処理のことです。 結果として得られるURIは、RFC 2396に規定された方法に基づいて、両方のURIのコンポーネントから構築されます。具体的には、元のURIで指定されていないコンポーネントについては、ベースURIから取得されます。 階層URIの場合、元のパスは、ベースのパスに基づいて解決されたあと、正規化されます。 たとえば、次のようになります。

sample/a/index.html#28                  (1)
ベースURIに対してhttp://example.com/languages/java/は結果URIは、
http://example.com/languages/java/sample/a/index.html#28
相対URI
../../demo/b/index.html    (2)
をこの結果に対して解決すると、次のようになります。
http://example.com/languages/java/demo/b/index.html
絶対と相対の両方のURIの解決、および階層URIの場合は絶対と相対の両方のパスの解決がサポートされます。 URI file:///~calendarは絶対なので、これをほかの任意のURIに対して解決すると、元のURIが生成されるだけです。 上記の相対URI (2)を相対ベースURI (1)に対して解決すると、正規化されていても相対のままのURIが生成されます。
demo/b/index.html

最後に、「相対化」は、解決の逆とみなすことができます。 uをスラッシュ文字('/')で終わる正規化された絶対URIにし、vを、ピリオド文字('.')またはスラッシュ文字('/')で始まらない正規化された相対URIにします。 次に、次の文が当てはまります:

u.relativize(u.resolve(v)).equals(v)
uをスラッシュ文字('/')で終わる正規化された絶対URIとし、vを正規化された絶対URIにします。 次に、次の文が当てはまります:
u.resolve(u.relativize(v)).equals(v)
この操作は、可能であればどこででも、ドキュメントのベースURIに対して相対的でなければならないURIを含むドキュメントを構築する場合に便利です。 たとえば、次のURI
http://example.com/languages/java/sample/a/index.html#28
を次のベースURIに対して相対化すると、
http://example.com/languages/java/
相対URI sample/a/index.html#28が生成されます。

文字カテゴリ

URI参照の各種コンポーネントで許可される文字は、RFC 2396で厳密に指定されています。 次のカテゴリを使用して、この制約について説明します。これらのカテゴリのほとんどはその仕様から取られています。
カテゴリ、 英字、数字、英数字、未予約、句読点、予約済み、エスケープ、その他を記述します
カテゴリ説明
alpha A から Z、およびa から zまでのUS-ASCII英文字
digit 0 から 9までのUS-ASCII 10進数字
英数字 すべての英字および数字の文字
未予約 すべての英数字文字、および文字列「_-!.~'()*」内の文字
句読 文字列「,;:$&+=」内の文字
予約済 すべての句読文字、および文字列「?/[]@」内の文字
エスケープ エスケープされたオクテット。つまり、パーセント文字(「%」)とそれに続く2桁の16進数(0-9A-F、およびa-f)で構成される三重項
other US-ASCII文字セットに含まれておらず、制御文字(Character.isISOControlメソッドを使って判定)でなく、空白文字(Character.isSpaceCharメソッドを使って判定)でないUnicode文字  (US-ASCIIに限定されているRFC 2396を変更したもの)

すべての有効なURI文字のセットは未予約予約済みエスケープ、およびその他の文字で構成されます。

エスケープ・オクテット、引用符、エンコーディング、およびデコーディング

RFC 2396では、エスケープ・オクテットをユーザー情報、パス、クエリー、およびフラグメントの各コンポーネントに表示することができます。 URIにおけるエスケープ処理の目的は、次の2つです。
  • URIにその他の文字を1つも含めないようにすることでURIをRFC 2396に厳密に準拠させる必要がある場合に、非US-ASCII文字をエンコードする。

  • そのままでは不正になるコンポーネント内の文字を引用符で囲む ユーザー情報、パス、クエリー、およびフラグメントの各コンポーネントは、有効または不正と見なされる文字の条件が多少異なる。

これらの目的のため、このクラスには次の3つの関連操作が用意されています。
  • 文字はUTF-8文字セット内のその文字を表すエスケープされたオクテットのシーケンスで置き換えてエンコードされる たとえば、ユーロ通貨記号(「u20AC」)は「%E2%82%AC」としてエンコードされる。 (特定の文字セットを指定しないRFC 2396を変更したもの。)

  • すべての不正な文字は、単にエンコーディングして引用符で囲まれる たとえば空白文字は、%20で置き換えて引用符で囲まれる。 UTF-8にはUS-ASCIIが含まれるので、US-ASCII文字の場合、この変換でRFC 2396で要求される効果が正確に得られる。

  • エスケープされたオクテットのシーケンスをデコードする。具体的には、そのシーケンスがUTF-8文字セット内で表している文字シーケンスで置換する。 UTF-8はUS-ASCIIを含む。したがって、デコード処理は、引用符で囲まれたすべてのUS-ASCII文字の引用符を解除する効果と、エンコードされたすべての非US-ASCII文字をデコードする効果がある。 エスケープされたオクテットのデコード時にデコード・エラーが発生した場合、そのエラーの発生したオクテットは、Unicode置換文字である\uFFFDに置き換えられる。

これらの操作は、次に示すように、このクラスのコンストラクタとメソッドで公開されます。
  • 単一引数コンストラクタは、その引数内のすべての不正文字が引用符で囲まれることを要求するが、存在するエスケープされたオクテットとその他の文字はすべてそのまま維持する。

  • 複数引数コンストラクタは、不正文字を含むコンポーネントからの要求に従って不正文字を引用符で囲む。 パーセント文字(%)は常に、これらのコンストラクタによって囲まれる。 その他の文字はすべてそのまま維持される。

  • getRawUserInfogetRawPathgetRawQuerygetRawFragmentgetRawAuthority、およびgetRawSchemeSpecificPartメソッドは、対応するコンポーネントの値をそのままの形式で返し、エスケープされたオクテットを解釈しない。 これらのメソッドから返される文字列には、エスケープされたオクテットとその他の文字の両方が含まれていることがあり、不正な文字は含まれない。

  • getUserInfogetPathgetQuerygetFragmentgetAuthority、およびgetSchemeSpecificPartメソッドは、対応するコンポーネント内のすべてのエスケープされたオクテットをデコードする。 これらのメソッドから返される文字列には、その他の文字と不正文字のどちらも含まれる可能性があるが、エスケープされたオクテットが含まれることはない。

  • toStringメソッドは、すべての必要な引用符を持つURI文字列を返すが、その他の文字が含まれる場合がある。

  • toASCIIStringメソッドは、完全に引用符で囲まれてエンコードされたURI文字列を返す。この文字列にはその他の文字は含まれない。

アイデンティティ

任意のURI uの場合に、常に次のようになります。
new URI(u.toString()).equals(u)
空の機関uの前に2つのスラッシュなどの冗長構文が含まれていないURI (file:///tmp/のとおり)の場合、またはホスト名の後にコロンが含まれていてもポート(http://www.example.com:のとおり)がなく、引用符で囲む必要のある文字以外の文字はエンコードしない場合は、次のIDも保持されます:
     new URI(u.getScheme(),
             u.getSchemeSpecificPart(),
             u.getFragment())
     .equals(u)
すべての場合において
     new URI(u.getScheme(),
             u.getAuthority(),
             u.getPath(), u.getQuery(),
             u.getFragment())
     .equals(u)
uが階層の場合
     new URI(u.getScheme(),
             u.getUserInfo(), u.getHost(), u.getPort(),
             u.getPath(), u.getQuery(),
             u.getFragment())
     .equals(u)
uが階層で、機関を持たないかサーバー・ベースの機関を持つ場合。

URI、URL、およびURN

URIはUniform Resource Identifierであり、URLはUniform Resource Locatorです。 したがって、抽象的に言えば、すべてのURLはURIですが、すべてのURIがURLであるとはかぎりません。 これは、URIの別のサブカテゴリであるURN (Uniform Resource Names)があるためです。 前に示したmailtonewsおよびisbnの各URIは、URNの例です。

URIとURLとの概念上の区別は、このクラスとURLクラスの間の相違に反映されています。

このクラスのインスタンスは、RFC 2396で定義されている構文としてのURI参照を表します。 URIは絶対、相対のいずれかになります。 URI文字列は、スキームが指定されていてもそれについては考慮せず、ジェネリックな構文に従って解析されます。 ホストが存在していてもその検索は実行されず、スキームに依存するストリーム・ハンドラの構築も行われません。 等価性、ハッシュ処理、および比較は、インスタンスの文字内容に基づいて厳密に定義されます。 言い換えれば、URIインスタンスは基本的に、比較、正規化、解決、および相対化という、スキームに依存しない構文上の操作をサポートする、構造化された文字列です。

これに対し、URLクラスのインスタンスは、URLの構文上のコンポーネントを表すだけでなく、その記述対象となるリソースへのアクセスに必要な情報も一部備えています。 URLは絶対でなければいけません。つまり、常にスキームを指定しなければいけません。 URL文字列は、そのスキームに従って解析されます。 どのURLに対してもストリーム・ハンドラが必ず確立されます。実際、使用可能なハンドラが存在しないスキームのURLインスタンスを作成することは不可能です。 等価性とハッシュ処理は、スキームと、ホストのインターネット・アドレス(存在する場合)の両方に依存します。比較は定義されません。 言い換えれば、URLは、解決という構文上の操作と、ホストの検索や指定されたリソースへの接続のオープンなどのネットワーク入出力操作をサポートする、構造化された文字列です。

APIのノート:
ファイル・パスおよびファイルUriを操作するアプリケーションは、2つの間で変換する適切なメソッドを使用することを検討する必要があります。 Path.of(URI)ファクトリ・メソッドとFile(URI)コンストラクタを使用して、ファイルURIからPathまたはFileオブジェクトを作成できます。 Path.toUri()File.toURI()を使用すると、ファイル・パスからURIを作成できます。 アプリケーションは、FileまたはPathインスタンスの直接文字列表現から、constructparse、またはresolveURIに試みないでください。

URLまたはURIの一部のコンポーネント(userinfoなど)は、先行するURLまたはURIの構築に不正に使用される可能性があります。 Urlまたはuriを処理するアプリケーションは、「RFC3986,セクション7,セキュリティに関する考慮事項」で推奨される推奨事項を考慮してください。

導入されたバージョン:
1.4
外部仕様
関連項目: