CSC300: Video [1/23] Previous pageContentsNext page

This lecture is semi-optional. You should watch it, but it will not be on exams.

Open Playlist

when you start working with objects in a programming language things start to get complicated for example what does it mean for two objects to be the same what does it mean to even have a printable form of an object let's look at an example in Java I'm going to take two arrays x and y and I'm just gonna draw out what the state of the machine looks like you can see here a picture where I have my main program with three variables of course the args array which is empty and then the two arrays I've declared x and y each of these has integer values in them 11 21 31 and the question I'm asking is are these equal and of course the answer here is both yes and no are they the same object no they're not but do they contain the same values yes they do Java gives us ways to answer this question in both forms first of all we have the equals operator in Java the equals operator always tests object identity at object types Java also provides us with an equals method and the equals method does different things depending upon the type of object that we're looking at for arrays the equals method is identical to the equals operator and therefore in this case you can see the equals method regardless of how it's invoked is going to give me false just like the identity does Java also provides a notion of equality for arrays which will check the values in the array that's called arrays dot equals and that finally we'll say that these two arrays are the same you can see even when I go to print an array I may not get what I expect you can see here I'm printing x and y I'd expect to get the eraser but what do I get I get some rubbish what does this mean well this is indicating to us the type of the object it's an array of integers and then it's printing out something called its hash code which more or less you can imagine is somehow related to its position in memory and you can see that these two objects are indeed at different positions in memory but they do contain the same values so eventually we can find some notion of equality which will equate them what's going on here is the equal operator in Java checks object identity on object types that is the two operands refer to the same object or even more concretely the two operands evaluate to the same address in memory unlike some other languages you cannot change the meaning of any operator in Java and therefore this double equals or the equal operator always means identity at object types but objects also have an equals method and the behavior of the equals method can vary from class to class the default method which is defined at java.lang object it is just like identity but some of the built-in classes override this to check value equality rather than object identity Java also provides some handy utilities such as the utilities in Java util objects if you want to see the code related to these you can actually find it in eclipse what you can do here is pull up the file click on the method you're interested in then go to the navigate menu and say open declaration there's also a shortcut for that and eclipse will open up the source file containing that method declaration you can see what equals does here it's using the short-circuit or operator remember the or operator here will only evaluate the right hand side if the left hand side is false so in this case we're checking first if a is equal to B those are our operands so if a and B are the same we'll return note that that will work also if and B are both null so if a and B are both null they'll be the same and so we'll return if they're not equal at least one of them must be non null so what happens is we check for the nullity of a if a is not null then we can simply return the result of calling the equals method of a on argument B in the case that B is null the equals method will always return false you can see the asymmetry of the dot equals method by looking at how it behaves with respect to null suppose I have an object that holds some value and I have a null reference I can definitely ask does the object equal null and the answer will always be no however if I reverse the question I'll get a null pointer exception because X is null objects dot equals is a safer method because it checks for nullity of both of its parameters Java provides a top-level class called object and you can instantiate new objects they don't mean very much and they don't have very many interesting fields but we can actually check them to see if they are the same object or if there's somehow equals to each other and you can see here that objects in the object class are compared with the equals method in the same way we compare object identity what about strings here I have two variables x and y initialized to the same string literal and you can see that these are actually going to refer to the same object therefore in addition to being equal these are identical objects if I use the string constructor I'm guaranteed to get a new object each time I call the constructor and therefore in this case I will have separate objects for x and y those are not identical but they are equal the java string class overrides equality to compare the value of the two strings so what's going on here why do I get two objects in one case but only one object in the other maybe it's because I'm using a string literal here and I'm assigning to them to the same thing let's try doing an operator between two strings in this case I'll use the concatenation operator you can see from the output that even if I build a string using an operator such as concatenation it's possible for Java to generate references to the same object for different expressions how does this happen it turns out that Java literals are interned and whenever a operation on strings happen in Java Java interns the resulting string interning is an operation which tries to find a canonical representative of a given string so looking here at this program you can see a and B are constructed as new string objects when I in turn a it will give me a reference to the canonical string object for that particular string and note that if I in turn B I'll get a reference to the same object and therefore those two are identical Java in turns strings to improve performance and decrease memory consumption unlike Python Java also has the concept of a base type like int and intz are dealt with differently from object types for base types the value of the type is stored directly in a variable so my main method here has three slots one for X 1 for Y 1 for args args holds a pointer to an object a reference to an object but x and y don't they hold values directly this is the binary representation of the number 3000 and you can see when I test for equality here on base types Java is always just checking whether not the two values are the same for each base type Java provides a corresponding object type for intz the corresponding type is integer if you assign an int value into an integer Java creates an object for you in this example I've done two such assignments and Java has created two objects note that the objects are independent in this case the conversion from a base type to an object type is called boxing the idea here is that instead of having my gift I have a box that contains the gift that's the reference to the number so hello here does not actually hold on directly to the numbers 3000 like it did with base types instead it has a reference to those numbers and those numbers themselves are stored in objects these are thought of as boxes if someone gives you a present the first thing you're going to want to do is unwrap it and that's what the unboxing operations do for integer values the unboxing operation is called int value we can take the int value and store it Java does boxing and unboxing automatically so you usually do not have to call the int value method explicitly Java provides an object class or wrapper class for every base type in the language we are mostly going to be using int and doubles but the other six types of the language also have these wrapper types to convert from an INT to an object Java uses integer value of to convert from an object back to an int Java uses the integer int value method all modern languages have a notion of boxed and unboxed types but they vary slightly from language to language you can see a couple of other approaches listed here one thing that may be surprising is that when you box a based you don't always get a new object for example integers close to zero are treated kind of like strings in Java where we intern them we're picking a canonical representative for those small integers this is done for efficiency and also to minimize the memory usage of a program for example if I box 30 twice I'll get the same object whereas if I box 3000 twice I'll actually get different objects what we're seeing here is the behavior of the value of operation the value of operation treats values close to zero differently from values far from zero you can see the exact limits by looking at the code in Eclipse for integer value of there is an integer constructor as well which is guaranteed to give you new objects the use of this constructor however is deprecated because it's just gonna be less efficient than using the value of method one of the guarantees of the language is that anytime you use new you will get a fresh object and therefore in this case I'm guaranteed to get different objects regardless of their values so we've seen that assigning an int value literal to an integer creates a new boxed object but the same thing does not happen if I copy a reference of an object to another reference so what's happening here is just aliasing here X&Y will now refer to the same object the assignment operation on objects always copies the address of the object from one place to another always creating an alias of this kind going back to our first example we can understand what's going on we have two separate objects x and y therefore they're not identical you can see that the equals method also says false here and that means that arrays don't do anything special for equality they're just checking identity if we want value equality we need to use another method such as arrays equals this is the same code where I've simply changed int for integer what that means is my arrays now instead of holding base values they hold references to objects the literals that I've written here are boxed to get into the integer array and since they're close to zero you can see that there Ilyas each of these two arrays refers to the same objects when we have objects that point to objects or objects that point to arrays that hold base types or objects that point to arrays that point to objects life can start to get exciting fortunately we're not gonna have to worry about these cases in this course but you should be aware that they exist we'll be satisfied to look at equality on simple object types and arrays of simple objects

Previous pageContentsNext page