切换语句与非常量情况

时间:2017-11-06 02:47:34

标签: java command-line internationalization switch-statement

我正在进行这项任务,即使用命令行界面。我使用一个简单的switch语句来创建这个命令行界面的控件,但是当我添加国际化支持作为我的赋值的一部分时,由于变量需要保持不变,我的switch语句已经崩溃。我该如何解决这个问题?

public class Editor {

    private boolean running = true;

    public static ArrayList<String> command = new ArrayList<String>();

    Locale enLocale = new Locale("en", "GB");
    ResourceBundle messages = ResourceBundle.getBundle("BaseBundle", enLocale);
    String open = messages.getString("open");
    String saveas = messages.getString("saveas");
    String put = messages.getString("put");
    String rot90 = messages.getString("rot90");
    String mono = messages.getString("mono");
    String help = messages.getString("help");
    String quit = messages.getString("quit");
    String look = messages.getString("look");
    String undo = messages.getString("undo");
    private String get = messages.getString("get");

    Parser parser = new Parser();

    public Editor() {
    }

    public void run() {
        System.out.println("fotoshop");
        while (running) {
            command = parser.readInput();
            interpret(command);
        }
        System.out.println("fotoshop exiting");
    }

    public void interpret(ArrayList<String> command) {


        switch (command.get(0)) {
            case open: OpenCommand.execute();
            case saveas: SaveCommand.execute();
            case put: PutCommand.execute();
            case get: GetCommand.execute();
            case rot90: ApplyRot90.execute();
            case mono: ApplyMono.execute();
            case help: HelpCommand.execute();
            case quit: running = false;
            case look: LookCommand.execute();
            case undo;

        }
    }



}

4 个答案:

答案 0 :(得分:2)

我对Java的国际化不是很熟悉,但我认为你应该使用的一般模式是这样的:

switch

