How "==" works on primitive types - java

I wonder how "==" operator works on primitive values. I understand that "==" checks if two references refers to the same object on heap.
But how it works in context of primitive values wihich are stored on stack?
e.g
int a = 5;
int b = 5;
I assume that these values aren't stored in the same place in memory but
a == b returns "true".
My hypotesis is that JVM treats all values stored in stack as stored in one place in memory and it returns true in case of "==".
Could you explain me this matter in a little more detailed way?
Regards

Your hypothesis is wrong. When comparing primitives there are no memory addresses in play. It's a simple instruction to compare whether a value is equal to another value, implemented in bytecode as a comparison (of a register value) and a conditional jump.

Edit: As pointed out by James and Varun, my original answer would not apply to the OP's example since an object reference is a numerical value just like an integer. So the comparison operation would actually be the same in this case.
In other languages there is something called operator overloading. Java does not support user operator overloading, but understanding how those work will give you a better idea how the same operator can use different logic depending on the context.
when you are comparing a variable and a primitive, the machine code that is produced is performing a different comparison operation than when comparing two objects. The same syntax is used because the idea of comparison is logically similar enough to warrant using the same operator symbol rather than defining a completely different symbol for the two different functionalities.

For any comparison operation, JVM looks for data type of the operands. Depending on the operand type different Java byte code instructions are used for comparison.
JVM works on two kinds of data types.
According to JVM 7 specification:
Like the Java programming language, the Java Virtual Machine operates
on two kinds of types: primitive types and reference types. There are,
correspondingly, two kinds of values that can be stored in variables,
passed as arguments, returned by methods, and operated upon: primitive
values and reference values.
References too are values of type reference.
The Java Virtual Machine contains explicit support for objects. An
object is either a dynamically allocated class instance or an array. A
reference to an object is considered to have Java Virtual Machine type
reference. Values of type reference can be thought of as pointers to
objects. More than one reference to an object may exist. Objects are
always operated on, passed, and tested via values of type reference.
For arithmetic operations on primitive and reference types, JVM uses opcodes which specify data type of the arguments along with operation.
For example,
lcmp - Compare two long values
Finally, for JVM any arithmetic operation is byte arithmetic on given operands.

Related

What are Value Types from Project Valhalla?

I've started reading about Project Valhalla and there is something I really don't understand and it's the Value Types.
This is what I understand:
1) Are objects that can't be compare it as reference?
final ValueType a = new ValueType();
final ValueType b = a;
System.out.println(a==b); returns false????
In Google AutoValue code example, it states
if(o == this){return true;}//equals method implementation what is this? I am comparing references here right?
2) According to Wikipedia, highly-efficient small 'objects' without inheritance. What do Small Objects? and Without inheritance mean?
Is this not possible using VT?
public final class ValueType extends Any //is this not possible??
3) Why are they used? Which scenario would be used and how would it be used.
4) According to Google AutoValue Library, in a nutshell, a value-typed object is an object without an identity, i.e. two value objects are considered equal if their respective internal state is equal. My question is: do they have state and should they implement equals and hashcode. What does object without an identity mean?
5) Is this assertion correct?
public static void main(final String[] args)
{
final Test clazz = new Test();
final AutoValue value = new AutoValue("Java Belongs to SUN");//Constructor Name
clazz.mutate(value);
System.out.println(value.getName()); //would print: Java Belongs to SUN??
}
private void mutate(final AutoValue value){value.setName("Java now is part of Oracle Corporation");return;}
If it is so, would JVM gain memory not tracking this Objects or Values between methods calls?
Project Valhalla is part of initial Project of Java 10 would be ready in 2018 or so.
Your final assertion is correct. The ValueType variables are entirely copied when passing them as a parameter to a function, rather than typically just getting a copy of the reference to an object. This allows you to treat a small object as if it were a value type like int or boolean.
1) Under Project Valhalla, two ValueTypes would be compared by fields directly, even for == checks, much like primitive types. With Google's AutoValue types, you would never use == directly, because that would still be an identity check.
2) Small Objects means that this should be used for objects that only have a few fields, as the whole content of the object is going to be copied repeatedly. Large objects would be better served with passes by reference.
Without Inheritance means that you won't be able to use polymorphism for Value Type objects. Because Value Types are meant to be stored directly, like primitive values, they don't include any class information, so the JVM must always be able to infer what the object is from the program itself, instead of from any information on the object. For example, an Integer field could be a Value Type member, while a Number field would have to still be by reference.
3) They are used to avoid the dereference penalty normally required for accessing an object's members. For example, with a List of Points, each Point is actually a reference to the x and y values in memory, so iterating over the list will involve many dereferences. If the Points were stored directly in the list, this would be avoided.
4) Object Without an Identity means that all that matters about the object is its value. Just as an int valued 1 should be the same as all other ints valued 1, and all Strings "hello world" are equal to all other Strings "hello world", whether or not they are actually the same object. By contrast, two ArrayLists that are both empty, while at the time equal, have identity, because they are mutable, and adding an element to one list must be distinct from adding an element to the other list.
5) Under Project Valhalla, the AutoValue, if it is a Value Object, would be immutable, so there would be no setName method to call. It would be similar to how you can never mutate 1 into 2, you instead modify where a 1 is located so that a 2 is there instead.
Source: http://cr.openjdk.java.net/~jrose/values/values-0.html
The other answers are fine, but there is one other perspective about the core point of value objects: they give you stack semantics.
Meaning: before project Valhalla, you either have primitive "objects" and
reference objects. The first ones can exist on the stack, but real objects only live on the heap.
Value objects will change that. You can have "real" objects - but their data only resides on the stack. This means that you do not have a reference (and therefore cost for de-referencing) anything - just like primitive types, the value is directly placed on the stack. But now that value can be more than just a single int, long, ... - you can have a real, "complex" object - but all its data is directly there on the stack.
And because of that, you can nicely do a == b now - because now you are no longer comparing references that point to the heap - but a and b directly have their corresponding values.
UPDATE 2019/2020, Build 14-valhalla+4-55 (2019/8/30)
Inline Class is the new name of "Value Type". According to current project state Inline Classes don't support inheritance but are able to extend interfaces. Following statement is legal:
public inline class MyInlineClass extends SomeJavaInterface {}
They do have equals, hashcode (and toString) methods. "==" operation and equals (default implementation) are same for simple case, where only Inline Classes and primitive fields are involved. But it is not true in general.
It becomes messy, if you add a classic Java Object (including String and Array) as a field inside of Inline Class. In this case "==" operation most probably won't work as expected anymore and you have to fallback to classic custom equal implementation.
Inline objects are immutable and don't support clone (clone makes no sense).
A possible usecase for Inline Classes would be complex numbers or matrix algebra, which is essential for neural networks algorithms of artificial intelligence systems.

