This handout will list frequently encountered questions about the Java language. This page will focus on issues that fall between purely syntactic issues and deep conceptual issues. (Please see a Java reference for the former and your TA or the Assignment Q & A for the latter.) If you have a Java language question not easily answered by a Java reference, please look here! As with the Assignment Q & A section, you may also want to refer to this page occasionally to be warned about potentially confusing issues in advance.
Contents:
SuperFoo myFoo = new Foo(); myFoo.staticMeth();Because static method calls are resolved by compile-time type, in this case, SuperFoo's implementation of staticMeth() will be invoked. This is because the compile-time type of myFoo is SuperFoo. The lesson to be learned here is to always invoke static methods by 〈Classname〉.〈method-name〉.
public class Test { public static int _myInt = 1; public static int foo() { return _myInt; } } public class Test2 extends Test { public static int foo() { _myInt++; return _myInt; } } public class TestDriver { public static void main(String args[]) { System.out.println(Test.foo()); System.out.println(Test2.foo()); System.out.println(Test.foo()); } }produces the following behavior:
sicp-19>rhlee~/cse331% java TestDriver 1 2 2This is because the superclass and all of its subclasses share the same copy of all static members.
A brief description of the different keywords:
public
- all classes are able to view this
constructor/method/field.
protected
- only subclasses and other classes in the
package are able to view this constructor/method/field
private
- this constructor/method/field is not
visible outside of this class.
The default access in java is "package visible (default-access)". This access level grants package-only access to the constructor/method/field.
You should always be careful to not expose more of your implementation than necessary, and you should always keep in mind the design trade-offs involved in using each level of visibility.
If you're still not sure about when each type of visibility is appropriate, please ask your TA.
cannot resolve symbol symbol: constructor Route () location: class hw2.Route public ElementaryRoute(GeoSegment gs) { ^
Keep in mind that if you do invoke super(...), it must be the first statement in your subclass's constructor. Also, if you define a class but declare no constructors, an implicit zero-argument constructor (which does nothing) is created for you. However, if you declare any constructors, there is no implicit zero-argument constructor.
Foo f[] = new Foo[20];
The length of an array is stored in a public final (read-only) field:
int size = f.length;
You cannot directly resize an array. In order to grow an array, you must create a new one of the desired size and copy the old elements over. You can copy the elements with System.arraycopy(). An example:
Foo temp[] = f; // 'temp' now points to the old array. f = new Foo[f.length*2]; // Make f a new array that's twice as large. System.arraycopy(temp,0,f,0,temp.length); // Copy old values back over.
Please see what the Java Languge Spec has to say about arrays, and speak with a TA if you're still confused.
java.util.List
(Vector
, ArrayList
, LinkedList
,
etc.) that I know is populated by a bunch of Foo
objects.
Is there an easy way to get a Foo[]
array without
stepping through the whole array and casting?
java.util.List
interface
defines a toArray(Object[])
method which takes as an
argument, the array into which the elements of this list are to be
stored, if it is big enough; otherwise, a new array of the same
runtime type is allocated for this purpose. Because we pass in the
array with that was created with the correct runtime type, it is safe
to cast the return value directly to the typed array.
For example:
//Vector fooVect is populated with Foo objects Foo[] fooList = new Foo[fooVect.size()]; fooList = (Foo[])fooVect.toArray(fooList);
(In Java, the hash code you generate can be any integer, but, based on the capacity of the hash table (which is maintained automatically), Java will take the modulo of your hash code to map it to an entry in the hash table.)
However, there is a many-to-one mapping from keys to hash codes, so knowing a hash code does not necessarily give you a single entry. Also, if many keys map to the same hash code, we'd have to search through all the keys associated with that hash code to find our desired entry; this would deny us our constant time search. (In the worst case, all keys might map to the same hash code, resulting in a simple list.) Thus, we want to try to write a hash function which trys to prevent collisions, mapping different keys to different hash codes whenever possible.
The basic tenets of hash tables:
About good vs. bad hash functions: Let's say your key is an ordered pair, (x,y). A worst case hash function would always return, say, 1. A better hash function might return x+y. In that case, (1,4) and (2,3) would still hash to the same code. An even better hash function would be x+1123*y, which would reduce the number of probable collisions even more. (We multiply by a prime number so our efforts aren't negated when Java takes a modulo. There's a lot more nuiance regarding hash functions that are beyond the scope of this Q & A.)
Hash tables are implemented via the HashMap class. The older Hashtable class is still around, but is slower, and you should use HashMap for most purposes.
Please see the spec for Object.hashCode(), which explains the restrictions for your implementation of hashCode(). While you're at it, please see the spec for Object.equals(Object), which explains the restrictions for your implementation of equals(). You must be sure to implement equals() correctly or your class will not work properly as a hash table key.
This is a very precusory primer to hash tables. If you would like to know more about them, please speak with your TA.
A: In Java, we frequently come across situations where two Objects must be compared to each other, such as when needing to implement sorted data structures (just like in getBallsFromSmallest()). The Java standard library has two methods for automatically comparing Objects together in these data structures: Comparable<T> and Comparator<T> (in each case, T is the class that you want to compare). While these both achieve the same thing, they go about it different ways.
Comparable<T> is an interface that you can add to any class you have edit access to (or, I suppose, any non-final class if you're okay with inheritance). The Comparable<T> interface adds a single method, compareTo(), which each of your instantiations of T gets. Whenever one of your Ts gets added to a sorted collection<T>, its compareTo() method is called against all other Ts it is compared against.
Good times to use Comparable<T> are when your class must always compare against itself the same way, or you don't want to define an entirely new class just to run comparisons. However, it does require editing the original T class, which is not always possible (or, with the case of Ball, recommended). In those cases, a Comparator<T> must be used.
The Comparator<T> interface is an interface designed to create a type of class called a function object (I believe, I don't have access to my copy of The Pragmatic Programmer at the moment). Function objects are a trick of using interfaces to basically gain some degree of first order functions (a function that can be passed as an argument).
So that's what a Comparator<T> is. How do you implement it? Unlike Comparable<T>, when you use Comparator<T> you make an entirely new class, containing only the method compareTo(T other). In the case of getBallsFromSmallest(), you would make a new class called something like BallSorter that implements Comparator<T>, and just use a regular compareTo() method like you would if you were using Comparable<T>. Then, when you construct a sorted data structure, you can simply pass the Comparator<T> in the constructor and the data structure will use that class's compareTo() method.
Of these two ways of comparing objects, which is the best? If you have edit access to the class and don't want to go through the hassle of creating a basically throwaway class that contains only a single method, use Comparable<T>. If you can't or shouldn't edit the class (such as with Ball), use a Comparator<T> and pass it to your data structure when you construct it.
Back to Conceptual Info
Back to the CSE 331 home page.