Why is an explicit cast not needed here? - java

class MyClass {
void myMethod(byte b) {
System.out.print("myMethod1");
}
public static void main(String [] args) {
MyClass me = new MyClass();
me.myMethod(12);
}
}
I understand that the argument of myMethod() being an int literal, and the parameter b being of type byte, this code would generate a compile time error. (which could be avoided by using an explicit byte cast for the argument: myMethod((byte)12) )
class MyClass{
byte myMethod() {
return 12;
}
public static void main(String [ ] args) {
MyClass me = new MyClass();
me.myMethod();
}
}
After experiencing this, I expected that the above code too would generate a compile time error, considering that 12 is an int literal and the return type of myMethod() is byte. But no such error occurs. (No explicit cast is needed: return (byte)12; )
Thanks.

Java supports narrowing in this case. From the Java Language Spec on Assignment Conversion:
A narrowing primitive conversion may be used if the type of the
variable is byte, short, or char, and the value of the constant
expression is representable in the type of the variable.

From Java Primitive Data Type reference:
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).
Try returning 128 : ))

This will work byte b = 4 as long as value is within the range, but if you try something like byte b = 2000 you would get compiler error because it is out of range. 12 is in within range so you aren't getting error.

Related

constant expression require in java switch case (field is final and initialized)

public static final Integer SAMPLE = 100;
public static void doSomething(int errorCode) {
switch (errorCode) {
case SAMPLE:
// ...
break;
}
}
I got constant expression required. if i change SAMPLE to int it will get fix. why ?
The relevant parts of the language spec are in JLS Sec 14.11:
Every case label has a case constant, which is either a constant expression or the name of an enum constant.
This explains why you can't use an Integer value: it's not a constant expression, since it is evaluated at runtime.
The fix is to change the case label to have a constant expression. To know what types are allowed, read on in the same section of the spec:
Every case constant associated with the switch statement must be assignment compatible with the type of the switch statement's Expression (§5.2).
and
The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error occurs.
Since you can't have a constant wrapped primitive type (Character, Byte, Short or Integer: they're all evaluated at runtime), this means that case labels can only be:
char
byte
short
int
String
An enum constant
The easiest option is to change your declaration of SAMPLE to:
public static final int SAMPLE = 100;
Note that 100 is in the guaranteed-cached range of Integer.valueOf, so there is no cost of declaring the value as a primitive: where you need a boxed value, a value is used from the cache.
Switch can only work with some primitives (char, byte, short, int), enum values and Strings.
change it to;
public static final int SAMPLE = 100;
Actually the switch statement can work with Integer.
Source: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
The case is only working with constant values, e.g. primitives and compile-time String.
Your SAMPLE field that you pass to the case statement should be of primitive type.

What is difference between wrapper and Auto Boxing/Unboxing in java?

A Wrapper Class is used to convert primitive into object and object into primitive. Similarly by using Autoboxing and Unboxing we can do the same then what is the difference in these two:
1-Concept wise
2-Code wise???
Auto-boxing and auto-unboxing is just the compiler silently helping you create and use primitive wrapper objects.
For example, the int primitive type has wrapper class called Integer. You wrap and unwrap as follows:
int myInt = 7;
// Wrap the primitive value
Integer myWrappedInt = Integer.valueOf(myInt);
// Unwrap the value
int myOtherInt = myWrappedInt.intValue();
With auto-boxing and auto-unboxing, you don't have to do all that boiler-plate stuff:
int myInt = 7;
// Wrap the primitive value
Integer myWrappedInt = myInt; // Compiler auto-boxes
// Unwrap the value
int myOtherInt = myWrappedInt; // Compiler auto-unboxes
It's just a syntactic sugar, handled by the compiler. The generated byte code is the same.
Wrapper classes in java provides a mechanism to convert primitive into object and object into primitive. Whereas automatic boxing and unboxing allows you to do that conversion automatically. Autoboxing and auto unboxing are legal in java since Java 5.
public class Main {
public static void main(String[] args) {
int x=100;
Integer iob;
iob=x;//illegal upto JDK1.4
iob= Integer.valueOf(x); //legal=> Boxing,Wrapping
iob=x; //Legal since JDK1.5=> Auto Boxing
}
}
Here x is a primitive variable, iob is a reference variable. So only an address can be assigned into this iob reference. iob=Integer.valueOf(x) will convert primitive integer into integer object. This conversion can be implied as wrapping. iob=x will do the same thing. It also saves a lot of coding.
public class Main {
public static void main(String[] args) {
Integer iob= new Integer(100);
int x;
x=iob;//illegal upto JDK1.4
x=iob.intValue(); //unboxing,unwrapping
x=iob; //legal since JDK1.5=> auto unboxing
}
}
Here iob.intValue() will take the value of integer object and it will assign that value into x. x=iob does the same thing except you don't need to write conversion code.