Can a primitive value be considered an object in java?

When I started out using Java, it was implied to me that we have two different types:
Objects (strings, from classes, println, etc)
primitive values (int, double, char)
I just got back an exam from a Professor where this difference would mean the difference between two choices as answers. When I asked my professor to clarify, he told me that primitive values can be objects.
Who is right here and can anyone give me any proof?
Proof would be something official sounding and I would choose that as the answer as well as awarding you some proverbial internets.
Primitives are not objects. Which is to say, an int is not an Integer.
However, with any vaguely-recent Java compiler, a primitive can be auto-boxed as an associated object type (int autoboxes as Integer) and auto-unboxed (Integer unboxes as int), and the instances of the object types related to primitives (Integer, Long, etc.) are immutable (which is important for behaving like their primitive counterparts), and so the distinction becomes blurry. That may have been what the professor was alluding to.
That is, a method (for instance) accepting an int can be given an Integer and the compiler just handles unboxing it; similarly, a method accepting an Object (maps come to mind) can accept a primitive, and the compiler boxes it into the corresponding object type.
Can a primitive value be considered an object?
The answer is No.
The JLS states
There are two kinds of types in the Java programming language: primitive types (§4.2) and reference types (§4.3). There are, correspondingly, two kinds of data values that can be stored in variables, passed as arguments, returned by methods, and operated on: primitive values (§4.2) and reference values (§4.3).
Those are Primitive Types and Values which are
predefined by the Java programming language and named by its reserved keyword
and Reference Types and Values which can be one of
class types (§8), interface types (§9), type variables (§4.4), and array types (§10).
Note also that there is a special type which is the null type and its corresponding value the null reference
There is also a special null type, the type of the expression null (§3.10.7, §15.8.1), which has no name.
...
The null reference is the only possible value of an expression of null type.
For the primitive types the JLS has defined a mechanism called Boxing Conversion for converting them into the corresponding reference types.
Boxing conversion converts expressions of primitive type to corresponding expressions of reference type.
So since there is the need for a conversion to go from a primitive type to a corresponding reference type one cannot say that primitives can be considered as objects and vice versa. But one can say they are convertible.
There is an implicit mapping between primitives and objects, so an int can be used where an Integer is expected. It is a feature called autoboxing.
For example:
Integer foo = 4; // 4 is really an int
Also, primitives have things in common with objects. They have a Class, such as int.class.
It should also be noted that all arrays are objects.
However, the notion of Object vs primitive is one of the worst thing there is in Java. A lot of modern languages simply don't make too much difference between them, or even don't have any primitives. (In java as well, you can do everything without ever using explicitly a primitive).
ONE LINE, QUOTING THE SPEC!!!!
https://docs.oracle.com/javase/specs/jls/se8/jls8.pdf
An object is a class instance or an array.
Conclusion:
value/primitive types are __NOT__ objects.
reference/class types are objects.
Also, all objects extend class object.
And the instanceof operator does not work with value types:
int a; //:<-- int is [value/primitive] type version
//: of Integer [reference/class] type.
if( a instanceof Object ){ ... } //:<-- SYNTAX ERROR

