Sun Microsystems, Inc

JDK 目次

@deprecated タグ

「@deprecated」: 古い API を取り除くための機械的なヘルプ

John R. Rose
1996, 10, 4

問題 :

Java 1.1 では新しい API が数多く追加されました。その中には、既存の API に取って代わるものもあります。新しい API と古い API は同じパッケージ内に一緒に入っています。 一部の API が古くなってしまったことによって、プログラマの作業にさまざまな影響が及びます。最も大変なのは、これらの API をできるだけ無視し、使用を避けなければならないということです。

部分的な解決法 : 古くなったクラス、メソッド、フィールドに、「deprecated」というマークをつけることによって、プログラマが集中的に見るべき箇所を判別しやすいようにします。またコンパイラは、プログラマが推奨されない API を意図せずに使っている場合に通知を出すことによって、この作業を助けます。

詳細 :

ドキュメンテーションのコメント内に、新しいパラグラフタグ「@deprecated」を定義します (JLS $$184 参照)。このタグは、クラスとメンバの両方のドキュメンテーションコメント内に出てくる可能性があり、そのコメントが表す構造にのみ適用されます。

タグがついているパラグラフは空のこともあります。空ではない場合は、その推奨されない機能の使用を避けるための方法が記載されています。

同じ機能の新バージョンを参照するパラグラフには、「@see」タグがついています。

コンパイラは、ドキュメンテーションコメント行の先頭 (空白文字を除く) に「@deprecated」タグが付いているのを見つけると、そのクラス、フィールド、またはメソッドに対応するクラスファイルを出力する際に「Deprecated」属性を付けます。

さらに、クラスやメンバへのアクセスチェックを行うのと同時に、コンパイラはアクセスするクラスやメンバの「Deprecated」属性を探し、推奨されていないクラスやメンバが使われているときには警告を出します。

推奨されない API というのはクラスや個々のメンバ自体に対して適用されるものであり、クラス名やメンバ名に対して適用されるわけではありません。このため、1 つのメソッドが推奨されないオーバーロードと推奨されるオーバーロードの両方をもつこともあり得ます。また、推奨されるメンバが推奨されないメンバを隠したり、オーバーライドしたりして、推奨されない要素を取り除くことも可能です。推奨されないメソッドのオーバーライドがやはり推奨されない API である場合、そのオーバーライドに推奨されない API としてマークをつけるのは、プログラマの責任です。

推奨されない API を含むコンパイル単位と、推奨されないクラスまたはメンバを使用するコンパイル単位を同時にコンパイルすると、推奨されない API に対する警告は抑制されます。このため、古い API が警告なしにコンパイルされることがあります。現在のところ、これは推奨されない API についての警告を抑制する唯一の手段です。

コンパイル時に仮の「-strict」オプションを使うと、推奨されない API についての警告から重要なエラーまで、すべての警告を表示させることができます。このオプションは 1.1 では使用できません。

Javadoc は、推奨されない API のパラグラフを何らかの方法で強調します。そして、推奨されない API の名前の隣に目を引くような絵を挿入します。

実例 :

次に示すのは、推奨されないメソッドの最も一般的な形式です。

    /**
     * @deprecated
     * @see #getPreferredSize
     */
    public Dimension preferredSize() {
	return getPreferredSize();
    }
(注意: 「@deprecated」タグの後には、必ず空白文字または改行文字が続きます。「@see」タグは必ず行の先頭にあります。詳細については JLS の第 18 章を参照してください。)

単なる改名によって推奨されなくなった API の場合は、「このメソッドは getPreferredSize に変更されました」という記述がなく、新しい API を参照するための「@see」タグが記載されているだけのこともあります。

改名だけではなく、完全に設計を見直された API の場合、パラグラフの内容はもっと複雑になります。次に示すのは、削除されるメソッドの例です。

    /**
     * Delete multiple items from the list.
     *
     * @deprecated  Not for public use in the future.
     * This method is expected to be retained only as a package
     * private method.
     * @see #remove(int)
     * @see #removeAll()
     */
    public synchronized void delItems(int start, int end) {
    ...
    }
