1 2 3 Previous Next 33 Replies Latest reply: Nov 14, 2007 12:05 PM by 807603 RSS

    using casting combined with the ternary operator

    807603
      Hi everyone.
      I have the following code, which works without problem:
      if (list.get(0) instanceof A) {
          something = ((A) list.get(0)).getSomething();
      } else {
          something = ((B) list.get(0)).getSomething();
      }
      ...but my eyes hurt when I see it: two identical lines save for the type casting. So I tried this:
      something = ((list.get(0) instanceof A? (A) : (B)) list.get(0)).getSomething();
      ...and it doesn't work! It gives me the following errors:

      something = ((list.get(0) instanceof A? *(A)* : (B)) list.get(0)).getSomething();
      A cannot be resolved

      something = ((list.get(0) instanceof A? (A) : *(B)* ) list.get(0)).getSomething();
      B cannot be resolved

      something = ((list.get(0) instanceof A? (A) : (B)) list.get(0)).getSomething();
      Syntax error on token "list", delete this token

      Is it impossible to use the ternary operator here? I tried several combinations of parenthesis, just in case, unsuccessfully.

      Thanks!
        • 1. Re: using casting combined with the ternary operator
          807603
          Any way you slice it, that code looks bad. Is there a common supertype of both A and B that defines getSomething? And can you use generics in such a way to avoid casting entirely?
          • 2. Re: using casting combined with the ternary operator
            807603
            Well, I'm using code not implemented by me, so I can't change the implementation. There's a superclass, let's call it X, and three subclasses: A, B and C. I know for a fact that the members of list are instances either of A or of B. C doesn't have a method getSomething(), so class X can't have a method getSomething(). Is this what you meant?
            • 3. Re: using casting combined with the ternary operator
              807603
              Check your parenthesis the segment in bold are grouped
              something = ( (list.get(0) instanceof A? (A) : (B)list.get(0)) ) .getSomething();
              • 4. Re: using casting combined with the ternary operator
                807603
                something = ( (list.get(0) instanceof A? *(A)* : (B)list.get(0)) ) .getSomething();

                Now it says A cannot be resolved. The problem seems to be that you can't have a cast that's not contiguous to the object you're casting: it doesn't have a problem with B, that is next to list.get(0), but it doesn't recognize A.

                The reason behind my choice of parenthesis is that the "value" (not a value but a type in this case, and I think that's the problem) returned by the expression list.get(0) instanceof A? (A) : (B) must be either (A) or (B). In your example you're including list.get(0) in the "else" of the ternary operator.

                Any other idea?
                Thanks for the suggestion.

                Edited by: black_blizzard on Nov 14, 2007 9:15 AM
                • 5. Re: using casting combined with the ternary operator
                  807603
                  Wait a minute. If you're assigning the result to "something", and you're using object types, then "something" must have a type that's a supertype of A and B.

                  So why are you casting at all?

                  If you're using primitive types...then use a conversion method to change the type, rather than casting.
                  • 6. Re: using casting combined with the ternary operator
                    807603
                    I dont know what you are doing but this works
                         public static void main(String[] args) {
                              List lst = new ArrayList(2);
                              lst.add("Hello");
                              lst.add(new Integer(2));
                              String s = lst.get(0) instanceof String?(String)lst.get(0):((Integer)lst.get(0)).toString();
                              System.out.println(s);
                         }
                    • 7. Re: using casting combined with the ternary operator
                      807603
                      To paulcw: Sorry, I don't think I get what you're saying. The thing is this:
                      * There is a class called X.
                      * There are three subclasses of X called A, B and C.
                      * A and B have a method called getSomething that returns a double, but C doesn't have that method.
                      * list is an ArrayList<X>.
                      * I know for a fact that list.get(0) is either of class A or B.

                      To WirajR: in your case you're repeating lst.get(0) twice. I know that works, but I was wondering if there was a way to avoid it.

                      Edited by: black_blizzard on Nov 14, 2007 9:25 AM
                      • 8. Re: using casting combined with the ternary operator
                        807603
                        import java.util.*;
                        
                        class X {}
                        
                        class A extends X {
                            public double getSomething() {
                                return 0.0;
                            }
                        }
                        
                        class B extends X {
                            public double getSomething() {
                                return 1.0;
                            }
                        }
                        
                        class C extends X {}
                        
                        public class CrazyExample {
                            public static void main(String[] args) {
                                test(new A());
                                test(new B());
                            }
                        
                            static void test(X x) {
                                List<X> list = new ArrayList<X>();
                                list.add(x);
                        
                                X elt = list.get(0);
                                double value = (elt instanceof A) ? ((A) elt).getSomething() : ((B) elt).getSomething();
                                System.out.println(value);
                            }
                        }
                        The design is still wacky.
                        • 9. Re: using casting combined with the ternary operator
                          807603
                          You're repeating code. I know how to do that, I'm asking if there's away to avoid that.
                          And the design isn't mine. Believe me, if it was things would be very different.
                          • 10. Re: using casting combined with the ternary operator
                            807603
                            WirajR wrote:
                            I dont know what you are doing but this works
                            String s = lst.get(0) instanceof String?(String)lst.get(0):((Integer)lst.get(0)).toString();
                            That's totally useless though. Just call toString() on the elements and assign it. Integer.toString() will still work, even if it's static type is Object. String.toString() returns the string itself, so there's no need to differentiate there. Let polymorphism work for you.
                            String s = lst.get(0).toString();
                            • 11. Re: using casting combined with the ternary operator
                              807603
                              hunter9000 wrote:
                              WirajR wrote:
                              I dont know what you are doing but this works
                              String s = lst.get(0) instanceof String?(String)lst.get(0):((Integer)lst.get(0)).toString();
                              That's totally useless though. Just call toString() on the elements and assign it. Integer.toString() will still work, even if it's static type is Object. String.toString() returns the string itself, so there's no need to differentiate there. Let polymorphism work for you.
                              String s = lst.get(0).toString();
                              But WirajR conjured up a crap example, and toString is not a general solution.
                              • 12. Re: using casting combined with the ternary operator
                                807603
                                black_blizzard wrote:
                                To paulcw: Sorry, I don't think I get what you're saying. The thing is this:
                                * There is a class called X.
                                * There are three subclasses of X called A, B and C.
                                * A and B have a method called getSomething that returns a double, but C doesn't have that method.
                                * list is an ArrayList<X>.
                                * I know for a fact that list.get(0) is either of class A or B.
                                In that case, there's no need to do any casting at all. You ought to read up on polymorphism and static vs dynamic typing. If you do this:
                                something = list.get(0).getSomething();
                                Then the dynamic type (the type that the object actually is (A or B) as opposed to the type that you're referencing it with (Object) ) determines which implementation of the method gets called. If it's actually an A, then A's version of getSomething gets called. If it's a B, then B's version is called.
                                • 13. Re: using casting combined with the ternary operator
                                  807603
                                  jToohey wrote:
                                  But WirajR conjured up a crap example, and toString is not a general solution.
                                  I know, it wasn't meant as a general solution to the OP's problem, just a response to his post.
                                  • 14. Re: using casting combined with the ternary operator
                                    807603
                                    hunter9000 wrote:
                                    black_blizzard wrote:
                                    To paulcw: Sorry, I don't think I get what you're saying. The thing is this:
                                    * There is a class called X.
                                    * There are three subclasses of X called A, B and C.
                                    * A and B have a method called getSomething that returns a double, but C doesn't have that method.
                                    * list is an ArrayList<X>.
                                    * I know for a fact that list.get(0) is either of class A or B.
                                    In that case, there's no need to do any casting at all. You ought to read up on polymorphism and static vs dynamic typing. If you do this:
                                    something = list.get(0).getSomething();
                                    Then the dynamic type (the type that the object actually is (A or B) as opposed to the type that you're referencing it with (Object) ) determines which implementation of the method gets called. If it's actually an A, then A's version of getSomething gets called. If it's a B, then B's version is called.
                                    If all you're doing is assigning something, then you don't need the cast. X is the supertype of A and B, and you know that the object must be an A or a B, so you can assign it to X. No problem.

                                    If you're going to invoke getSomething, then you'll have to cast it, because Java won't know whether the object is an A or a B, or a C. But in this case I'd strongly advise changing your design or at least the type hierarchy. For example you could define an interface that requires getSomething, declare A and B as implementing that interface, and then cast the the item from the list to be that interface. This could be a hack though.
                                    1 2 3 Previous Next