How to test for equivalence in a generic class?

Scheme knows three different equivalence operators: eq?, eqv?, equal?. Sere here for details. In short: eq? tests references, eqv? tests values and equal? recursively tests the values of lists. I would like to write a Java generic which needs the functionality of Scheme´s equal?.
I tried to use Java´s equals() method, because I thought it does a value comparison, because for a reference comparison the == operator exists and there is no need for equals to do the same. But this assumption is completely wrong, because equals in Java is completely unreliable. Sometimes it does a value comparison and sometimes it does a reference comparison. And one can not be sure which class does a reference comparison and which class does a value comparison.
This means that equals can not be used in a generic, because the generic would not do the same for all types. And it is also not possible to restrict the generic type in a way that only types are acceptable which implement the correct value comparison.
So the question is: how to do a reliable value comparison in a generic? Do I have to write it on my own from scratch?
By the way: I think Java´s equal failure does not start with Array. It starts already with Object. I think it is wrong that equals for two objects returns false. It must return true, because if you do a value comparison of something which does not have a value the values can not differ and therefor they must be the same. Scheme does it in that way and it is perfectly reasonable: (equal? (vector) (vector)) -> #t.
In Scheme, list equivalence is based completely on the structure of the items.
In Java by comparison, equality is context-dependent depending on the type of object, and may use some or all of the internal structure in its equivalence calculation. What it means for two objects of the same type to be "equal" is up to the object type to determine, so long as the general contract for equals is met (most notably that it forms an equivalence relation with all other objects).
Assuming all types used in a program have a reasonable equals definition, they should have a "reliable" value comparison, at least in the sense of the object oriented paradigm.
Returning to the analogous Java equal? implementation. It's a bit hard to piece together from the question's phrasing, but from context clues it appears that this is also attempting to operate on lists of items. The equals method on Java's List type already implements behavior directly analogous to Scheme's equals? operation:
Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if Objects.equals(e1, e2).) In other words, two lists are defined to be equal if they contain the same elements in the same order.
This definition also means that recursive list structures also work in a similar manner as Scheme's equals? operation.
Note that the List behavior is notably different from that of Java's array type (which you mention in your question). Arrays in Java are a fairly low-level type, and do not support much of the typical object-oriented functionality one might expect. Of particular note, for equality, arrays are compared by object reference rather than by a structural comparison of the items in the array. There are ways to do sensible equality comparison on arrays using methods in the Arrays class (e.g. Arrays.equals and Arrays.deepEquals).
As an aside, to address your postscript about the equality of two bare Objects.
assert !(new Object().equals(new Object()))
From an object-oriented perspective, it is sensible that two bare objects be equal only if they're the same reference. First, as mentioned above, there is not a direct relation between an object's internal structure and its equality, so there's no need for them to be equal. There is virtually no context as to what two different instances of Object represent from a object modeling perspective, so there's no inherent conceptual way to tell that these two objects are logically the "same" thing.
In summary, assuming all the types in your list have a sensible version of equals() defined per their object's type, Java's List.equals() behaves directly analogously to Scheme's equals? operation.

Representation of references in Java

Anjelika Langer in her Generics FAQ writes the following regarding the decision for Java to go with code reuse instead of code specialization for generic types :
Code specialization is particularly wasteful in cases where the
elements in a collection are references (or pointers), because all
references (or pointers) are of the same size and internally have the
same representation. There is no need for generation of mostly
identical code for a list of references to integers and a list of
references to strings. Both lists could internally be represented by
a list of references to any type of object. The compiler just has to
add a couple of casts whenever these references are passed in and out
of the generic type or method. Since in Java most types are reference
types, it deems natural that Java chooses code sharing as its
technique for translation of generic types and methods.
So first question is it true that all references are of the same size and internally share the same representation?
If the answer is true that what properties does all the references in Java share?
So first question is it true that all references are of the same size and internally share the same representation?
Yes. (Why would you imagine that someone as knowledgeable as Anjelika Langer would get that wrong???)
If the answer is true that what properties does all the references in Java share?
They all have a type that has Object as its ultimate supertype. Hence they all provide all methods in the java.lang.Object API.

Determining available operators at runtime

I would like to be able to retrieve the available operators for an object at runtime, possibly in a similar way as the getMethod() call.
In particular, I need to be able to call the less-than/greater-than operators of an object at runtime.
Basically, I have a bunch of primitives that have been cast to the Object object-type. I need to perform comparisons between them at run-time. (I do know that the objects being compared will be of the same original type, and have implemented my own type-checking).
Alternatively.. Maybe there is a way to programatically cast these objects back to their original type, and use their native comparison operators.. somehow?
Thanks for any assistance.
There is no way in Java to get available operators. For comparison the class should (you may do this thru reflection also) implement the Comparable interface.
If they are auto-boxed primitive types, the set of arithmetic operators is identical for all types other than Boolean, and the set of bitwise operators ditto apart from the two FP types.

Categories

Resources