如何根据Java中字符串的值返回方法中的不同类型?

时间:2010-04-26 16:41:58

标签: java

我是Java的新手,我遇到了以下问题:

我创建了几个实现“Parser”接口的类。我有一个JavaParser,PythonParser,CParser,最后是一个TextParser。

我正在尝试编写一个方法,因此它将采用File或String(表示文件名)并在给定文件扩展名的情况下返回相应的解析器。

这是我基本上试图做的一些伪代码:

public Parser getParser(String filename)  
{
    String extension = filename.substring(filename.lastIndexOf("."));

    switch(extension)
    {
        case "py": return new PythonParser();
        case "java": return new JavaParser();
        case "c": return new CParser();
        default: return new TextParser();
    }
}

一般来说,这是处理这种情况的正确方法吗?另外,我应该如何处理Java不允许切换字符串的事实?我应该使用字符串的.hashcode()值吗?

我觉得有一些设计模式或处理这个问题的东西,但它让我望而却步。这是你怎么做的?

7 个答案:

答案 0 :(得分:11)

  1. 您可以一个接一个地使用多个if语句。

  2. 您可以为您的语言创建特殊的enum,并在切换语句中使用它。

  3. 您可以使用Map,其中语言是键,解析器的原型是值。

  4. 第三个选项看起来很有趣。代码如下:

    return parsers.get(extention).newInstance();
    

    这是使用枚举的第二个选项的一个有点棘手的实现:

    enum Language {
    
        JAVA {
            public Parser getParser () {
                return new JavaParser ();
            }}, 
        PYTHON {
            public Parser getParser () {
                return new PythonParser ();
            }}, 
        TEXT {
            public Parser getParser () {
                return new TextParser ();
            }};
    
        public Parser getParser () {
            return null;
        }
    
        public static Language getLanguage (String extention) {
            try {
                return valueOf (extention);
            } catch (IllegalArgumentException e) {
                return TEXT;
            }
        }
    }
    
    ...
    
    public Parser getParser(String filename) {
        String extension = filename.substring(filename.lastIndexOf("."));    
        return Language.getLanguage (extension).getParser ();
    }
    

答案 1 :(得分:8)

这称为Factory method pattern,它似乎是处理问题的一种非常好的方法。解决“Java不允许切换字符串”问题的一种方法是使用if ... else语句。

if (extension.equals("py")) {
    return new PythonParser();
}
else if(extension.equals("java")) {
    return new JavaParser();
}
else ...

答案 2 :(得分:1)

您可以使用enum来决定使用哪种语言然后使用它(也在switch语句中):

enum Type { JAVA, PYTHON, CPP, C, PERL };

Type getType(String filename)
{
  // do your if chain here
  return JAVA;
}

public Parser getParser(String filename)  
{
    switch(getType(filename))
    {
        case PYTHON: return new PythonParser();
        case JAVA: return new JavaParser();
        case C: return new CParser();
        default: return new TextParser();
    }
}

关于你的第一个问题:你的方法没问题,当你有一些东西可以构建一个接口的多种具体实现时(在你的情况下是Parser),它被称为工厂模式在运行时选择哪一个

答案 3 :(得分:1)

  

一般来说,这是正确的方法吗?   处理这种情况?

这似乎是正确的方法,因为PythonParserJavaParser等实现或是Parser

的子类
  

另外,我应该如何处理这个事实   Java不允许打开   字符串?

使用if..else if;您不必使用哈希码或任何东西。查看字符串上的equals()方法。

  

我觉得有一些设计   模式或其他东西

yes

答案 4 :(得分:1)

PythonParser,JavaParser和CParser都应该是Parser的子类,或者Parser可以是它们都实现的接口。

您可以使用if / else if。

轻松解决案例陈述的限制

请勿使用字符串的哈希码。许多字符串映射到相同的哈希码,因为extension.hashCode()==“java”.hashCode()并不一定意味着extension.equals(“java”)。这里只有3个字符串,意外碰撞的可能性很小,但只要我们幸运,“大部分时间应该工作”的程序都是坏消息。在这种情况下,程序可以完全正确地使用这个特定的字符串集合,然后一段时间后你添加CobolParser并突然它退出工作。

有人提到使用枚举。通常,使用枚举来识别事物的“类型”比使用字符串要好得多。但在这种情况下,您从文件名中提取字符串,因此您必须通过if / else if块运行它以将其转换为枚举,然后测试枚举。当你迅速创建一个特定于类型的解析器时,你不可能保存枚举或再次查看它,所以我认为你没有获得任何东西。

答案 5 :(得分:0)

在这种情况下,使用界面是正确的。您的接口应该公开方法,以便调用类不需要将自己转换为特定的解析器实现。

关于switch case,如果你使用jdk1.5或更高版本,你应该为这些字符串定义enum,你可以轻松使用swicth case。

答案 6 :(得分:0)

我会:

public Parser getParser(String filename)  {
    String extension = filename.substring(filename.lastIndexOf("."));

    if( "py".equals(extension)  ) { return new PythonParser() }
    if( "java".equals(extension)) { return new JavaParser();  }
    if( "c".equals(extension)   ) { return new CParser();     }

    return new TextParser();
}

关于标题中的问题

  

如何根据Java中字符串的值返回方法中的不同类型?

你不能只返回一种类型。你可以做的是返回那种类型的子类型,所以如果你的解析器是子类或实现Parser类/接口,上面的代码将完美地工作。

即。

public interface Parser {
    //parser methods  
    ...
}
class PythonParser implements Parser {
     // parser implementation
     ...
}
class JavaParser implements Parser {
     // parser implementation
     ...
}
class CParser implements Parser {
     // parser implementation
     ...
}