Solved

When is it not bad form to cast in Java?

Posted on 2012-03-22
17
293 Views
Last Modified: 2012-03-22
Say you have custom generic class MyList<Elm extends ListElm>

where ListElm is an interface.  Now you have client code working with a concrete instance of MyList, instantiated using an implementor of ListElm, which also happens to have some of its own methods which are not part of the ListElm interface:

MyList<ListElmClass> myList = new MyList<ListElmClass>();
myList.someMethodFromListElmClass(); // where someMethodFromListElmClass() exists in ListElmClass but not in ListElm

Open in new window


The code above won't work as is.  I am required to manually cast "myList" to "ListElmClass" before calling someMethodFromListElmClass().  

1.  Is it bad form to do this?  If so, what is the better way?  

2.  Why doesn't this work?  Is it something to do with erasure?

Thanks!
0
Comment
Question by:Jonah11
  • 10
  • 4
  • 2
  • +1
17 Comments
 
LVL 47

Expert Comment

by:for_yan
ID: 37755840
>The code above won't work as is.  I am required to manually cast "myList" to "ListElmClass" before calling someMethodFromListElmClass().  

I think you have not quite correct logic

when saying this
MyList<ListElmClass> myList

you are saying that myList is an instance of class MyList<T> where parameter is type ListElmClass

Thsi by no means shoudl mean that myList is inatnce of ListElmClass and as a rule it will not be instance of ListElmClass and you will not be able to use mnethods of ListElmClass on myList and you should not be able to cast it to ListElmClass
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755844
this stuations is similar to the situation with say ArrayList

iif i say

ArrayList<String> ar;

then ar is an instance of ArrayList, it is not an isntance of String and I can neither
invoke methods of String on ar, say ar.substring(...) is wrong

and I would not be able to cast ar to String

ArrayList<String> ar is isntance of ArrayList, juts ArrayList has parameter and this paramtere should be some type which in this case is specified as String
it does not give me ability to think that ar is instance of string and I cannot cast ar to String
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755853
>implementor of ListElm, which also happens to have some of its own methods which are not part of the ListElm interface:

this implementor of ListElm is actually type parameter of MyList and therefore you cannot invoke methods of this implementor, no matter if those are methods of your interface, or some other methods,  on the instance of MyList
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 47

Expert Comment

by:for_yan
ID: 37755866
Consider this simple example showing distinction between genericised class
and its paramater type:
(see my comments in the code):

class MyClass<T> {
    T myObject;
    public MyClass(T tt){
        myObject = tt;
    }

 public T getParamInst(){
     return myObject;
 }


}

class A {
    public static void main(String[] args) {
        MyClass<String> mc = new MyClass<String>("ttytyt");

         String s2 =   mc.substring(0,5); //error, as mc is not a String - compiler complains
        String s = mc.getParamInst();
        String s1 =  s.substring(0,5);  // no error, as method getParmInst() returned typ of parameter T, which happens to be string
  }


}

Open in new window

0
 
LVL 26

Expert Comment

by:ksivananth
ID: 37755901
you can't access the additional methods defined in ListElmClass in MyList and you shouldn't be doing casting there, instead what you can do is,

class ListElmClassList extends MyList<ListElmClass>{

}

here you'll be able to access additional methods defined in ListElmClass

>>MyList<ListElmClass> myList = new MyList<ListElmClass>();

this will be changed to,

ListElmClassList myList = new ListElmClassList();
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755922
instance of class  MyList<ListElmClass>

just does not have methods of ListElmClass, it is absolutely different class

the same way as instance of ArrayList<String> does not have methods of String
0
 
LVL 7

Author Comment

by:Jonah11
ID: 37755933
Everyone,

I'm sorry for the confusion.  My original code snippet should have read:

MyList<ListElmClass> myList = new MyList<ListElmClass>();
myList.get(1).someMethodFromListElmClass(); // where someMethodFromListElmClass() exists in ListElmClass but not in ListElm

