shannah / Java-Objective-C-Bridge

A thin bridge that allows for two-way communication from Java to Objective-C.
123 stars 25 forks source link

Remove redundant primitive boxing in RuntimeUtils.getAsReferenceWrapper(...) #29

Closed Marcono1234 closed 3 years ago

Marcono1234 commented 3 years ago

RuntimeUtils.getAsReferenceWrapper(...) contains multiple redundant boxing and unboxing calls, e.g.: https://github.com/shannah/Java-Objective-C-Bridge/blob/473221aeef8f12ca9a659d899f3ca7092aed27ef/src/main/java/ca/weblite/objc/RuntimeUtils.java#L875

There is no need to call new Double(...).doubleValue(); same applies to all other primitive parsing methods used in that class. However, since is most cases you are assigning the result to an Object variable, it would be easiest to replace the parseX calls with the valueOf​(String) variants (e.g. Double.valueOf(String)) which already return a boxed value:

- val = new Double(Double.parseDouble((String)val)).doubleValue();
+ val = Double.valueOf((String) val);

Additionally the code checks !primitive.class.isInstance(val) and then performs val = ((Number) val).primitiveValue(), e.g.: https://github.com/shannah/Java-Objective-C-Bridge/blob/473221aeef8f12ca9a659d899f3ca7092aed27ef/src/main/java/ca/weblite/objc/RuntimeUtils.java#L822 This performs unnecessary unboxing for boxed primitives, e.g. Integer, because val is of type Object and therefore Java is automatically boxing the primitive again: Integer -> int -> Integer

shannah commented 3 years ago

I changed cases of new BoxedNumberType(...).primiteValue() to their corresponding BoxedNumberType.valueOf(...) call.

I'm not sure how to improve on cases of val = ((Number)val).intValue(); because they need to be coerced to the proper boxed type, and you can't just do something like Short s = (Short)someInteger; Either way it needs to be unboxed, then coerced to the correct primitive type, and then reboxed. Open to suggestions.

Marcono1234 commented 3 years ago

Sorry, I just noticed that the constructors which are called have the respective primitive as parameter. Therefore the parsePrimitive(...) methods are appropriate. Regarding val = ((Number)val).intValue(); I only meant the case where val is already an Integer, for every other Number this call is indeed needed. However, the int value can directly be used (as pointed out above), so calling intValue() is fine.

Additionally I completely missing that the Class.isInstance checks are impossible for primitive classes (because Object is never a primitive).

I have fixed these issues in #35.

Marcono1234 commented 3 years ago

This has been fixed with the merge of #35.