Java Generics Compare Number with Byte

Why can't Byte and Number/Integer be compared? I have attached my source code. See the comments. Also why I have to cast 88 into byte, isn't it done automatically with auto-boxing and auto-unboxing?
package com.practice;
public class Generics<T extends Number>
{
T ob;
public Generics(T i)
{
ob = i;
}
T getObj()
{
return ob;
}
boolean compare(Generics<?> o)
{
if (this.ob == o.ob)
{
return true;
}
else
{
return false;
}
}
public static void main(String[] args)
{
Generics<Number> num = new Generics<>(88);
// Generics<Byte> Byte = new Generics<>(88); //why this does not
// compile?
Generics<Byte> Byte = new Generics<>((byte) 88);
Generics<Integer> integer = new Generics<>(88);
System.out.println(num.compare(integer)); // this is true!!
System.out.println(num.compare(Byte)); // why False?
System.out.println(integer.compare(Byte)); // Why false?
}
}
Why I have to cast 88 into byte, isn't it done automatically with auto-boxing and auto-unboxing?
By default, a numeric literal (like 88) is an int. The auto-boxing does happen but the compiler boxes it into an Integer and not a Byte because, as I just told, it's an int.
Generics<Number> num = new Generics<>(88);
Generics<Integer> integer = new Generics<>(88);
Since, an Integer IS-A Number both of the above work just fine.
Generics<Byte> Byte = new Generics<>(88); // why this does not compile?
Now, in case of Generics<Byte>, the constructor becomes Generics(Byte i), which fails because an Integer cannot be assigned to a Byte as there's no inheritance between them. They both extend Number and are sibling classes.
Generics<Byte> Byte = new Generics<>((byte) 88);
So, to pass in a Byte and satisfy the compiler, the (byte) cast is required. Now the auto-boxing happens again but from a byte to Byte this time.
Regarding equality, your compare() method implementation is flawed because it only compares references this.ob == o.ob and not their values.
System.out.println(num.compare(integer)); // this is true!!
System.out.println(num.compare(Byte)); // why False?
System.out.println(integer.compare(Byte)); // Why false?
This however worked for integer comparison num.compare(integer) because you chose a small value 88 which falls in the range of values (-128 to +127) cached and shared by the JVM among auto-boxed Integer instances. If you run your program again with a larger value like 888, it will print false for the same comparison.
So, to fix your compare() method, you'll need to sort of unbox their numeric values.
return (this.ob.floatValue() == o.ob.floatValue());
PS: The equals() method wouldn't help here. Check the source code to know why :)

Null, primitive data value and wrapper class in method call [duplicate]

