• Post Reply Bookmark Topic Watch Topic
  • New Topic

Why We Use Type Casting?  RSS feed

 
Mohd Adil
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why We Use Type Casting and How It ll work .... and what is the process of type casting
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16028
87
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch.

As you know, Java is a statically typed language. Variables have a type, and the compiler which check that you use the correct types everywhere in your program - if you are trying to use a variable with a wrong type, you will get an error from the compiler.

Sometimes, you as the programmer know better than the compiler what the type of an object is. That's when you use casting. You're telling the compiler: don't check the type here, I'm telling you that this object is of type X so I want you to treat it like that.

For example, let's look at putting something in a raw List (without using generics):

Note that a type check will still be done - but at runtime, not at compile time. If, at runtime, the object in the list turns out not to be a String, you will get a ClassCastException.

It's better to avoid casts as much as possible, so that you can't get any ClassCastExceptions. That's why, in the case of collections, you should always use generics.

Note that a cast does not do any automatic conversion from one type of object to another. It's simply to tell the compiler: I have this object here, and I want you to treat it as if it is of type X.
 
Joe Bishara
Ranch Hand
Posts: 175
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
IMPLICIT CONVERSION
When carrying out an operation like an assignment, the compiler will check that conversion is possible (based on compile-time types). If conversion is impossible (based on compile-time types), you’ll get a compiler error at compile-time.

EXPLICIT CONVERSION (CASTING)
Sometimes, conversion is impossible (based on compile-time types) but conversion is possible (based on runtime types). If you’re sure that this is the case, you can disable compiler checks by casting. The JVM will check that conversion is possible (based on runtime types). If conversion is impossible (based on runtime types), the JVM will throw ClassCastException at runtime.


 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Joe Bishara wrote:. . . Sometimes, conversion is impossible (based on compile-time types) but conversion is possible (based on runtime types). . . .
Are you sure you have got those the right way round?
 
Joe Bishara
Ranch Hand
Posts: 175
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
Joe Bishara wrote:. . . Sometimes, conversion is impossible (based on compile-time types) but conversion is possible (based on runtime types). . . .
Are you sure you have got those the right way round?

Yes. If the programmer is sure that conversion is possible (based on runtime types), he can disable compiler checks by casting. As far as the compiler is concerned, conversion is impossible (based on compile-time types). The compiler cannot see that conversion is possible (based on runtime types) because the compiler cannot see runtime types. This is why the programmer can choose to disable compiler checks by casting.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mohd Adil wrote:Why We Use Type Casting

Actually, we generally don't if we can possibly help it. And since the introduction of generics there's almost never a need to; so if you find yourself doing it a lot, you should probably review your code.

Hopefully the others have answered the rest of your question.

Winston
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Joe Bishara wrote:. . .
Yes. If the programmer is sure that conversion is possible (based on runtime types), he can disable compiler checks by casting. As far as the compiler is concerned, conversion is impossible (based on compile-time types). The compiler cannot see that conversion is possible (based on runtime types) because the compiler cannot see runtime types. This is why the programmer can choose to disable compiler checks by casting.
No, I am not convinced you have got it right.

If the compiler sees that conversion would be impossible, it will fail to compile.You cannot cast a String to an Integer because they are not subtypes of each other.That code will compile because the compiler can not see that casting is impossible. Integer is a subtype of Number, so it is possible that the cast will succeed. Possible, not certain; the programmer has said it will be an Integer and the compiler believes that. If the compiler's naïve trust was misplaced, then you will suffer a class cast exception.
 
Joe Bishara
Ranch Hand
Posts: 175
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think that there are type compatibility checks and type conversion checks.

With implicit or explicit conversion of object references, type compatibility checks are mandatory i.e. the compiler always checks that both types are compatible i.e. it checks that both types are related by inheritance (based on compile-time types) – if not, compiler error will be generated.

