//************************************************************// //*******Object Superclass (cont.) - October 7th, 2016*******// //**********************************************************// -(for real this time) -Every class you write in java is part of a class hierarchy/ framework, and ALL classes inherit from a class called "Object" -Stored in java.lang.Object; since it's in java.lang, is automatically imported wherever it is -Object HAS some default methods, but many of them are meant to be overridden (e.g. toString, equals, hashCode, etc.) -Java will automatically call toString whenever we try to print an object; how does it know every class has a toString method? Because EVERY class inherits from object, which has a toString method. -Clone() method exists, but should NEVER be used (read Joshua Block) -Finalize() is helpful in some scenarios (runs code before destroying object), but is only used very rarely, so we won't go over it -So, we have a class "Animal" that "is-a" Object, and a class "Mammal" which is-a Object -By default, the .equals() method checks for identity equality, or "ALIASING"- Java checks to see if two objects have the same memory address -When should a class override this method? -When logical equality, or VALUE EQUALITY, is needed (e.g. checking if 2 dates stored in different objects are the same) -When classes don't use "instance control" (class checks that there's only one instance of a class (like a singleton)) -When the equals method for the superclass isn't suitable -In this class: ALMOST ALWAYS need to override the .equals(). -More importantly, we need to know not just "when", but HOW to override this -SIDE NOTE: ALWAYS use .equals(), unless you're testing for identity equality or working with primitives (otherwise, you can be making a dangerous assumption about how the equality ) -SIDE NOTE 2: KNOW OPERATOR PRECEDENCE! print("truth value : " + n == q ) will just print "false", since the == operator has precedence and will operate at the end -SIDE NOTE 3: When initializing a string with the same text as a pre-existing string, Java will just make the new string an alias of the old one, unless instantiated via String n = new String("coolString"); -For Comparable interface: we'll get to it later, but don't use it for now -In the Java documentation, the .equals(Object n) method should define "an equivalence relationship", which satisfies the properties: -Reflexivity: every object is equal to itself -Symmetry: A = B is the same as B = C -Transitive: A = C and B = C, then A = C -Consistent: If A and B don't change, then the same result should be given - a.equals(null) should ALWAYS return false (as otherwise, a is null and doesn't have an equals method) -e.g. we have a "Person" class, and we follow the recipe of: -Check object is not null -Check if we're comparing the object to itself -Check that the object is an "instanceof" the class we're using (return false if not true) -BE AWARE that this will return true if the object is a subclass of the current class -Cast the object to the type we want -Check the "significant" fields for the other object to determine if the two objects are equivalent -We follow this for ALL of our equals methods (for now...) -So, we would end up with this for the Person class: @Override public boolean equals(Object other) { if(null == other) {return false; } if(this == other) {return true; } if(!(other instanceof Person)) {return false; } return ((Person)other).getName().equals(this.name); } -Arrays are fixed collections of a fixed size and single type -ArrayLists are dynamically-allocated, and automatically resizes to fit objects -Uses multiple arrays behind the scenes, but we can just use it as a resizeable list e.g. ArrayList tasks = new ArrayList(); tasks.add("Eat"); -The "contains()" method in collections (not just ArrayLists) uses the "equals" method in the stored object to find if an object is in the list; the default implementation rarely works right off the bat for this -Note that ArrayList is a "generic" typed collection; by default, we can use it, but it will throw a warning if we don't give the ArrayList a specific type (by default, uses the "Object" type) -Override equivalence: -You want to override a method in a subclass; the method MUST have the EXACT same name, EXACT SAME parameter list, and a covariant return type -"Covariant return type? Gee, what's that?" -Means that it has to return either the same class OR a subclass of the return type as the original class -"Return type of equal or lesser hierarchy to the original return type" -Practically, returning subclass is rare, but occasionally useful -If EVERYTHING ELSE is the same except the return type/method body, then it won't compile (even as overloading) -Overloading is only when the parameter list is the only thing that has changed -Trying to override method in same class as the original method freaks the compiler out (WHICH ONE IS REAL AGGGGHHHHHH), so don't do it -Make sure to use @Override, as it is easy to OVERLOAD a method instead of actually overriding it -Static abstract classes: can call the static methods on the class directly w/o instantiation, but really, no one actually does this -Can we instantiate a static class? WHO KNOWS! (Taylor didn't know) -Won't be questions on exceptions (even if they're on the practice test) -Enums: can do some crazzzzzzy stuff with them (enum constructors, methods, etc.), but for this class, they're just numbers w/ names -Values given in order (0, 1, 2, 3, ..., n) -If more interested, Oracle has a great tutorial on Enums (...I got bored and went on a really awful poetry tangent in the margins of a paper I'll probably need later)