I have a rather simple test case below. I can send nulls to the constructor with no problems or errors, but when I try to send nulls to a method, it errors out with: error: incompatible types: <null> cannot be converted to int (or whatever type is expected). I'm not exactly sure why this occurs and I've seen in many places where sending nulls is acceptable practice. In all reality I just need nulls so that I can pump this example into Soot and Spark for static analysis, so the actual parameters sent to the methods are irrelevant other than a semantic necessity for entry points in the Spark-static analysis.
public class Test {
public Test(Object var1, Object var2) {
//do irrelevant stuff here with var1 and var2
}
public void api1(int x, int y) {
// do irrelevant stuff with x and y
}
public List<String> api2(String x, int y, boolean a) {
// do irrelevant stuff with x, y, and a and return a new ArrayList<String>()
}
}
public class Main {
public static void main(String[] args) {
Test usingVars = new Test(1, 2); // works, compiles and no errors
Test usingNulls = new Test(null, null); // works, compiles and no errors
/**
* usingVars will obviously work and not complain at all
*/
usingVars.api1(1, 2); // works, compiles and no errors
usingVars.api2("test", 1, false); // works, compiles and no errors
/**
* usingNulls should work, but throws this error on compilation:
* error: incompatible types: <null> cannot be converted to int
*/
usingNulls.api1(null, null); // should work, doesn't compile errors out
usingNulls.api2(null, null, null); // should work, doesn't compile errors out
}
}
primitives, (e.g., ints), can't take nulls. If you absolutely positively have to use a null value, you should define your method parameters as the appropriate wrapper class (e.g., java.lang.Integer for int):
public Test(Integer var1, Integer var2) {
//do irrelevant stuff here with var1 and var2
}
public void api1(Integer x, Integer y) {
// do irrelevant stuff with x and y
}
public List<String> api2(String x, Integer y, Boolean a) {
// do irrelevant stuff with x, y, and a and return a new ArrayList<String>()
}
In Java you have two types of variables, primitives and references.
A reference can be null as it references nothing. A primitive, such as int cannot be null, it has to be a number.
If you don't care what the values is you can use 0, -1 or Integer.MIN_VALUE
It is impossible to pass null to a method, constructor or otherwise, to a primitive type (e.g. int, short, byte, float) because in java you have two type systems, primitives and objects. Primitives can be cast to their object wrappers (e.g. Integer, Short, Byte, Float) and be used as objects, so if you need to pass null, use Integer, not int. However the convention in java for passing useless values for ints is to use -1.
Related
Here is a literal class that allows one to get a value of a specified type:
public class Literal {
private final String value;
public Literal(String value) {
this.value = value;
}
public <T> T getValue(Class<T> type) {
if (type == Boolean.class || type == Boolean.TYPE) {
return type.cast("true".equalsIgnoreCase(value));
}
throw new UnsupportedOperationException();
}
}
It works fine for object types:
new Literal("true").getValue(Boolean.class);
But it throws the error for primitive types:
new Literal("true").getValue(Boolean.TYPE);
java.lang.ClassCastException: Cannot cast java.lang.Boolean to boolean
Is it possible to return a boolean value without the exception?
Or maybe I can transform a primitive type to a corresponding object type before calling the method? Is there a method to transform boolean type to java.lang.Boolean.class, int type to java.lang.Integer.class, ...? Something like this:
new Literal("true").getValue(toObjectType(Boolean.TYPE));
Yes.. and no.
In basis what you say is a non-sequitur. Your question is: "How do I put this round green in this square hole" - concepts that don't even align.
"An object" cannot become a primitive value, and "an object" cannot be used where a primitive is required. This: Object o = 5; is illegal plain and simple.
Except.. it isn't. And the reason it isn't, is only because of syntax sugar. The compiler KNOWS it is illegal but assumes you MEANT to write Object o = Integer.valueOf(5); so, it just assumes you meant that and generates code accordingly. Just go compile that, run javap -c -v and lo! A call to integer.valueOf you never wrote.
You can do the same thing here: Write an 8-nested if/elseif:
if (type == boolean.class /* or Boolean.TYPE - same thing */) {
return (T) "true".equals(value);
}
The type.cast part only buys you a runtime check, which is literally pointless as you already just did so with an if, thus, (T) foo is superior to type.cast(foo) here. Even though (T) thing produces a warning - ignore it, you know the warning is irrelevant. The heap corruption it is warning you about cannot happen / the type.cast wouldn't fix it.
In other words, get rid of type.cast(x) and make that (T) x and the error goes away (and a warning comes in trade; but that one you can #SuppressWarnings). The code will do what you want:
boolean v = new Literal("true").getValue(boolean.class);
But note that the system auto-boxes and auto-unboxes anyway. You can't stop that from happening unless you make a new method for it:
boolean v = new Literal("true").getBooleanValue();
Where you can implement getBooleanValue as return "true".equals(value); of course.
"I do not want the overhead of autoboxing" and "... you will be making 8 additional methods then" go hand in hand. It's why e.g. IntStream exists instead of just having a Stream<Integer>.
NB: The cast operator is used for 3 utterly unrelated things. 2 of those 3 are about assertions (is this thing type X already? If yes do nothing, if no, throw an exception / break the JVM, depending on which of the 2) - only one actually converts things, and it's primitive conversion: the thing in the () has to be a primitive type. You can't get that kind of cast here, that kind of cast fundamentally is not dynamic. Hence, no conversion can take place, hence, trying to 'cast an object to lower-case-b boolean' is an error. "cast" the operator cannot do that.
rzwitserloot already explained quite well how and why you should adjust the casting and the difference between primitives and objects.
I just wanted to give you a small executable example on top of that. You could do something like the following:
public class Literal {
private final String value;
public Literal(String value) {
this.value = value;
}
public <T> T getValue(Class<T> type) {
if (type == Boolean.class || type == Boolean.TYPE) {
return (T) new Boolean(this.value); // or Boolean.valueOf(this.value)
} else if (type == boolean.class) {
return (T) this.value;
}
// [add other type checks here, if you want]
throw new UnsupportedOperationException();
}
public boolean getBooleanValue() {
return new Boolean(this.value); // or Boolean.valueOf(this.value)
}
/** This method is just here for demo purpose */
public static void main(String[] args) {
// Use it like this
Boolean obj = new Literal("true").getValue(Boolean.TYPE);
Boolean obj2 = new Literal("FALSE").getValue(Boolean.TYPE);
boolean primitive = new Literal("true").getValue(boolean.class);
boolean primitive2 = new Literal("FALSE").getValue(boolean.class);
System.out.println(obj); // true
System.out.println(obj2); // false
System.out.println(primitive); // true
System.out.println(primitive2); // false
// Or this
boolean primitive3 = new Literal("true").getBooleanValue();
System.out.println(primitive3); // true
}
}
In Java, consider the following piece of code:
int myPrimitiveInt = 5;
Integer myObjectInt = 4;
Object fromPrimitive = myPrimitiveInt;
Object fromObject = myObjectInt;
System.out.println(fromPrimitive.getClass());
System.out.println(fromObject.getClass());
System.out.println(int.class);
And the output:
class java.lang.Integer
class java.lang.Integer
int
What I would like, is a way to also get the output int for the first println.
WHY?, you will ask. Well, for one thing, I would just like to know if something like this is even possible.
But the actual practical reason behind this is an abstraction layer for testing private methods with primitive type arguments via reflection. The minimal code:
package testing;
import java.lang.reflect.Method;
public class Testing {
private static void doStuff(int a) {
System.out.println("primitive: " + ((Object) a).getClass());
}
public static void main(String[] args) throws ReflectiveOperationException {
Reflect.reflect(Testing.class, "doStuff", 10);
}
}
abstract class Reflect {
static Object reflect(Class<?> clazz, String methodName, Object arg) throws ReflectiveOperationException {
Method method = clazz.getDeclaredMethod(methodName, arg.getClass());
method.setAccessible(true);
return method.invoke(null, arg);
}
}
The output:
Exception in thread "main" java.lang.NoSuchMethodException: testing.Testing.doStuff(java.lang.Integer)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at testing.Reflect.reflect(Testing.java:17)
at testing.Testing.main(Testing.java:11)
Expected output:
primitive: class java.lang.Integer
Or even better (if possible at all):
primitive: int
Note: I know I can do clazz.getDeclaredMethod(methodName, int.class). The whole point of this post is to make this procedure more abstract. Please do not give me answers suggesting to pass the argument types to the reflect method!
What happens when you write Object x = 10
The int is autoboxed, which makes it into an Integer with value 10.
Why can't this be detected afterwards
Because there is no difference between the Integer with value 10 that was autoboxed and another Integer with value 10
How can I get around this
You need to add separate methods to overload for primitive values, these can handle the primitive values, so they do not get autoboxed.
A primitive type is never "cast" to an object.
A primitive may be "autoboxed" into an object, but you can never determine this in code, since autoboxing is just code that is added by the compiler and is indistinguishable from the same code that you might have added by hand.
I have the following generic test class:
public class BrokenGenerics<T> {
private T[] genericTypeArray;
public BrokenGenerics(T... initArray) {
genericTypeArray = initArray;
}
public void setArray(T[] newArray) {
genericTypeArray = newArray;
}
public T get(int idx) {
return genericTypeArray[idx];
}
public Class getType() {
return genericTypeArray.getClass().getComponentType();
}
public static boolean breakThis(BrokenGenerics any) {
any.setArray(new B[]{new B(2)});
return false;
}
public static void main(String[] args) {
BrokenGenerics<A> aBreaker = new BrokenGenerics<A>(new A("1"));
System.out.println(aBreaker.get(0));
System.out.println(aBreaker.getType());
breakThis(aBreaker);
System.out.println(aBreaker.get(0));
System.out.println(aBreaker.getType());
}
private static class A {
public String val;
public A(String init) {
val = init;
}
#Override
public String toString() {
return "A value: " + val;
}
}
private static class B {
public int val;
public B(int init) {
val = init;
}
#Override
public String toString() {
return "B value: " + val;
}
}
}
When I run it, I get this output, and no errors:
A value: 1
class BrokenGenerics$A
B value: 2
class BrokenGenerics$B
Now, I understand why this compiles; it can't know at compile-time that breakThis is being passed a generic of a bad type. However, once it runs the line any.setArray(new B[]{new B(2)});, shouldn't it throw a ClassCastException (NOTE THAT IT DOES NOT! Try it yourself!) because I'm trying to pass a B[] to a method that expects an A[]? And after that, why does it allow me to get() back the B?
After Type Erasure, T will be turned into Object since you didn't specify a bound on T. So, there is no problem at runtime assigning any type of array to genericTypeArray, which is now of type Object[] or calling the function setArray(...), which now also accepts an argument of type Object[]. Also, your get(...) method will simply return an Object.
Trouble starts when you access elements in the array with a wrong type expectation, since this might lead to (implicit or explicit) illegal type casts, for example by assigning the value returned by get(...) to a variable of type A.
You can also get a run-time ClassCastException if you try to type-cast the array itself, but, in my experience, that is a case that tends to come up less often, although it can be very obscure to find or even understand if it does happen. You can find some examples below.
All generics-checking happens only at compile-time. And if you use raw types, these checks can not be performed rigorously, and thus the best the compiler can do is to issue a warning to let you know that you are giving up an opportunity for more meaningful checks by omitting the type argument.
Eclipse with its standard settings (and probably the java compiler with the correct flags) shows these warnings for your code:
"Class is a raw type" where you define getType() (somewhat unrelated to your question)
"BrokenGenerics is a raw type" where you define breakThis(...)
"Type safety: The method setArray(Object[]) belongs to the raw type
BrokenGenerics" where you call setArray(...) inside breakThis(...).
Examples for causing ClassCastException due to illegal type-cast of the array:
You can get ClassCastExceptions at runtime if you expose the array to the outside world (which can often be a dangerous thing to do, so I try to avoid it) by adding the following to BrokenGenerics<T>:
public T[] getArray() {
return genericTypeArray;
}
If you then change your main method to:
BrokenGenerics<A> aBreaker = new BrokenGenerics<A>(new A("1"));
A[] array = aBreaker.getArray();
System.out.println(array[0]);
System.out.println(aBreaker.getType());
breakThis(aBreaker);
array = aBreaker.getArray(); // ClassCastException here!
System.out.println(array[0]);
System.out.println(aBreaker.getType());
You get the ClassCastException at runtime at the indicated position due to a cast of the array itself rather than one of its elements.
The same thing can also happen if you set the variable genericTypeArray to protected and use it from code that subclasses your generic class with a fixed type argument:
private static class C extends BrokenGenerics<A> {
public C(A... initArray) {
super(initArray);
}
public void printFirst() {
A[] result = genericTypeArray; // ClassCastException here!
System.out.println(result[0]);
}
}
To trigger the exception, add the following to you main method:
C cBreaker = new C(new A("1"));
cBreaker.printFirst();
breakThis(cBreaker);
cBreaker.printFirst();
Imagine this case coming up in a bigger project... How on earth would you even begin to understand how that line of code could possible fail?!? :) Especially since the stack trace might be of very little help trying to find the breakThis(...) call that is actually responsible for the error.
For more in-depth example cases, you can take a look at some tests I did a little while back.
shouldn't it throw a ClassCastException because I'm trying to pass a B[] to a method that expects an A[]?
No. As this post explains, your invocation of setArray in
public static boolean breakThis(BrokenGenerics any) {
any.setArray(new B[]{new B(2)});
return false;
}
is done on a reference expression of the raw type BrokenGenerics. When interacting with raw types, all corresponding generic parameters are erased. So setArray is actually expecting a Object[]. A B[] is a Object[].
why does it allow me to get() back the B?
Assuming you're asking about this
System.out.println(aBreaker.get(0));
PrintStream#println(Object) expects an Object, not an A. As such, there is no reason for the compiler to insert a cast here. Since there is no cast, there is no ClassCastException.
If you had instead done
A a = aBreaker.get(0);
or had a method like
void println(A a) {}
...
println(aBreaker.get(0));
then these would cause ClassCastException. In other words, the compiler will insert a cast (checkcast) anywhere a type needs to be converted from a generic type parameter. That was not the case with PrintStream#println.
Similarly,
System.out.println(aBreaker.getType());
doesn't even involve the generic parameter declared in BrokenGenerics
public Class getType() {...}
and also returns a value of the raw type Class. The compiler has no reason to add a checkcast to A.
We have Integer class in JAVA, but I couldn't find any equivalent class in C#? Does c# have any equivalent? If not, how do I get JAVA Integer class behavior in c#?
Why do I need this?
It is because I'm trying to migrate JAVA code to c# code. If there is an equivalent way, then code migration would be easier. To addon, I need to store references of the Integer and I don't think I can create reference of int or Int32.
C# has a unified type system, so int can be implicitly boxed into an object reference. The only reason Integer exists in Java is so that it can be converted to an object reference and stored in references to be used in other container classes.
Since C# can do that without another type, there's no corresponding class to Integer.
Code migration won´t work out of the box for any type of language without any manual changes. There are things such as a class Integer that simply does not exist within (C# why should it anyway, see recursives answer), so you´d have to do some work on your own. The nearest equivalent to what you´re after is Int32 or its alias int. However you may of course write your own wrapper-class:
public class Integer
{
public int Value { get; set; }
public Integer() { }
public Integer( int value ) { Value = value; }
// Custom cast from "int":
public static implicit operator Integer( Int32 x ) { return new Integer( x ); }
// Custom cast to "int":
public static implicit operator Int32( Integer x ) { return x.Value; }
public override string ToString()
{
return string.Format( "Integer({0})", Value );
}
}
The beauty of C# is that it has a unified type system. Everything derives from object, even primitive types. Because of this, all keywords are simply aliases for a corresponding class or struct. Java does not use a unified type system, so a separate Integer class is required to wrap the int primitive. In C# int is synonym for the Int32 struct.
What you're looking for has been right in front of you the whole time. Start using the dot notation directly on the int keyword (i.e. int.whatever()) to access the all goodness of the .NET version of the Javian Integer class.
I did some testing with Nullable types in a console application and it appears that they do not behave as you wish. For example:
static void Main(string[] args)
{
int? x = 1;
Foo(ref x);
Console.WriteLine(x);//Writes 2
}
private static void Foo(ref int? y)
{
y += 1;
var l = new List<int?>();
l.Add(y);
l[0] += 1;//This does not affect the value of x devlared in Main
Console.WriteLine(l[0]);//Writes 3
Console.WriteLine(y);//writes 2
Foo2(l);
}
private static void Foo2(List<int?> l)
{
l[0] += 1;
Console.WriteLine(l[0]);//writes 4
}
But if you roll your own generic class to wrap primitive/value types for use within your application you can get the behavior you are expecting:
public class MyType<T>
{
public T Value { get; set; }
public MyType() : this(default(T))
{}
public MyType(T val)
{
Value = val;
}
public override string ToString()
{
return this.Value.ToString();
}
}
static void Main(string[] args)
{
var x = new MyType<int>(1);
Foo(x);
Console.WriteLine(x);//Writes 4
}
private static void Foo(MyType<int> y)
{
y.Value += 1;
var l = new List<MyType<int>>();
l.Add(y);
l[0].Value += 1;//This does affect the value of x devlared in Main
Console.WriteLine(l[0]);//Writes 3
Console.WriteLine(y);//writes 3
Foo2(l);
}
private static void Foo2(List<MyType<int>> l)
{
l[0].Value += 1;
Console.WriteLine(l[0]);//writes 4
}
int, int? and System.Int32 are all struct and thus value types and does not compare to Java's Integer wrapper class which is a reference type.
System.Object class though a reference type can cause issue as boxing creates immutable object. In short, you can't alter a boxed value.
int a = 20;
Object objA = a; //Boxes a value type into a reference type, objA now points to boxed [20]
Object objB = objA; //Both objA & objB points to boxed [20]
objA = 40; //While objB points to boxed [20], objA points to a new boxed [40]
//Thus, it creates another ref type boxing a 40 value integer value type,
//Boxed values are immutable like string and above code does not alter value of previous boxed value [20]
Console.WriteLine($"objA = {objA}, objB={objB}");
//Output: objA = 40, objB=20
What exactly corresponds to Java's Integer is a custom generic wrapper class.
int a = 20;
Wrapper<int> wrapA = new Wrapper<int>(a);
Wrapper<int> wrapB = wrapA; //both wrapA and wrapB are pointing to [20]
wrapA.Value = 40; //Changing actual value which both wrapA and wrapB are pointing to
Console.WriteLine($"wrapA = {wrapA}, wrapB={wrapB}");
//Output: wrapA = 40, wrapB=40
Console.ReadKey();
Implementation of the wrapper class is given below:
public class Wrapper<T> where T : struct
{
public static implicit operator T(Wrapper<T> w)
{
return w.Value;
}
public Wrapper(T t)
{
_t = t;
}
public T Value
{
get
{
return _t;
}
set
{
_t = value;
}
}
public override string ToString()
{
return _t.ToString();
}
private T _t;
}
As pointed out in other answers, C# has a unified type system so everything derives from object. If you need to handle null values then use int? to specify that the integer object can be null.
c# have a integer type called int link is here
https://msdn.microsoft.com/en-us/library/5kzh1b5w.aspx
Here is a table of primitive types and their equivalent wrapper class.
Primitive type Wrapper class
============== =============
boolean Boolean
byte Byte
char Character
float Float
int Integer
long Long
short Short
double Double
I would like to create a method that would convert any given primitive variable into an appropriate class. I have tried something like below, but that obviously does not work. Any help would be appreciated:
public static <T> T forceBox(T t) {
switch (T) {
case boolean.class : return new Boolean(t);
case int.class : return new Integer(t);
// etc
}
}
the caller code looks like:
int x = 3;
System.out.println("x wrapper type: " + forceBox(x).getClass());
Though this is completely unnecessary in most cases, just use
public static <T> T forceBox(T t) { // compiler will add the conversion at the call site
return t;
}
Though you can also just use
Object o = <some primitive>;
The conversion is already done when needed as part of the boxing process.