If both types are compatible:
  • with implicit conversion, the compiler checks that type conversion is possible (based on compile-time types) – if not, compiler error will be generated
  • with explicit conversion, the JVM (not the compiler) checks that type conversion is possible (based on runtime types) – if not, ClassCastException will be generated

  • We might be saying the same thing in different ways.
     
    Campbell Ritchie
    Marshal
    Posts: 55768
    163
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I think you have got it right, but don't call things implicit conversion. The official terms are widening and narrowing. A widening conversion can be done automatically and a narrowing conversion cannot. You will find more info in the JLS (+Java® Language Specification) especially §5.1.5 and §5.1.6. That may be difficult to read. Compare that with conversions of primitives, which work completely differently.
     
    Joe Bishara
    Ranch Hand
    Posts: 175
    17
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:The official terms are widening and narrowing.

    I agree, but when dealing with object references, I find the distinction between “widening conversion” and “narrowing conversion” a little confusing because “narrowing conversion” is never allowed; only “widening conversion” is actually possible at runtime. This “widening conversion” may be implicitly or explicitly implied. For me, it's easier to distinguish between implicitly implied “widening conversion” and explicitly implied “widening conversion”.

    If the conversion type is implicitly specified, the compiler checks that “widening conversion” is possible – if not, it generates a compiler error.

    If the conversion type is explicitly specified, the JVM checks that “widening conversion” is possible – if not, it generates a ClassCastException.

    According to the JLS
    "...after the type of the expression has been deduced, an implicit conversion from the type of the expression to the target type can sometimes be performed"
     
    Campbell Ritchie
    Marshal
    Posts: 55768
    163
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Joe Bishara wrote:. . . If the conversion type is implicitly specified, the compiler checks that “widening conversion” is possible – if not, it generates a compiler error.

    If the conversion type is explicitly specified, the JVM checks that “widening conversion” is possible – if not, it generates a ClassCastException. . . .]
    No, you have got it the wrong way round. Widening reference conversions are always feasible and always succeed. You mean narrowing conversion, surely.
     
    Winston Gutkowski
    Bartender
    Posts: 10573
    65
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Joe Bishara wrote:If the conversion type is implicitly specified, the compiler checks that “widening conversion” is possible – if not, it generates a compiler error.
    If the conversion type is explicitly specified, the JVM checks that “widening conversion” is possible – if not, it generates a ClassCastException.

    That doesn't sound right to me.

    As far as objects (or references) are concerned, the compiler only allows what it knows it can allow, and produces warnings or errors for those it doesn't. AFAIR it's smart enough to know when a cast won't work - ie, a cast from a class in one hierarchy to another class in a different one, and will always produce an error, but there are several "grey" scenarios - particularly when interfaces get involved - where a cast might work, but which can only be evaluated at runtime (ie, by the JVM).

    And “conversion” strikes me as the wrong term here (although the JLS uses several terms that I don't particularly like). Casting never involves conversion - nothing changes, except the declared type - it is merely a check whether the object can be re-typed; and some of those can be done at compile time, the remainder are done at runtime.

    Don't know if it makes things any clearer, but HIH.

    Winston
     
    Joe Bishara
    Ranch Hand
    Posts: 175
    17
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:You mean narrowing conversion, surely.

    Widening conversion (based on runtime types) is always allowed. Narrowing conversion (based on runtime types) is never allowed.

    Joe Bishara wrote:If the conversion type is implicitly specified, the compiler checks that “widening conversion” is possible – if not, it generates a compiler error.

    Throwable t = new RuntimeException(); // compiler does not generate a compiler error
    This code implicitly tells the JVM to convert a RuntimeException type to a Throwable type (i.e. widen a RuntimeException type to a Throwable type) before doing the assignment. The compiler does not generate a compiler error because this is a widening conversion.

    RuntimeException t = new Throwable(); // compiler generates a compiler error
    This code implicitly tells the JVM to convert a Throwable type to a RuntimeException type (i.e. narrow a Throwable type to a RuntimeException type) before doing the assignment. The compiler generates a compiler error because this is a narrowing conversion.

    Joe Bishara wrote:If the conversion type is explicitly specified, the JVM checks that “widening conversion” is possible – if not, it generates a ClassCastException.

    Throwable t = new RuntimeException();
    Throwable x = (Exception)t; // JVM does not generate a ClassCastException
    This code (line 2) explicitly tells the JVM (via a cast) to convert a RuntimeException type to an Exception type (i.e. widen a RuntimeException type to an Exception type) before doing the assignment. The JVM does not generate a ClassCastException because the cast (RuntimeException to Exception) is a widening conversion.

    Throwable t = new RuntimeException();
    Throwable x = (java.io.IOException)t; // JVM generates a ClassCastException
    This code (line 2) explicitly tells the JVM (via a cast) to convert a RuntimeException type to an IOException type (i.e. narrow a RuntimeException type to an IOException type) before doing the assignment. The JVM generates a ClassCastException because the cast (RuntimeException to IOException) is a narrowing conversion.
     
    Campbell Ritchie
    Marshal
    Posts: 55768
    163
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Winston Gutkowski wrote:. . . the JLS uses several terms that I don't particularly like). Casting . . .
    There is another bad term: cast(ing). A cast on a reference type never changes the object being cast, but a cast on a primitive may delete data irretrievably.You cannot recover the 0123_4567 part of the original number however hard you try.

    If they had used different words for the two kinds of cast, it would not have been so bad.
     
    Campbell Ritchie
    Marshal
    Posts: 55768
    163
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Joe Bishara wrote:. . . Throwable t = new RuntimeException(); . . . The compiler does not generate a compiler error because this is a widening conversion.
    Agree.
    . . . Throwable t = new RuntimeException();
    Throwable x = (java.io.IOException)t; . . . the cast (RuntimeException to IOException) is a narrowing conversion.
    Nonsense. You are not narrowing runtime exception to IO exception. You are narrowing the reference t from Throwable to IO exception. Since that is a conceivable cast, the compiler permits it but as you said, it fails at runtime.
     
    Joe Bishara
    Ranch Hand
    Posts: 175
    17
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:You are not narrowing runtime exception to IO exception. You are narrowing the reference t from Throwable to IO exception.

    You're looking at what's going on at compile-time. When casting object references, what really matters is what's going on at runtime, not compile-time because as long as the types are compatible (related by inheritance), the compiler will always allow a cast to compile since it cannot see runtime types. The code is narrowing a RuntimeException type to an IOException type (based on runtime types).
     
    Campbell Ritchie
    Marshal
    Posts: 55768
    163
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Joe Bishara wrote:. . . cannot see runtime types. The code is narrowing a RuntimeException type to an IOException type (based on runtime types).
    That was nonsense before and it is nonsense now.

    If the compiler cannot see runtime types (correct) it can only go on the declared type, which is Throwable. If the compiler really thought it was casting a runtime exception to IO exception it would fail to compile.
     
    Joe Bishara
    Ranch Hand
    Posts: 175
    17
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sorry. The example I gave was wrong.

    Throwable t = new RuntimeException();
    Throwable x = (SecurityException)t; // JVM generates a ClassCastException

    As far as the compiler is concerned, the cast at line 2 is narrowing a Throwable type to a SecurityException type. The code compiles because both types are compatible (related by inheritance).

    As far as the JVM is concerned, the cast at line 2 is narrowing a RuntimeException type to a SecurityException type. The JVM generates a ClassCastException because the cast (RuntimeException to SecurityException) is a narrowing conversion.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!