Should primitive types or non-primitive types be preferred in Java interfaces?

(I thought I once read something about this in a book, but now I'm not sure where to find it. If this question reminds you of some material that you read, send the link!)

What are the pros and cons of primitives in interfaces?

In other words, one of them is preferable to the other and why? Perhaps one is preferable to the other in certain contexts?

public interface Foo { int getBar(); } 

or

 public interface Foo { Integer getBar(); } 

Similarly:

 public interface Boz { void someOperation(int parameter); } 

or

 public interface Boz { void someOperation(Integer parameter); } 

Obviously, there is a problem dealing with null in a non-primitive case, but are there any deeper problems?

+4
source share
6 answers

Primitive types should be used for efficiency and simplicity if there is no particular reason for using an object type (for example, you need null ). Using object types can lead to various subtle errors, such as erroneous comparisons, if two references refer to the same object, instead of having the same value. See how native Java libraries use primitive types other than containers that accept Object .

+10
source

I would say that for primitives there is usually no reason to use a primitive wrapper as the return type. One argument is simply memory requirements. With a primitive return value, you only need X bytes for the return value vs wrapper, where you have the service data of the object. The only place you can save is a cached value for things like Integer.valueOf (1), but for example, with an integer, this only works for values ​​-128 → 127.

While lexicore makes the correct point using null as the return value for a special case, there are many times when you can do the same with the primitve value (for example, something in the API that says: "Integer. MIN_VALUE is returned when the result cannot be scanned. "This is in many cases viable for all primitives except booleans.

There is also always the possibility of exceptions, since it can be argued that the interface should always be well defined for all possible inputs and that the input that will lead to an undefined return is an exception definition (and as such, perhaps a good case for an IllegalArgumentException).

The final solution (perhaps much less elegant) should add to the interface some method of checking the state, which can be tested after calling the method, which may not be executed as desired:

 boolean b = (interface).doFoo(); if((interface).wasError()){ //doFoo did not complete normally }else{ //do something fooish } 

where wasError can be automatically cleared in the style of the thread interrupt flag (note that this approach will be prone to errors in multi-threaded code).

+2
source

Except in rare cases where primitives are unpleasant (I had some “good” experience with CORBA), I would suggest using primitives.

+2
source

I also think about such things:

Suppose we have this type:

 public interface Foo { int getID(); } 

Then, for some reason, the ID type is entered:

 public interface Foo { FooID getID(); } 

Now suppose that some client was written before the change, and the client contains the following code:

 if (A.getID() == B.getID()) { someBehavior(); } 

Where A and B Foos .

This code would be corrupted after the change, because comparing the primitive equality ( == ) between int s, which was normal before the change, now incorrectly compares reference values, and does not call equals(Object) for identifiers.

Had getID() from the very beginning produced Integer , the correct client code would be (normal, the correct client code could be like that. Box conversions would be applied with == to make this work too):

 if (A.getID().equals(B.getID())) { someBehavior(); } 

This is still true after software development.

If the change were "reverse", in other words, if getID() originally created some type of FooID , then if it were changed to create an int , the compiler would complain about calling equals(Object) on the primitive and the client code would be fixed.

There seems to be some sense of “future verification” with a non-primitive type. I agree? Do not agree?

+1
source

Use primitives. Auto-boxing / -boning will make your int up to Integer and so on. Primitives are also allocated on the stack, not on the heap. Using wrapper classes, you use more memory and get more overhead; why do you want to do this?

+1
source

Yes. The main use you can see is the transmission of an object over a network. ** Using serialization. **

0
source

Source: https://habr.com/ru/post/1305656/


All Articles