Open in new window


That is, we are trying to invoke the method on an element of the list, not on the list itself.  Everything else in my OP should hopefully make more sense now.
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755938
OK, this makes much more sense
but if you declaethat each element implements interface ListElm
then complier only knows that on this element you caninvoke methods of that interface
so if you want to invoke some other methods - you need to explicitly tell compiler that it belongs to the class which has these additional methods - to cast to that class
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755942
this is still not clear what you mean:
> someMethodFromListElmClass() exists in ListElmClass but not in ListElm

how many classes/interfcaes   do you have and how you declare them?
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755944
Is ListElm class or inteface?
0
 
LVL 26

Expert Comment

by:ksivananth
ID: 37755948
>>myList.get(1).someMethodFromListElmClass(); // where someMethodFromListElmClass() exists in ListElmClass but not in ListElm
>>

this should work! what error you get?
0
 
LVL 35

Accepted Solution

by:
mccarl earned 500 total points
ID: 37755949
How exactly have you implemented the custom MyList class? In particular, what is the definition of the get() method that you mention in line 2 above?

I might assume that it is defined like...

public ListElm get(int index) {
...
}

Open in new window


??? Is that true. If so you have to change that to be...

public Elm get(int index) {
...
}

Open in new window


As long as MyList is defined as in your OP, ie. public class MyList<Elm extends ListElm> {
0
 
LVL 7

Author Comment

by:Jonah11
ID: 37755952
ListElm is an interface, but that doesn't matter.  It could be a superclass of ListElmClass as well.

then complier only knows that on this element you caninvoke methods of that interface
so if you want to invoke some other methods - you need to explicitly tell compiler that it belongs to the class which has these additional methods - to cast to that class

This is my question.  Why can't the compiler tell from my declaration MyList<ListElmClass> that now this specific list is a list of ListElmClass, and not just plain ListElm?  

And again, to return to my OP, is it considered poor design to do this the way I have, where casting is required?
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755953
check this - i just checked it with compiler - all very logical

interface ListElm {
    public void method();

}

class ListElmClass implements ListElm {

    public void method() {

    }
    
     public void method2()   {
         
     }
    

}

class MyList<T> {
    T t;
    
    public T getT() {
        return t;
        
    }
    
}

class B {

    public B() {

      MyList<ListElm> myList = new MyList<ListElm>();
             myList.getT().method();
            myList.getT().method2();   // this causes error - it deoes know that it has method() but does not know taht is has method2()

        
           ((ListElmClass) myList.getT()).method2(); // this is OK
            
        
    }



}

Open in new window

0
 
LVL 26

Expert Comment

by:ksivananth
ID: 37755957
can you respond to #37755949?
0
 
LVL 47

Expert Comment

by:for_yan
ID: 37755960
if you reeally declare it like that:
 MyList<ListElmClass> myList = new MyList<ListElmClass>();

then there is no error - i just checked

interface ListElm {
    public void method();

}

class ListElmClass implements ListElm {

    public void method() {

    }

     public void method2()   {

     }


}

class MyList<T> {
    T t;

    public T getT() {
        return t;

    }

}

class B {

    public B() {

      MyList<ListElmClass> myList = new MyList<ListElmClass>();
             myList.getT().method();
            myList.getT().method2();   // this is fine

           ((ListElmClass) myList.getT()).method2(); // this is OK

        
    }



}

Open in new window

0
 
LVL 26

Expert Comment

by:ksivananth
ID: 37755962
>>MyList<ListElm> myList = new MyList<ListElm>();

change it to and see,

MyList<ListElmClass> myList = new MyList<ListElmClass>();
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
session migration servlets 2 42
eclipse console opening separately 2 29
going to wrong jsp page 2 33
Selenium docs api java index 3 48
For customizing the look of your lightweight component and making it look lucid like it was made of glass. Or: how to make your component more Apple-ish ;) This tip assumes your component to be of rectangular shape and completely opaque. (COD…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question