6

ユーザー設定のストアを作成していますが、ユーザーが値を設定できる設定の数は決まっています。プリファレンス (設定) の名前は Enum として保存されます。

public enum UserSettingName {

    FOO,
    BAR,
    ETC

}

私ができるようにしたいのは、サービスが正しいJavaタイプでユーザーの値を保存できるように、値のタイプを名前で保存することです。たとえば、FOO は でありLong、BAR は である可能性がありStringます。これまでは、すべての値をStrings として格納し、その値を適切な Java 型に手動でキャストしていました。これにより、サービス内に try/catch を 1 つだけ持つ方が理にかなっている場合でも、あらゆる場所で try/catch ブロックが発生します。列挙型はジェネリック型を持つことができないことを理解しているので、次のことをいじっています。

public enum UserSettingName {

    FOO(Long.class),
    BAR(String.class),
    ETC(Baz.class)

    private Class type;

    private UserSettingName(Class type) {
        this.type = type;
    }

    public Class getType() {
        return this.type;
    }
}

私は、正しい型で値を返し、設定するメソッドを持つ汎用 UserSetting オブジェクトを持っていpublic T getSettingValue() ます。私の問題は、次のようなことができないため、設定を作成または取得するときにpublic void setSettingValue(T value)そのジェネリック型を指定しようとすることにあります。T

new UserSetting<UserSettingName.FOO.getType()>(UserSettingName.FOO, 123L)

これが明確でない場合は申し訳ありませんが、理解できない場合は明確にすることができます。

ありがとう!

アップデート

設定の名前と値の両方が、Spring MVC REST 呼び出しから取得されます。

public ResponseEntity<String> save(@PathVariable Long userId, @PathVariable UserSettingName settingName, @RequestBody String settingValue)

Spring は受信データを自動的にキャストするため、Enum を使用しました。

4

3 に答える 3

3

まず一歩下がって、何を達成しようとしているのかを考え、それを達成するために標準パターンまたは言語構造を使用する必要があります。

ここで何をしようとしているのかは完全には明らかではありませんが、あなたのアプローチからは、Java ではるかに簡単な方法で実行できる何かを再発明しているようにほぼ確実に見えます。たとえば、オブジェクトのランタイム クラスを知り、操作する必要がある場合は、リフレクション API の使用を検討してください。

より実用的なレベルでは、ここでやろうとしていることはジェネリックでは不可能です。ジェネリックはコンパイル時の言語機能です。ジェネリックは、オブジェクトからすべてを明示的にキャストすることを回避し、コンパイル時に型チェックを行うのに役立ちます。このようにジェネリックを使用することはできません。つまり、実行時にのみ認識されるT値として設定します。UserSettingName.Foo.getType()

于 2013-10-14T22:12:46.253 に答える
2

netty がどのように実行したかを見てください。

http://netty.io/wiki/new-and-noteworthy.html#type-safe-channeloption

彼らは型付き定数を使用してそれを行いました:

http://grepcode.com/file/repo1.maven.org/maven2/io.netty/netty-all/4.0.0.Beta1/io/netty/channel/ChannelOption.java#ChannelOption

編集:

public interface ChannelConfig {
   ...
   <T> boolean setOption(ChannelOption<T> option, T value);
   ...
}

public class ChannelOption<T> ...
    public static final ChannelOption<Integer> SO_TIMEOUT =
        new ChannelOption<Integer>("SO_TIMEOUT");
    ...
}

EDIT2:次のように変換できます:

class Baz {}

class UserSettingName<T> {
    public static final UserSettingName<Baz> ETC = new UserSettingName<Baz>();
}

class UserSetting {
    public <T> UserSetting(UserSettingName<T> name, T param) {

    }
}

public class Test {
    public static void main(String[] args) {
        new UserSetting(UserSettingName.ETC, new Baz());
    }
}
于 2013-10-14T22:02:46.637 に答える
0

列挙型はここでの答えではありません。どこでもコードを繰り返していることに気付いた場合は、ユーティリティ クラスを作成し、そこにすべての try/catch ロジックをカプセル化することができます。これにより、現在のコードに大きな影響を与えることなく、コードの冗長性を削減できます。

public class Util
{
    public static MyObject getObjectFromString(String s)
    {
        try
        {
            return (MyObject)s;
        }
        catch(Exception e)
        {
            return null;
        }
    }
}

次に、次のように使用します。

MyObject myObj = Util.getObjectFromString(string);
于 2013-10-14T22:29:16.803 に答える