Submission: switch (...) instanceof feature

Reinier Zwitserloot reinier at zwitserloot.com
Mon May 4 02:51:00 PDT 2009


Why is this neccessary? We have a similar situation here as the  
inherited exception issue: Rare and definitely broken (at runtime)  
code will now break at compile time. This is technically 'backwards  
incompatible', insofar that code that used to compile no longer does.  
However, I believe the decision was made that this technical  
incompatibility was acceptable, because the code made no runtime sense  
in the first place. You have the same situation here:


old code:

Object x = foo();

if ( x instanceof String ) {
   Integer y = (Integer)x;
}

would compile, eventhough it's clearly bogus. With this change:

if ( x instanceof String ) {
    //within this block, 'x' is considered to be both a String and  
whatever x's actual type is, if it's not a strict supertype of String.
}

the original clearly broken code would all of a sudden produce a  
compile error, because casting a String to an Integer is not allowed  
(at compile-time too, not just at runtime). You could make a rule to  
relax this restriction (and generate a warning instead). Personally  
I'd say that clearly broken code should generate compile-time  
exceptions, that's why we went with static typing in the first place,  
so there's no need to complicate the JLS with such a relaxation just  
to be backwards compatible. That's kind of like Windows Vista taking  
the trouble to be compatible with viruses written for XP, just so they  
can say "we're 100% compatible!". (That's a hypothetical, not a  
comment on Microsoft's programming division. I don't even use windows,  
I have no idea if Vista works like that).


Why would we possibly want to introduce new syntax here?


  --Reinier Zwitserloot
Like it? Tip it!
http://tipit.to



On May 4, 2009, at 10:58, Jeroen van Maanen wrote:

