web-dev-qa-db-ja.com

Java(クラス自体のスコープ内で設定可能)に読み取り専用フィールドがありますか?

クラス内でwritableであるが、そのクラスの外でのみ「読み取り可能」な変数を使用するにはどうすればよいですか?

たとえば、これを行う代わりに:

Class C {
  private int width, height;

  int GetWidth(){
    return width;
  }

  int GetHeight(){
    return height;
  }

  // etc..

私はこのようなことをしたいと思います:

Class C {
  public_readonly int width, height;

  // etc...

最適なソリューションは何ですか?

35
Pacerier

Javaでこれを行う方法はありません。

2つのオプション(あなたが言及した1つ)は、パブリックgetterを使用して、フィールドをプライベートにするか、クラスの完全なドキュメントにします。

ゲッターメソッドのオーバーヘッドは非常に小さい(あるとしても)。何度も実行する場合は、getメソッドを呼び出す代わりに、フェッチした値をキャッシュすることをお勧めします。

編集:

その方法の1つは、ゲッターよりもオーバーヘッドが大きくなりますが、innerCクラスでのみ使用可能なコンストラクターでパブリック内部クラスを定義することです(Cと呼びましょう)。フィールドを公開します。そうすれば、クラスの外部でinnerCインスタンスを作成できないため、フィールドを外部から変更することはできませんが、内部から変更することはできます。ただし、外部から読むことができます。

17
Luchian Grigore

public finalフィールドを持つクラスを作成します。これらのフィールドが初期化されるコンストラクターを提供します。これにより、クラスは不変になりますが、外部から値にアクセスする際のオーバーヘッドはありません。例えば:

public class ShortCalendar
{
    public final int year, month, day;

    public ShortCalendar(Calendar calendar)
    {
        if (null == calendar)
            throw new IllegalArgumentException();

        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH);
        day = calendar.get(Calendar.DATE);
    }
}
41
Aleks N.

私が知っていることから、コンパイラはこの種のコードを最適化しない

Hotspot JITコンパイラー ほとんど間違いなく

私は最善の解決策は何だろうと思っていましたか?

最適化を時期尚早に停止します。このコードをペインティングルーチンで使用している場合、インライン化されていなくても、実際のペインティングが単純なメソッドの呼び出しよりも少なくとも100倍長くなることを保証できます。

6

外部からフィールドを「読み取り専用」にする方法はありません。唯一の-そして正しい-方法は、フィールドをプライベートにし、セッターではなくゲッターのみを提供することです。

3
Thomas Uhrig

実際、HotSpotコンパイラはほとんどの場合、ゲッターへのインライン呼び出しを行うため、オーバーヘッドは発生しません(これらのメソッドを呼び出すオーバーヘッドはほとんど測定できません)。

[〜#〜] edit [〜#〜]

すべてのCPUサイクルが本当に必要な場合は、CまたはC++を使用します(またはパフォーマンスクリティカルな部分をその中に記述し、JNA経由で呼び出します。時間を費やす価値があります)。

1
helpermethod

あなたの解決策は次のとおりです。プライベートフィールド、プライベートセッター、保護されたゲッターまたはパブリックなゲッター

0
U Mad