This question already has answers here:
Why is the default type of Java integer literals int instead of long? [closed]
(7 answers)
Closed 7 years ago.
I have following code snippet
public class Sample {
public static void main(String[] args) {
test(1);//fine & output - int
test(1L);//fine & output - long
//test(null); fine & output - Integer
test(12233333333);//error
}
static void test(int a){
System.out.println("int");
}
static void test(Integer a){
System.out.println("Integer");
}
static void test(long a){
System.out.println("long");
}
static void test(Long a){
System.out.println("Long");
}
static void test(List<Integer> a){
System.out.println("List");
}
}
My question is,
Why number value always refer int(primitive type) but null refer the most specific method among the overloads?
Why we need to say implicitly 1L why it not taking long value if u give big number(1233333333333)?
Can u some one explain those?
Why number value always refer int(primitive type) but null refer the
most specific method among the overloads?
Because by default compiler refers to the 32-bit integer operation for number without suffix l OR L (for long).
Why we need to say implicitly 1L why it not taking long value if u
give big number(1233333333333)? Can u some one explain those?
As I said above it by default refers to the integer operation and for such a big number it is out of the range of the Integer as this number will be considered as integer without suffix l or L so it will refer to the method which takes int as parameter but error comes up that value is out of range.
Let's see what JLS says..
JLS 4.2
If an integer operator other than a shift operator has at least one
operand of type long, then the operation is carried out using 64-bit
precision, and the result of the numerical operator is of type long.
If the other operand is not long, it is first widened (§5.1.5) to type
long by numeric promotion (§5.6).
Otherwise, the operation is carried out using 32-bit precision, and
the result of the numerical operator is of type int. If either operand
is not an int, it is first widened to type int by numeric promotion.
1233333333333 is an int literal so you could use that but you would have to cast it to long in which case the compiler will do the conversion. It does not work because it is too large to be an int.
The reason the compiler cannot just assume it is long is because ithey would be inconsistent with 123 being an int.

Need to understand Boxing in core java

I cant figure out how the int 7 is consider as object in below example.
The sifer(7) is consider to be method sifer(Object o). I am not able to get it how this happened. In one of my java reference book it says Int can be boxed to an Integer and then "widened" to an object. I am not sure what that means.
>> Class A
class A { }
>> Class B
class B extends A { }
>> Class ComingThru
public class ComingThru {
static String s ="-";
static void sifer(A[] ...a2)
{
s = s + "1";
}
static void sifer(B[] b1)
{
s += "3";
}
static void sifer(Object o)
{
s += "4";
}
public static void main(String[] args) {
// TODO Auto-generated method stub
A[] aa= new A[2];
B[] ba = new B[2];
//sifer(aa);
//sifer(ba);
sifer(7);
System.out.println(s);
}
}
Since there is no sifer(int) method, the compiler will try to find the "closest match". In this case, the other 2 sifer methods take arrays as parameters, which an int clearly isn't.
The last method, sifer(Object) can be applied to any objects, including an Integer so that's the method that is used for sifer(7).
The reality is a little more complex, and the JVM will look for a matching mathod in the following order:
an identity conversion
in your case: sifer(int) but there is no such method
a widening primitive conversion
in your case: sifer(long) for example, but there is no such method
a widening reference conversion
in your case: not applicable, int is not an object
a boxing conversion optionally followed by widening reference conversion
in your case that's what's happening: int is boxed to Integer which is widened to Object
an unboxing conversion optionally followed by a widening primitive conversion
in your case: not applicable
1. Above code provides an classic example of Method Overloading, along with AutoBoxing and Auto-UnBoxing which came by Java 1.5, cause manual Boxing and Unboxing was a pain.
2. The sifer(A[]... a2) and sifer(B[] b1) both accepts Array type Arguments in its parameter, which no way matches int. So now we are left only with sifer(Object o).
3. Now the int will be converted into Wrapper Object Integer Automatically.
You can verify it by doing this in snifer(Object o) method.
o.getClass().getName();
See this link for further details:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html
7 will be auto boxed to Integer which is an Object
Also See
java: boolean instanceOf Boolean?
Steps as below-
The int (7) was boxed to a Integer.
The Integer reference was widened to an Object (since Integer extends Object).
The sifer() method got an Object reference that actually refers to a Integer
object.

Categories

Resources