新しい 1.1 API を設計する際には、それによって古い API が推奨されなくなるかどうかを慎重に考慮する必要があります。このような API がある場合、古い API のユーザに対して新しい API への移行を推奨するためには、ドキュメンテーションコメントに推奨されない API のパラグラフを追加する必要があります。推奨されない API を表すパラグラフを空にすると、ユーザがその警告によって生成された警告に対処する際の手助けにならないので、空のパラグラフは好ましくありません。

ユーザを新しい API に移行させる有効な理由としては、次のものがあります。

どの理由を見ても、推奨されない API とするのは合理的ですが (必須ではありません)、これらの理由の重要度はすべて同じではありません。したがって、デフォルトでは、推奨されない API によって致命的なエラーが生成されることはありません。 また、推奨されない API のコメントは、ユーザが新しい API に移行する時期を決定する手助けとならなければならず、その API に変更を加えた技術的な理由を簡単に記載しなければなりません。

(推奨されない API の削除予定を記載するのは、あまりよいことではありません。これは、別の方法で連絡すべき業務上の決定事項です。)

推奨されないクラスの個々のメンバに、推奨されない API を示すパラグラフを追加する必要はありません。もちろん、そのメンバについて何か特別に記載すべき事項がある場合は例外です。

ある機能が推奨されなくなった場合、その事実をエンジニアリング組織に通知するようにします。そして、他のエンジニアがその変更内容に対応する意見 (賛否) を適切なタイミングで提出できるようにします。

設計上のその他のオプション :

コンパイラがドキュメンテーションコメントの内容を認識するようになったのは、今回が初めてです。(以前は、解析ツリー内の正しい場所にいるかどうかの確認は行いましたが、ドキュメンテーションのコメントは認識しませんでした。) これは、コンパイラの動作をコメントの内容に依存させるような設計は軽率だという考えがあったからです。

コメント内を認識するプログラムで、以前からあるものとしては「lint」があります。lint は /*PRINTFLIKE2*/ という形のコメントを使って C API に注釈を付けます。

Java ドキュメンテーションコメントは構造化されており、その構造は Java言語仕様で規定されています。つまり、この特殊なコメントの形式は当社が「所有」しているので、当社の設計は lint が使用する特色の少ない規則に比べると、合理的といえます。

推奨されない API にプラグマを使用する (<*deprecated*> など) という案もありましたが、このようにすると非互換の機能拡張が多数行われる可能性が出てくるので、乱用を避けるために採用されませんでした。

ただし、@deprecated はプラグマと同じように機能します。このタグはソース内にあり、ソースについての情報を表しますが、ソースの意味を変えてしまうことはありません。一般のプラグマと @deprecated が異なる点は、@deprecated は人間が見ることを目的としているという点です。

コンパイラは役に立つ警告を生成しますが、どのような規則も施行しません。推奨されない API のパラグラフの内容を使用するのはプログラマの責任です。データの第一のユーザは人間なので、これはコメントに属します。

「transient」などという新しいキーワードを追加する案もありました。これによって機械的な問題を解決することはできますが、代わりに言語自体を修正しなければならなくなります。特に、以前予約していなかったコーダー (var など) から識別子を取り除かなければなりません。 さらに、推奨されない API に対する警告を使用するのは主に人間なので、キーワードによるアプローチでは十分ではありません。またコメント規則を増やさなければならず、javadoc にもできれば統合する必要があります。したがって、キーワードによるアプローチは適当ではないと判断しました。

コンパイラはこれまで、ドキュメンテーションコメントを無視してきました。また一般には無視すべきでした。今回の変更は、明らかに例外的な措置です。しかし、 推奨されない API について別の設計オプションを選択すると、もっと悪質な不規則性が生じることになります。


Copyright (C) 1996 Sun Microsystems, Inc., 2550 Garcia Ave., Mtn. View, CA 94043-1100 USA. All rights reserved.

ご意見等は jdk-comments@java.sun.com までお送りください。