JDK-6204730 : Adding typeswitch to Java
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2004-12-06
  • Updated: 2010-04-26
  • Resolved: 2006-11-13
Related Reports
Duplicate :  
Description
Background
----------

Java 5 introduced generic types to the core Java syntax. This has had 
two effects. Firstly, the type-safety of code using generics is much 
better. In particular, it is now possible to have type-safe generic 
collections. Seccondly, it has removed the need for many explicit cast 
operations. This makes the code more readable, and also cuts out yet 
another source of run-time failures.

Some casting between Object types will always be required in Java. 
However, generics have shown that removing the need for explicit casts 
by adding language features can be a worth-while trade off between 
language complexity and increased code quality.

One of the most frequent remaining cases where casts are used is when 
executing a block only if an object is of a given type. A contrived 
example would be:

Object item;
...
if(item instanceof String) {
  String s = (String) item;
  s.subString(2, 5);
} else if(item instanceof Number) {
  Number n = (Number) item;
  n.intValue();
} else ...

Code like this is often found in parsers and AST processors, 
serialization code, and user input handling. Although sometimes it 
indicates that the software has not been developed in a very OO manner, 
it is in some cases unavoidable or just pragmatic.

These code blocks always follows the same highly-stylised form. There is 
an if/else where each if is a test on instanceof for some class, and 
then inside the if, the object is cast to that class and then used. C# 
and C++ both have syntaxes to simplify this type of conditional-on-type 
expression. ML-family languages tend to support this kind of expression 
directly in the language as a list of alternates guarded by types using 
their pattern-matching facilities. Some languages, such as NICE use 
multiple dispatch (Java has single-dispatch - dispatch on object type, 
and non-oo procedural langauges usually have just one method for each 
identifier). The classical OO approach to working arround having single 
dispatch is to use the Visitor design pattern, but this comes with 
design-time overheads and can't always be retro-fitted to existing code.


The proposal
------------

The switch construct allows code to be conditionaly executed based upon 
the value of an item. The value can either be an integer type or an 
enum. We propose that a similar syntax be added for switching over 
types. We will refer to this as typeswitch.

Object item;
...
typeswitch (x : item)
{
  case String:
    x.subString(2, 5); // use x as String
  case Number:
    x.intValue(); // use x as Number
  ...
}

The new typeswitch expression is of the form:

  typeswitch ( identifier : expression ) typeswitch_case_list

where each typeswitch_case is of the form:

  case type_name : statement

The above example typeswitch expands to this code:

Object item;
...
if(item instanceof String) {
  String x = (String) item;
  x.subString(2, 5);
} else if(item instanceof Number) {
  Number x = (Number) item;
} else ...

As every typeswitch expression can be directly converted into existing 
Java expressions, we are not adding anything to the semantics of the 
language. However, we are arguably producing a much cleaner syntax that 
removes the need to write repetative and error-prone code.

The colon seperating the identifier and the expression in the typeswitch 
has been chosen to mirror the use of the colon in the extended for loop. 
It would be possible to add a new keyword 'typeswitch' to Java, but this 
may cause problems. However, the syntax of typeswitch as presented here 
is easy to distinguish from that of switch, so the switch keyword could 
be re-used.

To avoid type-safety issues, it would be necessary to prevent typeswitch 
cases from falling through, as integer and enum switches currently do. 
If fall-through was supported, then the above example would eroneously 
attempt to treat a String object as a Number.

There is no need for a default clause, as Object can always be added as 
one of the cases. It would probably be good coding style to habitually 
supply a case that matches Object that raises an exception indicating 
that there is an unhandled type case.

Cases are processed from top to bottom. It is an error to have a case 
where the type is incompatible with the type of the expression. For 
example, if the expression has type String, it would be an error to use 
any concrete class other than String and Object. However, it would be 
legal to use any interface that String does or may implement.

It is an error for a case to be unreachable because a previous case will 
always accept the item. This should cover a lot of user errors.


Summing up
----------

The addition of a typeswitch construct to Java could be done with 
minimal impact on existing code. It would address one of the last 
remaining legitimate causes of explicit casts not addressed by generics. 
By using the switch keyword with the new syntax, there would be no 
reason to expand the set of Java keywords.

There are the arguments agains typeswitches that I can forsee. The 
semantics of a typeswitch are not the same as that for existing switch 
statements (in particular, the lack of fall-through on cases). This 
would tend to be an argument towards using something modelled on a 
type-aware if/else construct, such as:
  if(Type identifier : expression) body
However, in the earlier discussions, this was ruled out.

Adding typeswitch may encourage developers to use switch-over-type where 
polymorphism is the cleaner solution. However, some situations just 
can't be handled in this manner. The visitor design pattern is a 
work-arround for some of these problem cases. A typeswitch would allow 
visitor-like behavior to be implemented over class hierachies that don't 
have visitor support (for example, the java reflective Type hierachy).




###@###.### 2004-12-06 22:00:41 GMT