> A colleague of mine pointed out that "if (... instanceof ...)" is  
> currently syntactically correct code. Suddenly the "if" statement  
> would show kind of a meta side effect for a highly specific subset  
> of tests. He suggested that the new "type narrowing if" would get a  
> clearly distinguished syntax, for example:
>
> a concise syntax similar to the extended "for" statement:
>
> if (name : Type) { ... }
>
> or verbose:
>
> if instanceof (name : Type) { ... }
>
> or like a declaration rather that a test, which clearly emphasizes  
> the side effect:
>
> if instanceof (Type name) { ... }
>
> Jeroen
>
> Jeroen van Maanen schreef:
>> I agree that "if (... instanceof ...)" is more readable than the  
>> extension of "switch" that I proposed originally. I believe that  
>> this feature that avoids an unnecessary new name and cast would be  
>> of great benefit to the Java language.
>> Jeroen
>> Derek Foster schreef:
>>> I notice that the example you gave is actually an argument for an  
>>> "if" that respects instanceOf, rather than a 'switch' that does.  
>>> It seems to me like an abuse of notation to use a 'switch' in a  
>>> case like this where only one decision (it is or it isn't a  
>>> subtype of a given type) is being made.
>>>
>>> Although I am skeptical of the 'switch instanceof' feature, for  
>>> the reasons I outlined below, I would very much like to see Java  
>>> implement the 'if instanceof' feature that is implied in the  
>>> proposal, and which various people have been suggesting, so that  
>>> this very common coding pattern:
>>>
>>> if (foo instanceof Bar) {
>>>     Bar bar = (Bar)foo;
>>>     doSomethingWith(bar);
>>> }
>>>
>>> could be simplified to:
>>>
>>> if (foo instanceof Bar) {
>>>     doSomethingWith(foo);
>>> }
>>>
>>> with no loss of type safety. It seems to me that your example  
>>> would be more readable with such a construct than it is with the  
>>> 'switch instanceof' feature.
>>>
>>> I had intended to submit a proposal along these lines myself, but  
>>> simply ran out of time to put it together. Still, it seems to me  
>>> that there's been widespread agreement on the list that the 'if  
>>> instanceof' sub-proposal is a good idea.
>>>
>>> Derek
>>>
>>>
>>>
>>>
>>>
>>> -----Original Message-----
>>>> From: Ulf Zibis <Ulf.Zibis at gmx.de>
>>>> Sent: Apr 22, 2009 5:17 AM
>>>> To: Derek Foster <vapor1 at teleport.com>
>>>> Cc: Gabriel Belingueres <belingueres at gmail.com>, Jeroen van  
>>>> Maanen <jeroen at entreact.com>, coin-dev at openjdk.java.net
>>>> Subject: Re: Submission: switch (...) instanceof feature
>>>>
>>>> Am 22.04.2009 06:55, Derek Foster schrieb:
>>>>> Like Gabriel, I have severe reservations about this proposal. I  
>>>>> am concerned that it will encourage people to avoid the common  
>>>>> OOP "best practice" of using virtual method dispatch in favor of  
>>>>> doing an explicit "switch" on each subtype of a type, in cases  
>>>>> where doing so is not necessary.
>>>>>
>>>>> I concede that there are a few (FEW!) places where doing the  
>>>>> equivalent of a switch on instances of a type is necessary (for  
>>>>> instance, if the type is in a library you don't have the ability  
>>>>> to change). I can see some value in this proposal for that  
>>>>> purpose. However, I would very much not like to see use of this  
>>>>> construct become commonplace. I already see too many instances  
>>>>> of people doing the equivalent of "if (object.type == FOO)  
>>>>> {doThis(); } else if (object.type == BAR) { doThat(); }" instead  
>>>>> of writing "object.doSomething();"
>>>>>
>>>>>
>>>> I like to provide an example where
>>>>
>>>> "object.doSomething();"
>>>>
>>>> doesn't work:
>>>>
>>>>   synchronized Charset lookup(String lowCanonical) {
>>>>       // cache is initialized with available Charset classes names
>>>>       Object o = cache.get(lowCanonical);
>>>>       // Check cache first
>>>>       if (o instanceof String) {
>>>>           // Instantiate new charset
>>>>           Charset cs = newCharset((String)o, lowCanonical);
>>>>           // Cache it
>>>>           if (cs != null)
>>>>               cache.put(lowCanonical, cs);
>>>>           return cs;
>>>>       }
>>>>       return (Charset)o;
>>>>   }
>>>>
>>>>
>>>> This would look much nicer, as it avoids casting:
>>>>
>>>>   synchronized Charset lookup(String lowCanonical) {
>>>>       // cache is initialized with available Charset classes names
>>>>       switch (Object o = cache.get(lowCanonical) instanceof ?) {
>>>>           case String :
>>>>               // Instantiate new charset
>>>>               Charset cs = newCharset(o, lowCanonical);
>>>>               // Cache it
>>>>               if (cs != null)
>>>>                   cache.put(lowCanonical, cs);
>>>>               return cs;
>>>>           case Charset :
>>>>               return o;
>>>>       }
>>>>   }
>>>>
>>>>
>>>> Refer:
>>>> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup
>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402
>>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html
>>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html
>>>>
>>>> - My example could also be smartly coded without switch..case  
>>>> statement, if we would enhance if statement accordingly
>>>> - I also would like to have possibility to declare variables in  
>>>> if clause, like it's possible in for clause:
>>>>
>>>>       if ((Object o = cache.get(lowCanonical)) instanceof String)
>>>>           ... ;
>>>>       else if (o instanceof Charset)
>>>>           ... ;
>>>>
>>>> -Ulf
>>>>
>>>>
>>>>> Derek
>>>>>
>>>>> -----Original Message-----
>>>>>
>>>>>> From: Gabriel Belingueres <belingueres at gmail.com>
>>>>>> Sent: Mar 30, 2009 7:31 AM
>>>>>> To: Jeroen van Maanen <jeroen at entreact.com>
>>>>>> Cc: coin-dev at openjdk.java.net
>>>>>> Subject: Re: Submission: switch (...) instanceof feature
>>>>>>
>>>>>> IMO I'm against this.
>>>>>>
>>>>>> First, it is against current best practices for the design of
>>>>>> object-oriented software to make easier to code something with  
>>>>>> a case
>>>>>> statement on types/classes.
>>>>>>
>>>>>> Second:
>>>>>> void log(Object object) {
>>>>>>  switch (object) instanceof {
>>>>>>  case String:
>>>>>>    logger.debug("'" + object + "'");
>>>>>>  case Date:
>>>>>>    logger.debug(object.getTime());
>>>>>>  case void:
>>>>>>    logger.debug("null");
>>>>>>  default:
>>>>>>    logger.debug("<" + object.toString() + ">");
>>>>>>  }
>>>>>> }
>>>>>>
>>>>>> It think it is clearer (when possible) writing it with several
>>>>>> overloaded methods and double dispatching.
>>>>>>
>>>>>> ....
>>>>>>
>>>
>




More information about the coin-dev mailing list