この記事では、Longを例として、パッケージングクラスのバッファプールの設計を見てみましょう。
1.構造
Longのバッファプール関連コード:
public final class Long extends Number implements Comparable<Long> {
// 用来保存具体long值
private final long value;
// 在构造时传入要封装的long值
public Long(long value) {
this.value = value;
}
// 注:这里需要静态成员(缓存数组:cache)所以是静态内部类
private static class LongCache {
// 私有构造函数,不能被new出来
private LongCache(){
}
// 缓存(本质是一个数组)范围从 -128 到 127,+1 是因为有个 0
static final Long cache[] = new Long[-(-128) + 127 + 1];
// 容器初始化时,进行加载
static {
// 缓存 Long 值,注意这里是 i - 128 ,所以再拿的时候就需要 + 128
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
}
1.1コア1のパッケージ化:パッケージ化
longはlong型の値をカプセル化して拡張することです
1.2コア2のパッケージ化:キャッシュ
Longはそれ自体でキャッシュメカニズムを実装し、-128から127までのすべてのLong値をキャッシュします。これがこの範囲のLong値である場合、初期化されませんが、キャッシュから取得されます;キャッシュは仮想にロードされますマシンタイム実行
ご覧のとおり、クラスのキャッシュプールを設計するという考え方:静的コンテナー+静的初期化==>静的内部クラスにカプセル化されています。次に、疑問があります。なぜ静的内部クラスの代わりに静的内部クラスを使用するのですか?または、静的内部クラスと非静的内部クラスの違い:
- 静的メンバーはありますか
- 静的内部クラスは、上記のような静的メンバー(属性、メソッド)を持つことができます
static final Long cache[]
- 非静的内部クラスは静的メンバー(属性、メソッド)を持つことができません
- 静的内部クラスは、上記のような静的メンバー(属性、メソッド)を持つことができます
- 外部クラスのメンバーにアクセスする
- 静的内部クラスは外部クラスの静的メンバーのみを参照できます
- 非静的内部クラスは、外部クラスのすべてのメンバー(属性、メソッド)にアクセスできます
- 作成方法
クラスAに静的内部クラスBと非静的内部クラスCがあるとすると、作成BとCの違いは次のとおりです。- 静的内部クラス:AB b = new AB()
- 非静的内部クラス:AC c = a.new C()
2.メソッド分析とAPI
2.1 valueOf
public static Long valueOf(long l) {
final int offset = 128;
// 先在缓冲池中取
if (l >= -128 && l <= 127) {
// 这里+offest是要计算出索引,因为cache[0]=-127
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
2.2 longValueおよびintValue
public long longValue() {
// 直接返回value
return value;
}
intValue、floatValue、doubleValueに加えて
public int intValue() {
// 直接强制类型装换
return (int)value;
}
3. 2つの質問
-
自動ボクシングと自動アンボクシング?
各基本タイプには、独自のパッケージ化クラスがあり、独自のバッファープールもあります。
長い–
作为函参(装箱)
–>長い–参加运算(拆箱)
–>長い- オートボクシングは、コンパイル時に自動的にvalueOfメソッドを呼び出します
- 自動ボックス化解除によりlongValueメソッドが呼び出されます
-
Longを使用する場合、valueOfメソッドをより多く使用し、parseLongメソッドをより少なくすることが推奨されるのはなぜですか?
Long自体には、-128から127の範囲のLongをキャッシュするキャッシュメカニズムがあるため、valueOfメソッドはキャッシュから値を取得します。キャッシュがヒットすると、リソースのオーバーヘッドが減少します。parseLongメソッドにはこのメカニズムがありません。