文字列の不変性、長いキャッシュのソースコード分析、インタビューの質問

文字列の不変性、長いキャッシュのソースコード分析、インタビューの質問

誰もがStringとLongに精通しています。次に、StringとLongの基礎となるソースコードの実装を実際の作業シナリオと組み合わせて見てみましょう。それらを使用するときに注意が必要な点があるかどうかを確認し、これらのAPIが何に適用できるかを要約します。シーン。

1つ:文字列

1.1。不変性

このようなインタビューの質問をよく目にします。String、StringBuilder、StringBufferの違いについて簡単に説明してください。その中で、Stringは他の2つとは異なり、String値が初期化されると変更できず、変更されると新しいクラスになります。次のコードを見てみましょう。最後に「ssssss」が出力されますが、Stringの値が変更されているようです。

String str = "aaa";
str = "ssssss";
System.out.println(str);

実際、文字列の値が変更されていないことは、Debugを通じて直感的に確認できます。
文字列の不変性
文字列の不変性
最初、strが指すメモリアドレスは527であり、割り当てのラウンドの後、strが指すメモリアドレスは529になります。言い換えると、一見単純に見えるstr = "ssssss"の割り当ては、実際にはstrの参照を新しい文字列にポイントします。

次に、Stringのソースコードから理由を確認します。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
    
    /** The value is used for character storage. */
    private final char value[];
}    

Stringのソースコードから次のことがわかります。

  1. Stringはfinalによって変更されます。これは、Stringクラスが継承されないことを示します。つまり、Stringの操作メソッドが継承によって上書きされることはありません
  2. Stringに格納されているデータはchar配列値です。値もfinalによって変更されることがわかりました。つまり、値が割り当てられると、メモリアドレスを変更することは絶対に不可能であり、値のアクセス許可はプライベートであり、外部からは絶対にアクセスできず、Stringは値の割り当てを開始していません。メソッドなので、値が生成されると、メモリアドレスはまったく変更できません

上記の2つの点が、Stringの不変性の理由であり、finalキーワードの特性を最大限に活用しています。クラスをカスタマイズするときに不変にしたい場合は、Stringのこれら2つの操作を模倣することもできます。

1.2、平等判断

等式を判断するには、equalsとequalsIgnoreCaseの2つの方法があります。後者が等しいと判断された場合、ケースは無視されます.2つの文字列の同等性を判断するロジックを作成するように求められた場合は、その作成方法を、equalsのソースコードを見てみましょう。

public boolean equals(Object anObject) {
    
    
    // 判断内存地址是否相同
    if (this == anObject) {
    
    
        return true;
    }
    // 待比较的对象是否是 String,如果不是 String,直接返回不相等
    if (anObject instanceof String) {
    
    
        String anotherString = (String)anObject;
        int n = value.length;
        // 两个字符串的长度是否相等,不等则直接返回不相等
        if (n == anotherString.value.length) {
    
    
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // 依次比较每个字符是否相等,若有一个不等,直接返回不相等
            while (n-- != 0) {
    
    
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

equalsのソースコードからわかるように、ロジックは非常に明確であり、同等のコードはStringの基礎となる構造に完全に基づいて記述されています。これはまた、考え方を提供します。誰かが2つが等しいかどうかを判断する方法を尋ねられた場合、2つの基本的な構造から始めることができるので、基本的な文字列と同じように、実用的なアイデアと方法をすばやく考えることができます。データ構造はchar配列と同じです。等しいかどうかを判断するときは、char配列の文字を1つずつ比較して、等しいかどうかを確認してください。

2:長い

2.1、キャッシュ

Longのキャッシングの問題が最も懸念されています。Longは、-128から127までのすべてのLong値をキャッシュするキャッシングメカニズムを実装しています。この範囲のLong値の場合、初期化されませんが、キャッシュから取得します。キャッシュ初期化のソースコードは次のとおりです。

private static class LongCache {
    
    
    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);
    }
}

3:インタビューの質問

3.1。Longを使用するときに、valueOfメソッドを多く使用し、parseLongメソッドを少なくすることが推奨されるのはなぜですか。

Long自体には-128〜127の範囲のLongをキャッシュするキャッシュメカニズムがあるため、valueOfメソッドはキャッシュから値を取得します。キャッシュがヒットすると、リソースのオーバーヘッドが削減されます。parseLongメソッドにはこのメカニズムがありません。

3.2。なぜ、Stringは不変であると誰もが言うのですか?

Stringとデータを保持するchar配列の両方がfinalキーワードによって変更された場合、それらは不変です。詳細については、上記を参照してください。

3:まとめ

ストリングとロングは私たちの仕事で頻繁に使用されます。インタビューの過程で、審査官は私たちの習熟度をチェックするためにいくつかの実用的な質問をすることも好きです。

おすすめ

転載: blog.csdn.net/weixin_38478780/article/details/107762049