How should I return different types in a method based on string value in Java?

I am new to Java and I had the following problem:

I created several classes that all implement the Parser interface. I have JavaParser, PythonParser, CParser and finally TextParser.

I am trying to write a method, so it will take either a file or a string (representing the file name) and will return the appropriate parser based on the file extension.

Here is the psuedo code of what I'm basically trying to do:

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(); } } 

In general, is this the right way to handle this situation? Also, how should I handle the fact that Java doesn't allow strings to be included? Should I use the .hashcode () value of strings?

I feel like there is some kind of design template or something for this, but it eludes me. So will you do it?

+6
java
source share
7 answers

This is called the Factory Method Template , and it seems like a pretty good way to handle your problem. One way you can get around the "Java does not allow the inclusion of strings" problem is to use the if ... else .

 if (extension.equals("py")) { return new PythonParser(); } else if(extension.equals("java")) { return new JavaParser(); } else ... 
+8
source share
  • You can simply use several if one after another.

  • You can create a special enum for your languages ​​and use it in your switch statement.

  • You can use Map , where languages ​​are keys and prototypes of parsers are values.

The third option looks interesting, as for me. The code will look like this:

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

And here is a small complicated implementation of the second option with the enumeration:

 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 (); } 
+11
source share

you can use enum to decide which language you are dealing with and then use it (also in switch statements):

 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(); } } 

Regarding your first question: your approach is fine, it is called a factory pattern , when you have something that creates many kinds of specific implementations of the interface (in your case Parser ) whose choice at runtime

+1
source share

In general, is this the right way to deal with this situation?

This seems to be the right way, given that PythonParser , JavaParser , etc. implement or subclass Parser

Also, how should I deal with the fact that Java doesn't allow strings to be included?

Use if..else if; You do not need to use hash codes or anything else. Check the equals() method on the lines.

I feel like there is some kind of design pattern or something

yes

+1
source share

PythonParser, JavaParser, and CParser must be subclasses of Parser, or Parser may be the interface that they all implement.

You can easily get around the limitation of case statements by using if / else if.

DO NOT use the hash of the string. Many, many lines are mapped to the same hash code, therefore simply because extension.hashCode () == "java" .hashCode () does not necessarily mean extension.equals ("java"). There are only 3 lines here, the probability of an accidental collision is small, but programs that "should work most of the time while we're lucky" are bad news. In this case, the program can work absolutely correctly with this particular set of lines, and then after a while you add CobolParser and suddenly stop working.

Someone mentioned using enumerations. In general, it is much better to use enumerations to identify the "types" of things than to use strings. But in this case, you extract the string from the file name, so you need to run it through the if / else if block to convert it to an enumeration, and then check the enumeration. Since you quickly create a type-dependent parser, you are unlikely to save the enum or someday look at it again, so I don’t think you won anything.

+1
source share

In this case, the use of the interface is correct. Your interface should expose the methods in such a way that the calling classes do not need to bring themselves into a concrete parser implementation.

As for the switch case, if you use jdk1.5 or higher, you should define an enumeration for these lines, and you can easily use the swicth case.

0
source share

I'd:

 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(); } 

About the question in your title

How do I return different types in a method based on a string value in Java?

You cannot return only one type. What you can do is return subtypes of this type, so if your parsers are subclasses or implement the Parser class / interface, the code above will work fine.

t

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

All Articles