Switch statements with String
cases have been implemented in Java SE 7, at least 16 years after they were first requested. A clear reason for the delay was not provided, but it likely had to do with performance.
Implementation in JDK 7
The feature has now been implemented in javac
with a "de-sugaring" process; a clean, high-level syntax using String
constants in case
declarations is expanded at compile-time into more complex code following a pattern. The resulting code uses JVM instructions that have always existed.
A switch
with String
cases is translated into two switches during compilation. The first maps each string to a unique integer—its position in the original switch. This is done by first switching on the hash code of the label. The corresponding case is an if
statement that tests string equality; if there are collisions on the hash, the test is a cascading if-else-if
. The second switch mirrors that in the original source code, but substitutes the case labels with their corresponding positions. This two-step process makes it easy to preserve the flow control of the original switch.
Switches in the JVM
For more technical depth on switch
, you can refer to the JVM Specification, where the compilation of switch statements is described. In a nutshell, there are two different JVM instructions that can be used for a switch, depending on the sparsity of the constants used by the cases. Both depend on using integer constants for each case to execute efficiently.
If the constants are dense, they are used as an index (after subtracting the lowest value) into a table of instruction pointers—the tableswitch
instruction.
If the constants are sparse, a binary search for the correct case is performed—the lookupswitch
instruction.
In de-sugaring a switch
on String
objects, both instructions are likely to be used. The lookupswitch
is suitable for the first switch on hash codes to find the original position of the case. The resulting ordinal is a natural fit for a tableswitch
.
Both instructions require the integer constants assigned to each case to be sorted at compile time. At runtime, while the O(1)
performance of tableswitch
generally appears better than the O(log(n))
performance of lookupswitch
, it requires some analysis to determine whether the table is dense enough to justify the space–time tradeoff. Bill Venners wrote a great article that covers this in more detail, along with an under-the-hood look at other Java flow control instructions.
Before JDK 7
Prior to JDK 7, enum
could approximate a String
-based switch. This uses the static valueOf
method generated by the compiler on every enum
type. For example:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}
This snippet on the Advanced Bash Scripting Guide says:
# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.
[[ $a == z* ]] # True if $a starts with a "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
So you had it nearly correct; you needed double brackets, not single brackets.
With regards to your second question, you can write it this way:
HOST=user1
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes1
fi
HOST=node001
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes2
fi
Which will echo
yes1
yes2
Bash's if
syntax is hard to get used to (IMO).
Best Answer
This is a very interesting question. After some testing I don't think this is possible because of the way the text field in the data model is configured.
In principle, you could use the unicode empty-set character of
\u2205
to represent a default empty string but the text field does not seem to accept any escapes so it converts any attempt to escape a unicode character code to the literal string of the code characters themselves e.g. entering '\u2205' ends up as the literal text '\u2205'.In theory you could write a utility app to read in the graphically generated managed object model file and then programmatically set the attribute default to equal an empty string and then save the file back to disk. I say "in theory" because there is no documented way to way to save a managed object model file from code. You can read one and modify it in memory but not persist the changes.
Bit of an oversight, I think.
I don't think you have any choice but to set the default empty string pragmatically when the model first loads. That is simple to do but it's ugly and you'll have to remember you did (especially if you migrate versions) but I think right now that is the only choice.