Call void on possible null object, in one line - java

I use Java8 in my project but i cannot solve this issue with a nice implementation.
UIInput textInput = ...;
if (textInput != null)
{
textInput.setValid(false);
}
Is there a solution to check if the object is null, and if not, then call the function on it, in one line ?!

Don't.
What you have is easily readable for anyone with some Java knowledge. Any one-liner misusing a construct intended for something else will take most people way more time to read and understand than this will. And likely some people will misread it and have to read it again later when it does not behave like they expect during a debugging session.
Brevity / Number of lines of code is not an ultimate measure for readability or quality.
What you can do, if this is at the wrong level of detail compared with the rest of your method, is abstract it away with a single speaking method call. Say, create a method 'ensureTextInputIsSet' that just contains this code and returns the potentially modified object.

Optional.ofNullable(textInput).ifPresent(x -> x.setValid(false));
But this is not what Optional was designed for...

If a variable may be null, an object is optional, then:
Optional<UIInput> textInput = ...;
With a circumstantial, but always safe usage:
textInput.ifPresent(ti -> ti.setValid(false));
And nice chaining, for instance for Optional<UIInput> to Optional<String> calling a method on the UIInput.
String s = textInput.map(UIInput::getText).orElse("");

Related

which one to choose between calling a function twice and storing the return value in a variable?

I have the following scenario.. and I come across the similar scenario many a times. Which is more preferable of the following two options?
Option-1:
String result = ( getDetails(...) == null ) ? "" : getDetails(...);
Option-2:
String returnValue = getDetails(...);
String result = ( returnValue == null ) ? "" : returnValue;
Which is more preferable and/or a good practice.?
Imho The second one is better because it's avoiding calling getDetails(...) method twice.
If you have to do that check for every call of getDetails then the best way would be getDetails method to return "" in cases when you return null.
Also calling the same method twice (which is probably idempotent in your case) is not a good practice even if it is very simple.
Please read this java-how-expensive-is-a-method-call. Main idea is don't do premature optimization, but you should get used to these simple cases when you can write better code
Option-2: is better
Option-1: Results in extra method call and such cases should always be avoided unless getDetails(...) is a getter method (a one liner method which returns something)
If you dig down to micro optimization, a method call generally results in
allocation of stack for the method variables
jumping the instruction set
which are couple of many overheads. As many say, such performance optimization should be left to Compiler and the code should be written to be more readable.
I'd prefer the second option because it is more readable, especially when using the ternary operator.
If it is a problem or not to call getDetails(...) twice depends on your method. If it is a simple getter, the JVM might optimize the call and directly use the value so storing it in a local variable does not make a difference.
If it is a more complex method, e.g. a query to the database, I would definitely store the result in a local variable.
Generally speaking: Care about code readability first! If you find performance problems later on, try optimizing then.
option-2 will be always optimized one what ever you wrote in the calling function.
Even if you are writing any in-build function or expression two times it will take fraction of section more than option-2.

Why can I use .equalsIgnoreCase("anoterString") without assigning it to a variable or within a control flow statement?

I came across this code:
for (final String s : myList)
{
s.equalsIgnoreCase(test);
updateNeeded = true;
break;
}
I suspect that this is not what the programmer actually wanted to do. I believe he meant to write something like:
for (final String s : myList)
{
if(s.equalsIgnoreCase(test))
{
updateNeeded = true;
break;
}
}
However, I don't understand why there is no error in the first code snippet.
s.equalsIgnoreCase(test);
since the method .equalsIgnoreCase("anoterString") returns a boolean and it is not being assigned to anything or used within a control flow statement
It's just a method call. You don't have to use the result of a method call for anything else.
It's rarely a good idea to ignore the result of a non-void method (in particular, the return value of InputStream.read is sometimes ignored when it really shouldn't be) but the language specification makes no attempt to call this out as a problem.
It should probably meant to be as you think. You can call a method and not assigning its result, as sometimes you just don't need the result.
You are right, this is probably an error. However, Java compiler has no way of knowing that equalsIgnoreCase method is a "pure function", i.e. produces no side effects and is otherwise meaningless unless you keep its return value.
Most programming languages allow you to ignore the returned code of a method.
There are times that you would not care about the returned value and in these cases you should be allowed to.

What is the point of the class Option[T]?

