- "Java" refers to a language, an API, and a VM. It's good to be aware of this overloading of the word so that you can see how the whole system fits together, especially with the proliferation of languages that run on the JVM.
- Java has primitive types and reference types. Primitive types are just boxes that hold values, but reference types are for objects, the fundamental building blocks of OO systems.
- All of the primitive types have similarly-named reference types. For example, there's
int
and there'sInteger
. The difference between these reveals an important insight into object-oriented software design. Whereas anint
variable is just a box that holds a value, anInteger
instance is a representation of the idea of a number. Consider the following code.
Here, x is just a box that holds an integer, and so we can sayint x = 5; Integer y = 5;
x=7
, and that means we're putting a different value in the box. On the other hand,y
is five. We cannot sayy.setValue(7)
any more than we can assert that 5=7 in mathematics. - It's good to recognize that
y=5
is not free: it's using autoboxing to convert anint
primitive into an instance ofInteger
. While it's true that premature optimization is the root of all evil, you shouldn't write code that creates unnecessary objects either. - It is critical that a Java developer builds a functionally-correct mental model of
classes, objects,static
, methods, and fields. A blog post is not the right way to help you, dear reader, to identify the problems in your own mental model. The good news is that my services are for hire. ;) - There are four access control modifiers that you should know so that you can read code:
public
,private
,protected
, and package-protected (which has no keyword). However, you should really only ever usepublic
andprivate
, so you just saved half your allocated brainspace on this topic. - To understand classes, abstract classes, and interfaces, I used an example like the following.
A few highlights of this example:public interface InningListener() { public void strikeOut(); public void walk(); public void balk(); public void beaned(); public void hit(); } public abstract class AbstractInningListener implements InningListener { public void strikeOut() {} public void walk() {} public void balk() {} public void beaned() {} public void hit() {} } public class Inning { private final List<InningListener> listeners = new ArrayList<InningListener>(); private int strikes = 0; public void addInningListener(InningListener listener) { listeners.add(listener); } public void strike() { strikes++; if (strikes==3) { fireStrikeOutEvent(); strikes=0; } } private void fireStrikeOutEvent() { for (InningListener listener : listeners) { listener.strikeOut(); } } } public class Demo { public static void main(String[] args) { Inning inning = new Inning(); inning.addInningListener(new AbstractInningListener() { public void strikeOut(){ System.out.println("Strike out!"); } }); for (int i=0; i<3; i++) inning.strike(); } }
- This is an example of the Observer design pattern.
- The abstract class provides default empty implementations of the methods in the interface so that implementors—like the one in
Demo
—can provide implementations of only those methods that they care about. This keeps the code from getting cluttered up with no-op implementations. - This pattern can be found throughout
java.awt.event
. I tend to do something a little more idiosyncratic involving inner interfaces and inner classes, but that's for another day.
- If you're doing I/O, it's good to know that the
InputStream
/OutputStream
family of classes is for byte-level I/O,Reader
/Writer
family is for character-encoded content, and thenio
libraries are for blazing fast access to hardware buffers, and so can be ignored until you need it. To me, the critical classes to know areBufferedReader
andPrintWriter
.BufferedReader
has the amazingly-usefulreadLine
method, allowing line-by-line access to a stream, and aPrintWriter
behaves exactly likeSystem.out
. - The classloader trick will load a resource from the classpath whether you are running in Eclipse, from a command-line, from an executable jar, in a servlet, or on Java WebStart:
Thread.currentThread().getContextClassLoader().getResourceAsStream("whatever.png");
- Here's a slapdash tour of the collections API:
List<T>
defines a sequence. There are two useful implementations,
LinkedList<T>
andArrayList<T>
, which come with the usual caveats implied by their names.Set<T>
defines a set, in the discrete mathematics sense.
The two common implementations areTreeSet<T>
andHashSet<T>
, but you should use the latter because you're always providing a usefulhashCode
method in all of your Java classes—or else you're doing it wrong.Map<K,V>
defines a dictionary, an associative array, a lookup table—choose your favorite mental model. Again, we haveTreeMap<K,V>
andHashMap<K,V>
, and you should use the latter and overridehashCode
in all of your classes.
- Finally, use guava.
I think that's everything we covered, except for some of the more specific questions. I hope this post is helpful to someone looking for a birds-eye view of Java. As I mentioned at the workshop, when I started using Java in 1998, there was not much to learn and there was basically one place to go to get started. Now, I imagine that novices can be easily overwhelmed by the immensity of just the standard libraries. By the way, the good news here is that the best place to go for an introduction to Java—as long as you aleady know something about programming— is still The Java Tutorials.
No comments:
Post a Comment