换句话说,维护某种类型的地图,它可以将您想要支持的任何语言的命令映射到命令英语语言命令。然后,重构您的String input = parser.readInput(); String command = i18Map.get(input); switch (command.get(0)) { case "open": OpenCommand.execute(); case "saveas": SaveCommand.execute(); case "put": PutCommand.execute(); case "get": GetCommand.execute(); // etc. } 语句以打开那些英语常量而不是变量:

<select class="bookly-select-mobile bookly-js-select-employee">
    <option value="">Any</option>
    <option value="1">Brandon Davis</option>
    <option value="2">Ryan Floyd</option>
</select>

答案 1 :(得分:0)

您是否看过以下技巧来实现动态切换? 这可能是一种矫枉过正,但值得一看。

您可以使用String而不是Integer来定义它,以将其映射到应用程序应支持的不同语言中的不同操作。

java-tip-3-how-to-implement-dynamic-switch

class Switcher {

    private Map<Integer, Command> caseCommands;

    private Command defaultCommand;

    private Command getCaseCommandByCaseId(Integer caseId) {
        if (caseCommands.containsKey(caseId)) {
            return caseCommands.get(caseId);
        } else {
            return defaultCommand;
        }
    }

    public Switcher() {
        caseCommands = new HashMap<Integer, Command>();

        setDefaultCaseCommand(new DoNothingCommand());
    }

    public void addCaseCommand(Integer caseId, Command caseCommand) {
        caseCommands.put(caseId, caseCommand);
    }

    public void setDefaultCaseCommand(Command defaultCommand) {
        if (defaultCommand != null) {
            this.defaultCommand = defaultCommand;
        }
    }

    public void on(Integer caseId) {
        Command command = getCaseCommandByCaseId(caseId);

        command.execute();
    }
}

您的主要课程:

public class Main {
    public static void main(String[] args) {
        Switcher switcher = new Switcher();
        switcher.addCaseCommand(1, new Command() {
            @Override
            public void execute() {
                System.out.println("Command on {id: 1}");
            }
        });
        switcher.addCaseCommand(2, new Command() {
            @Override
            public void execute() {
                System.out.println("Command on {id: 2}");
            }
        });
        switcher.addCaseCommand(3, new Command() {
            @Override
            public void execute() {
                System.out.println("Command on {id: 3}");
            }
        });
        switcher.setDefaultCaseCommand(new Command() {
            @Override
            public void execute() {
                System.out.println("Command on {default}");
            }
        });

        for (int i = 1; i <= 4; i++) {
            switcher.on(i);
        }
    }
}

//输出

Command on {id: 1}
Command on {id: 2}
Command on {id: 3}
Command on {default}

甚至更好地避免在hashmap中直接硬编码所有消息,因此在添加新语言支持时必须重新编译更改代码

  

将示例程序国际化

     

如果您查看国际化的源代码,您会注意到这一点   硬编码的英文消息已被删除。因为消息   不再是硬编码的,因为语言代码是在   运行时,可以在全球范围内分发相同的可执行文件没有   本地化需要重新编译。该计划已经   国际化。

     

您可能想知道消息文本发生了什么或者是什么   语言和国家代码的意思。别担心。你将了解到   当您逐步完成国际化过程时,这些概念   示例程序。

     

<强> 1。创建属性文件

     

属性文件存储有关a特征的信息   程序或环境。属性文件采用纯文本格式。您   可以使用几乎任何文本编辑器创建文件。

     

在示例中,属性文件存储了可翻译文本   要显示的消息。在该计划国际化之前,   这段文字的英文版本是硬编码的   System.out.println陈述。默认属性文件,即   名为MessagesBundle.properties,包含以下行:

     

greetings = Hello   farewell = Goodbye   inquiry = How are you?现在   消息在属性文件中,它们可以被翻译成   各种语言。不需要更改源代码。该   法语翻译器创建了一个名为的属性文件   MessagesBundle_fr_FR.properties,其中包含以下行:

     

greetings = Bonjour.   farewell = Au revoir.   inquiry = Comment   allez-VOUS?请注意,等号右侧的值   已翻译,但左侧的键没有   改变。这些键不能更改,因为它们将被引用   当你的程序获取翻译的文本时。

     

属性文件的名称很重要。例如,名称   MessagesBundle_fr_FR.properties文件包含fr语言代码   和FR国家代码。创建时也使用这些代码   区域设置对象。

     

<强> 2。定义区域设置

     

Locale对象标识特定语言和国家/地区。该   以下语句定义语言为英语的语言环境   而这个国家就是美国:

     

aLocale = new Locale("en","US");下一个示例创建Locale   加拿大和法国的法语对象:

     

caLocale = new Locale("fr","CA"); frLocale = new Locale("fr","FR");   该计划非常灵活。而不是使用硬编码语言和   国家/地区代码,程序在运行时从命令行获取它们   时间:

     

String language = new String(args[0]);   String country = new String(args[1]);   currentLocale = new Locale(language, country);区域设置   对象只是标识符。定义区域设置后,将其传递给   执行有用任务的其他对象,例如格式化日期和   数字。这些对象因其行为而对区域设置敏感   根据Locale的不同而不同。 ResourceBundle就是一个例子   区域设置敏感对象。

     

第3。创建ResourceBundle

     

ResourceBundle对象包含特定于语言环境的对象。你用   ResourceBundle对象用于隔离区域设置敏感数据,例如   可翻译的文本。在示例程序中,支持ResourceBundle   由包含我们想要的消息文本的属性文件   显示。

     

ResourceBundle创建如下:

     

messages = ResourceBundle.getBundle(&#34; MessagesBundle&#34;,currentLocale);   传递给getBundle方法的参数标识了哪些属性   文件将被访问。第一个参数MessagesBundle引用   这个属性文件系列:

     

MessagesBundle_en_US.properties MessagesBundle_fr_FR.properties   MessagesBundle_de_DE.properties Locale,这是第二个   getBundle的参数,指定哪个MessagesBundle文件   选择。创建区域设置时,语言代码和国家/地区   代码被传递给它的构造函数。注意语言和   国家/地区代码按照属性名称中的MessagesBundle进行操作   文件。

     

现在你所要做的就是从中获取翻译的消息   ResourceBundle中。

     

<强> 4。从ResourceBundle

获取文本      

属性文件包含键值对。价值观包括   程序将显示的翻译文本。你指定了   从ResourceBundle获取已翻译的消息时的密钥   使用getString方法。例如,要检索消息   通过问候键标识,您可以按如下方式调用getString:

     

String msg1 = messages.getString(&#34; greetings&#34;);示例程序使用   关键的问候,因为它反映了消息的内容,但是   它可能使用了另一个String,例如s1或msg1。只记得   密钥在程序中是硬编码的,它必须存在于   属性文件。如果您的翻译人员意外修改了密钥   属性文件,getString无法找到消息。

     

<强>结论

     

那就是它。如您所见,国际化程序也不是   难。它需要一些规划和一些额外的编码,但是   好处是巨大的。为您提供概述   国际化进程,本课的示例程序是   故意保持简单。当您阅读以下课程时,您将会这样做   了解更高级的国际化功能   Java编程语言。

来源官方文件:https://docs.oracle.com/javase/tutorial/i18n/intro/steps.html

答案 2 :(得分:0)

使用if else语句

示例

String com = command.get(0);
if (com.equals(open)) {
    OpenCommand.execute()
} else if (com.equals(saveas)) {
    SaveCommand.execute();
} ...

答案 3 :(得分:0)

执行此操作的一种方法是使用Map,其中键是国际化字符串,值是您要执行的命令。因此,假设所有不同的Command类(OpenCommandSaveCommand等)都有一个公共子类型Command,其中声明了execute方法,您可以像这样填补地图。

Map<String,Command> commandsByInternationalisedString = new HashMap<String,Command>();
Locale enLocale = new Locale("en", "GB");
ResourceBundle messages = ResourceBundle.getBundle("BaseBundle", enLocale);

commandsByInternationalisedString.add(messages.getString("open"), new OpenCommand());
commandsByInternationalisedString.add(messages.getString("saveas"), new SaveAsCommand());
commandsByInternationalisedString.add(messages.getString("put"), new PutCommand());

所以现在你有一个带有Command对象的地图,对应于用户可能输入的任何命令。要使用它,你可以这样做。

public void interpret(ArrayList<String> command) {

    Command toExecute = commandsByInternationalisedString.get(command.get(0));
    if (toExecute != null ) {
        toExecute.execute();
    } else {
        System.out.println("That's not a valid command");
    }
}