I am not able to understand the point of Option[T] class in Scala. I mean, I am not able to see any advanages of None over null.
For example, consider the code:
object Main{
class Person(name: String, var age: int){
def display = println(name+" "+age)
}
def getPerson1: Person = {
// returns a Person instance or null
}
def getPerson2: Option[Person] = {
// returns either Some[Person] or None
}
def main(argv: Array[String]): Unit = {
val p = getPerson1
if (p!=null) p.display
getPerson2 match{
case Some(person) => person.display
case None => /* Do nothing */
}
}
}
Now suppose, the method getPerson1 returns null, then the call made to display on first line of main is bound to fail with NPE. Similarly if getPerson2 returns None, the display call will again fail with some similar error.
If so, then why does Scala complicate things by introducing a new value wrapper (Option[T]) instead of following a simple approach used in Java?
UPDATE:
I have edited my code as per #Mitch's suggestion. I am still not able to see any particular advantage of Option[T]. I have to test for the exceptional null or None in both cases. :(
If I have understood correctly from #Michael's reply, is the only advantage of Option[T] is that it explicitly tells the programmer that this method could return None? Is this the only reason behind this design choice?
You'll get the point of Option better if you force yourself to never, ever, use get. That's because get is the equivalent of "ok, send me back to null-land".
So, take that example of yours. How would you call display without using get? Here are some alternatives:
getPerson2 foreach (_.display)
for (person <- getPerson2) person.display
getPerson2 match {
case Some(person) => person.display
case _ =>
}
getPerson2.getOrElse(Person("Unknown", 0)).display
None of this alternatives will let you call display on something that does not exist.
As for why get exists, Scala doesn't tell you how your code should be written. It may gently prod you, but if you want to fall back to no safety net, it's your choice.
You nailed it here:
is the only advantage of Option[T] is
that it explicitly tells the
programmer that this method could
return None?
Except for the "only". But let me restate that in another way: the main advantage of Option[T] over T is type safety. It ensures you won't be sending a T method to an object that may not exist, as the compiler won't let you.
You said you have to test for nullability in both cases, but if you forget -- or don't know -- you have to check for null, will the compiler tell you? Or will your users?
Of course, because of its interoperability with Java, Scala allows nulls just as Java does. So if you use Java libraries, if you use badly written Scala libraries, or if you use badly written personal Scala libraries, you'll still have to deal with null pointers.
Other two important advantages of Option I can think of are:
Documentation: a method type signature will tell you whether an object is always returned or not.
Monadic composability.
The latter one takes much longer to fully appreciate, and it's not well suited to simple examples, as it only shows its strength on complex code. So, I'll give an example below, but I'm well aware it will hardly mean anything except for the people who get it already.
for {
person <- getUsers
email <- person.getEmail // Assuming getEmail returns Option[String]
} yield (person, email)
Compare:
val p = getPerson1 // a potentially null Person
val favouriteColour = if (p == null) p.favouriteColour else null
with:
val p = getPerson2 // an Option[Person]
val favouriteColour = p.map(_.favouriteColour)
The monadic property bind, which appears in Scala as the map function, allows us to chain operations on objects without worrying about whether they are 'null' or not.
Take this simple example a little further. Say we wanted to find all the favourite colours of a list of people.
// list of (potentially null) Persons
for (person <- listOfPeople) yield if (person == null) null else person.favouriteColour
// list of Options[Person]
listOfPeople.map(_.map(_.favouriteColour))
listOfPeople.flatMap(_.map(_.favouriteColour)) // discards all None's
Or perhaps we would like to find the name of a person's father's mother's sister:
// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister
// with options
val fathersMothersSister = getPerson2.flatMap(_.father).flatMap(_.mother).flatMap(_.sister)
I hope this sheds some light on how options can make life a little easier.
The difference is subtle. Keep in mind to be truly a function it must return a value - null is not really considered to be a "normal return value" in that sense, more a bottom type/nothing.
But, in a practical sense, when you call a function that optionally returns something, you would do:
getPerson2 match {
case Some(person) => //handle a person
case None => //handle nothing
}
Granted, you can do something similar with null - but this makes the semantics of calling getPerson2 obvious by virtue of the fact it returns Option[Person] (a nice practical thing, other than relying on someone reading the doc and getting an NPE because they don't read the doc).
I will try and dig up a functional programmer who can give a stricter answer than I can.
For me options are really interesting when handled with for comprehension syntax. Taking synesso preceding example:
// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister
// with options
val fathersMothersSister = for {
father <- person.father
mother <- father.mother
sister <- mother.sister
} yield sister
If any of the assignation are None, the fathersMothersSister will be None but no NullPointerException will be raised. You can then safely pass fathersMothersSisterto a function taking Option parameters without worrying. so you don't check for null and you don't care of exceptions. Compare this to the java version presented in synesso example.
You have pretty powerful composition capabilities with Option:
def getURL : Option[URL]
def getDefaultURL : Option[URL]
val (host,port) = (getURL orElse getDefaultURL).map( url => (url.getHost,url.getPort) ).getOrElse( throw new IllegalStateException("No URL defined") )
Maybe someone else pointed this out, but I didn't see it:
One advantage of pattern-matching with Option[T] vs. null checking is that Option is a sealed class, so the Scala compiler will issue a warning if you neglect to code either the Some or the None case. There is a compiler flag to the compiler that will turn warnings into errors. So it's possible to prevent the failure to handle the "doesn't exist" case at compile time rather than at runtime. This is an enormous advantage over the use of the null value.
It's not there to help avoid a null check, it's there to force a null check. The point becomes clear when your class has 10 fields, two of which could be null. And your system has 50 other similar classes. In the Java world, you try to prevent NPEs on those fields using some combination of mental horesepower, naming convention, or maybe even annotations. And every Java dev fails at this to a significant degree. The Option class not only makes "nullable" values visually clear to any developers trying to understand the code, but allows the compiler to enforce this previously unspoken contract.
[ copied from this comment by Daniel Spiewak ]
If the only way to use Option were
to pattern match in order to get
values out, then yes, I agree that it
doesn’t improve at all over null.
However, you’re missing a *huge* class
of its functionality. The only
compelling reason to use Option is
if you’re using its higher-order
utility functions. Effectively, you
need to be using its monadic nature.
For example (assuming a certain amount
of API trimming):
val row: Option[Row] = database fetchRowById 42
val key: Option[String] = row flatMap { _ get “port_key” }
val value: Option[MyType] = key flatMap (myMap get)
val result: MyType = value getOrElse defaultValue
There, wasn’t that nifty? We can
actually do a lot better if we use
for-comprehensions:
val value = for {
row <- database fetchRowById 42
key <- row get "port_key"
value <- myMap get key
} yield value
val result = value getOrElse defaultValue
You’ll notice that we are *never*
checking explicitly for null, None or
any of its ilk. The whole point of
Option is to avoid any of that
checking. You just string computations
along and move down the line until you
*really* need to get a value out. At
that point, you can decide whether or
not you want to do explicit checking
(which you should never have to do),
provide a default value, throw an
exception, etc.
I never, ever do any explicit matching
against Option, and I know a lot of
other Scala developers who are in the
same boat. David Pollak mentioned to
me just the other day that he uses
such explicit matching on Option (or
Box, in the case of Lift) as a sign
that the developer who wrote the code
doesn’t fully understand the language
and its standard library.
I don’t mean to be a troll hammer, but
you really need to look at how
language features are *actually* used
in practice before you bash them as
useless. I absolutely agree that
Option is quite uncompelling as *you*
used it, but you’re not using it the
way it was designed.
One point that nobody else here seems to have raised is that while you can have a null reference, there is a distinction introduced by Option.
That is you can have Option[Option[A]], which would be inhabited by None, Some(None) and Some(Some(a)) where a is one of the usual inhabitants of A. This means that if you have some kind of container, and want to be able to store null pointers in it, and get them out, you need to pass back some extra boolean value to know if you actually got a value out. Warts like this abound in the java containers APIs and some lock-free variants can't even provide them.
null is a one-off construction, it doesn't compose with itself, it is only available for reference types, and it forces you to reason in a non-total fashion.
For instance, when you check
if (x == null) ...
else x.foo()
you have to carry around in your head throughout the else branch that x != null and that this has already been checked. However, when using something like option
x match {
case None => ...
case Some(y) => y.foo
}
you know y is not Noneby construction -- and you'd know it wasn't null either, if it weren't for Hoare's billion dollar mistake.
Option[T] is a monad, which is really useful when you using high-order functions to manipulate values.
I'll suggest you read articles listed below, they are really good articles that show you why Option[T] is useful and how can it be used in functional way.
Martians vs Monads: Null Considered Harmful
Monads are Elephants Part 1
Adding on to Randall's teaser of an answer, understanding why the potential absence of a value is represented by Option requires understanding what Option shares with many other types in Scala—specifically, types modeling monads. If one represents the absence of a value with null, that absence-presence distinction can't participate in the contracts shared by the other monadic types.
If you don't know what monads are, or if you don't notice how they're represented in Scala's library, you won't see what Option plays along with, and you can't see what you're missing out on. There are many benefits to using Option instead of null that would be noteworthy even in the absence of any monad concept (I discuss some of them in the "Cost of Option / Some vs null" scala-user mailing list thread here), but talking about it isolation is kind of like talking about a particular linked list implementation's iterator type, wondering why it's necessary, all the while missing out on the more general container/iterator/algorithm interface. There's a broader interface at work here too, and Option provides a presence-and-absence model of that interface.
I think the key is found in Synesso's answer: Option is not primarily useful as a cumbersome alias for null, but as a full-fledged object that can then help you out with your logic.
The problem with null is that it is the lack of an object. It has no methods that might help you deal with it (though as a language designer you can add increasingly long lists of features to your language that emulate an object if you really feel like it).
One thing Option can do, as you've demonstrated, is to emulate null; you then have to test for the extraordinary value "None" instead of the extraordinary value "null". If you forget, in either case, bad things will happen. Option does make it less likely to happen by accident, since you have to type "get" (which should remind you that it might be null, er, I mean None), but this is a small benefit in exchange for an extra wrapper object.
Where Option really starts to show its power is helping you deal with the concept of I-wanted-something-but-I-don't-actually-have-one.
Let's consider some things you might want to do with things that might be null.
Maybe you want to set a default value if you have a null. Let's compare Java and Scala:
String s = (input==null) ? "(undefined)" : input;
val s = input getOrElse "(undefined)"
In place of a somewhat cumbersome ?: construct we have a method that deals with the idea of "use a default value if I'm null". This cleans up your code a little bit.
Maybe you want to create a new object only if you have a real value. Compare:
File f = (filename==null) ? null : new File(filename);
val f = filename map (new File(_))
Scala is slightly shorter and again avoids sources of error. Then consider the cumulative benefit when you need to chain things together as shown in the examples by Synesso, Daniel, and paradigmatic.
It isn't a vast improvement, but if you add everything up, it's well worth it everywhere save very high-performance code (where you want to avoid even the tiny overhead of creating the Some(x) wrapper object).
The match usage isn't really that helpful on its own except as a device to alert you about the null/None case. When it is really helpful is when you start chaining it, e.g., if you have a list of options:
val a = List(Some("Hi"),None,Some("Bye"));
a match {
case List(Some(x),_*) => println("We started with " + x)
case _ => println("Nothing to start with.")
}
Now you get to fold the None cases and the List-is-empty cases all together in one handy statement that pulls out exactly the value you want.
Null return values are only present for compatibility with Java. You should not use them otherwise.
It is really a programming style question. Using Functional Java, or by writing your own helper methods, you could have your Option functionality but not abandon the Java language:
http://functionaljava.org/examples/#Option.bind
Just because Scala includes it by default doesn't make it special. Most aspects of functional languages are available in that library and it can coexist nicely with other Java code. Just as you can choose to program Scala with nulls you can choose to program Java without them.
Admitting in advance that it is a glib answer, Option is a monad.
Actually I share the doubt with you. About Option it really bothers me that 1) there is a performance overhead, as there is a lor of "Some" wrappers created everywehre. 2) I have to use a lot of Some and Option in my code.
So to see advantages and disadvantages of this language design decision we should take into consideration alternatives. As Java just ignores the problem of nullability, it's not an alternative. The actual alternative provides Fantom programming language. There are nullable and non-nullable types there and ?. ?: operators instead of Scala's map/flatMap/getOrElse. I see the following bullets in the comparison:
Option's advantage:
simpler language - no additional language constructs required
uniform with other monadic types
Nullable's advantage:
shorter syntax in typical cases
better performance (as you don't need to create new Option objects and lambdas for map, flatMap)
So there is no obvious winner here. And one more note. There is no principal syntactic advantage for using Option. You can define something like:
def nullableMap[T](value: T, f: T => T) = if (value == null) null else f(value)
Or use some implicit conversions to get pritty syntax with dots.
The real advantage of having explicit option types is that you are able to not use them in 98% of all places, and thus statically preclude null exceptions. (And in the other 2% the type system reminds you to check properly when you actually access them.)
Another situation where Option works, is in situations where types are not able to have a null value. It is not possible to store null in an Int, Float, Double, etc. value, but with an Option you can use the None.
In Java, you would need to use the boxed versions (Integer, ...) of those types.

Null pointers everywhere because data is suddenly sparse

Someone designed code that relied on full data; the XML always had every element. The data source is now sending sparse XML; if it would have been empty before, it's missing now. So, it's time to refactor while fixing bugs.
There's 100+ lines of code like this:
functionDoSomething(foo, bar, getRoot().getChild("1").getChild("A").
getChild("oo").getContent());
Except now, getChild("A") might return null. Or any of the getChild(xxx) methods might.
As one additional twist, instead of getChild(), there are actually four separate methods, which can only occur in certain orders. Someone suggested a varargs call, which isn't a bad idea, but won't work as cleanly as I might like.
What's the quickest way to clean this one up? The best? "try/catch" around every line was suggested, but man, that's ugly. Breaking out the third argument to the above method into it's own function could work... but that would entail 100+ new methods, which feels ugly, albeit less so.
The number of getChild(xxx) calls is somewhere between six and ten per line, with no fixed depth. There's also no possible way to get a correct DTD for this; things will be added later without a prior heads up, and where I'd prefer a warning in the logs when that happens, extra lines in the XML need to be handled gracefully.
Ideas?
getChild() is a convenience method, actually. The cleanest way I have in mind is to have the convenience methods return a valid Child object, but have that "empty" Child's getContent() always return "".
Please consider using XPATH instead of this mess.
What you described (returning a special child object) is a form of the NullObject pattern, which is probably the best solution here.
The solution is to use a DTD file for XML. It validates your XML file so getChild("A") won't return null when A is mandatory.
How about:
private Content getChildContent(Node root, String... path) {
Node target = root;
for ( String pathElement : path ) {
Node child = target.getChild(pathElement);
if ( child == null )
return null; // or whatever you should do
target = child;
}
return target.getContent();
}
to be used as
functionDoSomething(foo, bar, getChildContent(root, "1", "A", "oo"));
Your problem could be a design problem: Law of Demeter.
If not you can use something like an Option type changing the return type of getChild to Option<Node>:
for(Node r : getRoot())
for(Node c1 : r.getChild("1"))
for(Node c2: c1.getChild("A"))
return c2.getChild("oo")
This works because Option implements Iterable it will abort when a return value is not defined. This is similary to Scala where it can be expressed in a single for expression.
One additional advantage is that you can define interfaces that will never return a null value. With an Option type you can state in the interface definition that the return value may be undefined and the client can decide how to handle this.
If it always drills down to roughly the same same level, you can probably refactor the code using Eclipse, for example, and it'll automatically change every line that looks the same.
That way you can modify the method to be smarter, rather than modifying each line individually

How do I turn a conditional chain into faster less ugly code?

I have 9 different grammars. One of these will be loaded depending on what the first line of txt is on the file it is parsing.
I was thinking about deriving the lexer/parser spawning into sep. classes and then instantiating them as soon as I get a match -- not sure whether that would slow me down or not though. I guess some benchmarking is in order.
Really, speed is definitely my goal here but I know this is ugly code.
Right now the code looks something like this:
sin.mark(0)
site = findsite(txt)
sin.reset()
if ( site == "site1") {
loadlexer1;
loadparser1;
} else if (site == "site2") {
loadlexer2;
loadparser2;
}
.................
} else if (site == "site8") {
loadparser8;
loadparser8;
}
findsite(txt) {
...................
if line.indexOf("site1-identifier") {
site = site1;
} else if(line.indexOf("site2-identifier") {
site = site2;
} else if(line.indexOf("site3-identifier") {
site = site3;
}
.........................
} else if(line.indexOf("site8-identifier") {
site = site8;
}
}
some clarifications
1) yes, I truly have 9 different grammars I built with antlr so they will ALL have their own lexer/parser objs.
2) yes, as of right now we are comparing strings and obivously that'll be replaced with some sort of integer map.
I've also considered sticking the site identifiers into one regex, however I don't believe that will speed anything up.
3) yes, this is pseudocode so I wouldn't get too picky on the semantics here..
4) kdgregory is correct in noting that I am unable to create one instance of the lexer/parser pair
I like the hash idea to make the code a little bit better looking, however I don't think it's going to speed me up any.
The standard approach is to use a Map to connect the key strings to the lexers that will handle them:
Map<String,Lexer> lexerMap = new HashMap<String,Lexer>();
lexerMap.put("source1", new Lexer01());
lexerMap.put("source2", new Lexer02());
// and so on
Once you've retrieve the string that identifies the lexer to use, you'd retrieve it from the Map like so:
String grammarId = // read it from a file, whatever
Lexer myLexer = lexerMap.get(grammarId);
Your example code has a few quirks, however. First, the indexOf() calls indicate that you don't have a stand-alone string, and Map won't look inside the string. So you need to have some way to extract the actual key from whatever string you read.
Second, lexers and parsers usually maintain state, so you won't be able to create a single instance and reuse it. That indicates that you need to create a factory class, and store it in the map (this is the Abstract Factory pattern).
If you expect to have lots of different lexers/parsers, then it makes sense to use a map-driven approach. For a small number, an if-else chain is probably your best bet, properly encapsulated (this is the Factory Method pattern).
Using polymorphism is almost guaranteed to be faster than string manipulation, and will be checked for correctness at compile time. Is site really a String? If so, FindSite should be called GetSiteName. I would expect FindSite to return a Site object that knows the appropriate lexer and parser.
Another speed issue is speed of coding. It would definitely be better to have your different lexers and parsers in individual classes (perhaps with shared functionality in another). It'll make your code slightly smaller, and it will be significantly easier for someone to understand.
Something like:
Map<String,LexerParserTuple> lptmap = new HashMap<String,LexerParserTuple>();
lpt=lptmap.get(site)
lpt.loadlexer()
lpt.loadparser()
combined with some regex magic rather than string.indexOf() to grab the names of the sites should dramatically clean up your code.
Replace Conditional With Polymorphism
For a half-measure, for findsite(), you could simply set up a HashMap to get you from site identifier to site. An alternative cleanup would be simply to return the site string, thus:
String findsite(txt) {
...................
if line.indexOf("site1-identifier")
return site1;
if(line.indexOf("site2-identifier")
return site2;
if(line.indexOf("site3-identifier")
return site3;
...
}
Using indexOf() in this way isn't really expressive; I'd use equals() or contains().
Suppose your code is inefficient.
Will it take more time than (say) 1% of the time to actually parse the input?
If not, you've got bigger "fish to fry".
I was thinking about deriving the lexer/parser spawning into sep. classes and then instantiating them as soon as I get a match
It looks like you have the answer already. That would create code that is more flexible, but not necessary faster.
I guess some benchmarking is in order
Yes, measure with both approaches and take an informed decision. My guess is the way you have it already would be enough.
Perhaps, if what's bothers you is to have a "kilometric" method you could refactor it in different functions with extract method.
The most important thing is to have first a solution that does the job even though it is slow, and once you have it working, profile it and detect points where the performance could be improved. Remember the "Rules of optimization"
i would change the type of findsite to return a site type (super class) and then leverage the polymorphism...
That should be faster than string manipulation...
Do you need separate lexers ?
Use a Map to configure a site to loadstrategy structure. Then a simple lookup is required based on 'site' and you execute the appropriate strategy. Same can be done for findSite().
Could have a map of idenifiers vs sites, then just iterate over the map entries.
// define this as a static somewhere ... build from a properties file
Map<String,String> m = new HashMap<String,String>(){{
put("site1-identifier","site2");
put("site2-identifier","site2");
}}
// in your method
for(Map.Entry<String,String> entry : m.entries()){
if( line.contains(entry.getKey())){
return line.getValue();
}
}
cleaner: yes
faster: dunno...should be fast enough
You could use reflection possibly
char site = line.charAt(4);
Method lexerMethod = this.getClass().getMethod( "loadLexer" + site, *parameters types here*)
Method parserMethod = this.getClass().getMethod( "loadparser" + site, *parameters types here*)
lexerMethod.invoke(this, *parameters here*);
parserMethod.invoke(this, *parameters here*);
I don't know about Java but some language allow switch to take strings.
switch(site)
{
case "site1": loadlexer1; loadparser1; break;
case "site2": loadlexer2; loadparser2; break;
...
}
As for the seconds bit, use a regex to extract the identifier and switch on that. You might be better off using an enum.

Categories