If you go to a language like python then everything is an object, including numeric literals. I suspect the Java creators did not go that route because it becomes more difficult to maintain performance, and perhaps because they were trying to create a language that would be familiar to C/C++ programmers.
Variables of a primitive type (one of: byte, short, int, long, char, boolean, float, double) simply directly contain the value of the specified type.
Any other kind of variable is a reference variable: it contains a reference to an object (conceptually, the variable contains the address of where the object is in memory).
Java has primitive variables mainly for efficiency; because the variable contains the value directly, they are more efficient to work with than reference variables. When you need to do anything with an object, there's always an extra step that the CPU has to perform: it has to lookup the object in memory before it can do anything with it.
As Jude already mentioned, there are also wrapper classes for each of the primitive types, for example int -> java.lang.Integer, long -> java.lang.Long etc. These are necessary because in some places you can only use objects and not primitive types (for example, collections can only store objects). you should only use those wrapper classes if it's really necessary, because they are less efficient than primitive types.
Mike. J. Thompson wrote:I suspect the Java creators did not go that route because it becomes more difficult to maintain performance, and perhaps because they were trying to create a language that would be familiar to C/C++ programmers.
In principle, they could have designed the Java programming language in such a way that for the programmer, there wasn't such a visible distinction between primitive types and objects. Newer languages, such as Scala, make it look like everything is an object, but under the covers they compile down to efficient primitive types.
So, the distinction between primitive types and reference types ultimately comes down to a design choice that the people who invented Java took long ago. It's not because of some fundamental technical principle.
From the practical point of view - some languages, like Scala for example, make them all objects (i.e. they simply hide primitives from you giving you only wrappers). But this is more memory- and time-consuming surely, though coding is sometimes simplified.
Java has two kinds of variables: variables of a primitive type, and reference variables.
Actually, more to the point, Java has 2 kinds of object types. Primitive objects and class (instance) objects. Whether they ever get actually assigned to variables or not is sort of secondary.
The idea that certain items would be "magical" was a basic design decision that I'm not sure everyone thought was a good idea at the time, although the precise arguments are unknown to me.
I'm fairly sure that Smalltalk, which is the seminal OOP language made its numeric and character types behave with object semantics. I know that FORTH did, because I once redefined the number 9 as 123 just for giggles.
In practice, having 2 kinds of objects (3, if you consider arrays) has certain consequences. Literal values cannot have class methods invoked on them, because they're not derived from java.lang.Object. Expression processors have to consider both primitive and class object operands (and more recently, the auto-boxing of primitives) Stuff like that.
There have been occasional rumors that a forthcoming Java version may make primitives more class-like. Auto-boxing was certainly a step in that direction.
Tim Holloway wrote: . . . I know that FORTH did, because I once redefined the number . . .
So you can prove that 2 + 2 = 5.
Less than a minute ago, Campbell's Computer wrote:RVM_FORTH HI L operations.fth
UoT Formal Methods and Programming Research Group
Reversible Forth vsn 1.0. Built on campbellsComputer
Mon Oct 27 15:32:30 GMT 2014
: 5 4 ; 2 2 + 5 = booleanPrint trueok
I am not convinced that 2 behaves as an object, nor 5. It is the token 5 which behaves as an object, more likely. Maybe if you declare a named variable that variable behaves as an object, like this:-
I know that passing the token 5 (before redefining it) puts the value 0000_0000_0000_0000_0000_0000_0000_0101 onto the stack. So I think that 5 is a primitive, because the data representation is actually 5. Bill who designed reversible FORTH says it supports three kinds of primitives, INT FLOAT (=64‑bit IEEE754 number) and STRING, but I disagree. The FLOAT and STRING datatypes are put on the stack as pointers/addresses, so I think they count as nearer objects than primitives.
2 VALUE i i i + 5 = booleanPrint trueok
In the current implementation, STRING is a UTF‑8 null‑terminated String pointer a bit like in C.
Somebody told me to search for Project Valhalla the other day. I did and they have plans to make primitives behave like an intermediate form between objects and the current primitives. I shall be interested to see that in real life; it looks good.
Tim Holloway wrote: . . . There have been occasional rumors that a forthcoming Java version may make primitives more class-like. Auto-boxing was certainly a step in that direction.
I may be mistaken but I think C# has moved onto that sort of footing several years ago.
You can call methods on literals.
but not on number literals because the String literal is an object in its own right, whereas the number literals are not objects at all. You can cast number literals to Object which will force boxing.
They're also looking at allowing primitive types in generics, so a List<int> will be allowed. That will also reduce the need for boxing, and will probably reduce the number of cache misses.
Rodion Gork wrote:From the practical point of view - some languages, like Scala for example, make them all objects (i.e. they simply hide primitives from you giving you only wrappers). But this is more memory- and time-consuming surely, though coding is sometimes simplified.
No, languages like Scala only make them look like objects - but the compiler uses primitives behind the scenes. Class Int in Scala is, under the covers, really a primitive Java int. It's not more memory- or performance-intensive than a primitive int.