0

特定のプロパティに対して、他に類を見ないオブジェクトを作成したいと思います。

import java.util.HashMap;

public class SourceLanguage {
    private  final String name;
    private static HashMap<String,SourceLanguage> existing;

    private SourceLanguage(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public static SourceLanguage get(String name){
        if(existing==null){
            existing = new HashMap<>();
            SourceLanguage sl = new SourceLanguage(name);
            existing.put(name.toLowerCase(),sl);
            return sl;
        }
        SourceLanguage check = existing.get(name);
        if(check==null){
            SourceLanguage sl = new SourceLanguage(name);
            existing.put(name.toLowerCase(),sl);
            return sl;
        }else {
            return check;
        }
    }
}

このクラスのオブジェクトを別のマップのキーとして使用したいと思います。

ちょっとやり過ぎだと思います。目標を達成するためのより簡単な方法はありますか?

4

4 に答える 4

2

レジストリパターンの使用を検討できます。そうすれば、SourceLanguageオブジェクトの動作を、その一意性を強制する動作から分離することができます。また、互いに独立してより複雑になる可能性があります。SourceLanguageレジストリは、クラスを乱雑にすることなく、コメントで説明されているメモリリークに対処できます。

SourceLanguageとRegistryクラスの両方を同じパッケージに入れますが、SourceLanguageクラスをパッケージに表示可能にします(またはprotectedコンストラクターを指定します)。そうすると、外部コンポーネントは直接インスタンス化できなくなりSourceLanguage、レジストリを通過する必要があります。

于 2012-11-15T22:13:48.553 に答える
2

キャッシュの強い参照を避けることを強くお勧めします。これがスレッドセーフになる場合は、同期も必要です。

public class SourceLanguage {
    private final String name;
    private final static Map<String, SoftReference<SourceLanguage>> cache
        = new HashMap<String, SoftReference<SourceLanguage>>();

    private SourceLanguage(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public static SourceLanguage get(String name){
        final String key = name.toLowerCase();
        SourceLanguage lang = null;
        synchronized (cache) {
            SoftReference<SourceLanguage> ref = cache.get(key);
            if (ref != null) {
                lang = ref.get();
            }
            if (lang == null) {
                SourceLanguage sl = new SourceLanguage(name);
                cache.put(key, new SoftReference<SourceLanguage>(sl);
            }
        }
        return lang;
    }
}
于 2012-11-15T22:27:58.703 に答える
1

私が何かを見逃していなければ、あなたならできると思います。

public class SourceLanguage {
    private  final String name;
    private static HashMap<String,SourceLanguage> existing = new HashMap<String, SourceLanguage>();

    private SourceLanguage(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public static SourceLanguage get(String name){
        SourceLanguage ret = existing.get(name.toLowerCase());
        if(ret == null) {
            ret = new SourceLanguage(name);
            existing.put(name.toLowerCase(),ret);
        }
        return ret;
    }
}
于 2012-11-15T22:15:48.500 に答える
0

あなたが試みていることは、インターンの一般的な概念の下にあります。一般に、メモリリークが発生しやすいですが、言語がそれほど多くないため、あなたの場合は問題になるとは思いません.

これをスレッドセーフにするための私のアドバイスは、次のものを使用することConcurrentHashMapです。

private static final ConcurrentMap<String, SourceLanguage> existing = 
  new ConcurrentHashMap<>();

public static SourceLanguage get(String name) {
  name = name.toLowerCase();
  final SourceLanguage old = existing.get(name);
  if (old != null) return old;
  final SourceLanguage 
    created = new SourceLanguage(name),
    justPut = existing.putIfAbsent(name, created);
  return justPut != null? justPut : created;
}
于 2012-11-15T22:29:16.307 に答える