I've gone through a few Java questions on SO. And I must say the content here is pretty well written and the Java guys on SO can really pump out the answers.

But what I always found was Java answers for Java people. Which is great on its own, but I'm a Java noob. So I don't really care for the workings of "Joint union in type parameter variance". It's probably handy down the line but for now.. it's not.

So Java for a noob (coming from PHP and Python) what are the cheatcodes?

If you could link to an SO answer (which is probably out there but I couldn't find) or write up what are the things Java does differently than other languages? (on a basic level)

Some might call these the Java Gotchas (I couldn't find the official one though)

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
If this question can be reworded to fit the rules in the help center, please edit the question.

23 Answers
23

There's a collection of semi-official "gotchas", known as the Java Puzzlers, and documented in a book of the same name; you might also find a few screencasts on the web. Periodically, Joshua Bloch and Neal Gafter like to present a bunch of innocuous-looking challenges and proceed to systematically remove any notion you had that you understood even the vaguest basics of the Java language.

On a slightly less cynical note, if you're looking to avoid many of the common design and implementation cock-ups, you might take a look at Effective Java, by the aforementioned Joshua Bloch, which has a wealth of decent advice on how to go about designing several of the important - but frequently badly written - aspects of writing components in Java, including a comprehensive explanation of how to properly implement the contract of equals() and hashCode(), and why you should avoid clone() like the plague.

It's okay to compare strings with the == operator if you know that you're comparing string constants with string constants (or otherwise interned strings). :-) But yeah, that's not a trick for the faint of heart.
–
Chris Jester-Young♦May 5 '09 at 0:37

4

I'm torn between whether to downvote for the first paragraph (which talks about stuff way too high level for a n00b), or upvote for the last two
–
KipMay 5 '09 at 0:40

Oh, I agree; Gafter's material is primarily aimed at upsetting those of us who think we know...however, I was mainly addressing the "official gotchas" point; when you say "Java gotchas" to me, I do naturally think of the Java Puzzlers.
–
RobMay 5 '09 at 0:44

I definitely recommend Effective Java. It will do more than any other book to give you a serious grounding in good Java programming. It's pretty much precisely for what your question is about. It's not a white paper on Java, it's not a list of what's in the API, it's just a lot of stuff you should know to be an Effective Java programmer.
–
Brandon YarbroughMay 5 '09 at 0:58

+1: I am sick of guys telling me that Java is by value for value types and reference for objects. It is ALWAYS by value. The example in the link above is also the example I use to prove them wrong. I have brought many a supposed Java guru to his knees with that and I am just that afore mentioned n00b myself.
–
uriDiumMay 6 '09 at 8:30

A small one: searching for a Java class on Google and expecting to find up to date information. Advice: always include the version number i.e search "inputstream 6" not "inputstream". Similarly, beware of tutorials on the net, lot of them are outdated.

I think another common beginner pitfall is re-inventing the wheel. That is, writing some (low-level) algorithm, data structure or utility yourself, when there would be (likely far better) implementation already offered by libraries.

For elaboration on this point, read Item 47 in Joshua Bloch's Effective Java (2nd ed): Know and use the libraries. (Read the whole book, while at it! ;-) I'll quote some of the main advice he gives:

By using a standard library, you take
advantage of the experts who wrote it
and the experience of those who used
it before you.

[...] every programmer should be familiar
with the contents of java.lang,
java.util, and, to a lesser extent,
java.io.

Specifically the Java Collections Framework, in java.util, will be immensely useful for any Java programmer, newbie or not; it definitely "reduces programming effort while increasing performance" as Mr Bloch says.

Along with libraries that come with the Java platform itself, a family of Java libraries worth mentioning is Apache Commons. It covers a lot of ground, is widely used, and often continues right where the standard libraries leave off. In addition, although I have yet to use them myself, it seems that Google has recently been putting out some high-quality Java libraries that supplement the Java platform, such as Google Collections (interesting article about it). Edit: now that I've acquainted myself better with Google Collections, I can say that the library is definitely worth looking into after learning the Java Collections framework; it seems like the perfect extension! Start with the Javalobby article I linked to, and also check out this presentation by Kevin Bourrillion, the main developer: part 1 & part 2.

This. Especially since there is a LOT that has been added (relatively) recently (as in Java 1.5+) that has made a lot of the tutorials most people find when Googling around obsolete. If you know your way around java.util.concurrent and the Collections framework, and know how to use Generics, you'll be way ahead of an amazing number of people.
–
Adam JaskiewiczMay 5 '09 at 18:56

1

This is a great one. Java's open source communities are a rich source for things you need to get done, but don't necessarily want to do yourself. Apache's Jakarta and Commons projects are REALLY your friends!! ;)
–
mezmoJul 15 '10 at 15:21

The difference between the scalar type int and the boxed type Integer is surprising to someone new to Java.

Java has always made a distinction between the "scalar" types, which are not classes: boolean (true/false), char (unsigned 16-bit), short (signed 16-bit), int (signed 32-bit), and long (signed 64-bit); and everything else which is a class and ultimately derived from the Object class.

The problem comes when you want to use something like a generic collection like a List. A List can contain anything that is derived from Object, but not scalar values. So in order to store int values into a List, you need to wrap them into an instance of a class called Integer that is derived from Object.

In old versions of Java, you also needed to explicitly get the value out of the Integer class using a .intValue() method call. In newer versions of Java, this conversion is called "unboxing" and is automatic in some situations.

Sun has a short page about autoboxing which is aimed toward a more experienced programmer but might be informative.

Think about running FindBugs on your code (available as an Eclipse plugin). It can flag many common errors. As inspection tools go, I think it is a good one for beginners because it doesn't nitpick over inconsequential details.

I think that the best "cheatcode" is "Don't be smart, write dumb code".

The terms are somewhat loaded but basically you want things to be simple when you write them, because then they will be simple to read when you come back to it later. Also these days the JVM is a LOT smarter than you are, and non-dumb code usually try to do something "more efficiently" which may prohibit the JVM from doing something even smarter.

Please note: It is ok to write smart code, you just need to prove first it is necessary :)

EDIT: A few more things.

Write a lot of code. Practice makes perfect - always strive to do this in the best way possible. If you come back to your code later, you might have learned a thing or two since which allow you to perspective your earlier choices allowing you to make a better descision next time you have to make a choice. THIS INCLUDES DOCUMENTATION! Documentation is what allow others to use your code without understanding it in detail.

Read a lot of code. Set up your IDE so it allows you to see as much source as possible for what you work with. By using a JDK as the JVM in Eclipse the sources are automatically attached so you can SEE the source for whatever you happen to hit in a breakpoint. When including a jar from e.g. Apache in your code, include the sources so you can see what it does. It will help you some day that you can figure out WHY a certain thing happens and how to avoid it.

Work with peers. Other programmers on a similar level may provide input to a situiation - perhaps even just their listening to your explanation clarifies things in your mind - and you may also help them. By working together and evaluating together you can leverage each other.

The Java Tutorial from Sun covers a LOT of the Java libraries, and learning those covering the essential part of the runtime (java.lang, java.io) by heart and having read the rest (just to know what exists) will make you a more skilled programmer. You will know what is in your toolbox!

Participate in Stack Overflow. Writing good answers to questions (even if they have been answered but badly) will allow you to put your experiences into words, which is practice for writing documentation :)

This may be a bit too basic of advice, so forgive me if I'm offending you for bringing it up, but I've seen way too much beginning Java code that throws the static keyword around freely, seemingly without regard for what it's for. So if you see a warning complaining about "static reference to non-static value" or some such thing, don't try to solve it by randomly placing static on an otherwise non-static thing, unless it makes sense to do so.

Here's a minor tip that you might have trouble searching for until you know the term for it: "package-private". In Java, there is the same public, protected, and private scopes that exist in other places like C++. You can read up on what they're for, if you don't already know. Note, however, that if you don't specify whether something is public, protected, or private, it's none of those things. It's package-private, and there's no keyword that specifies it except lack of a keyword. Package-private things act as private values to anything in another package and public to things that are in the same package.

One more random tip: Use packages. It's possible to not begin your .java files with a package com.whatever.foo; line, and if you're using command-line javac you'll find that it's nice that files lacking that line show up in your working directory, but it'll almost always end up being a pain later. And stop using command-line javac anyway. Use Eclipse.

Java is a very straight forward language to start with, if you are already familiar with an imperative C sytle language. The deep issues are not specifically language related, but more broadly related to Statically (and strongly) typed, Single inheritance, OO languages.

I also humbly disagree with my Java brethren here and recommend that you learn to the basics using a text editor and the command line. That is were the specific gotchas of the JVM are most prominent.

Remember the most important distinction between Java and other languages: Java is both a language AND a platform.

You'll need to understand the notion of a classpath; the relationship between logical package structure and its (analogous) embodiment in the file system.

What will typing 'java', 'javac', etc. do when typed in the command line? Learn the fundamentals.

IDEs will completely paper over these fundamental issues of the Java platform.

I also recommend, if you are up to it, to read the Java language specification and (yes) the JVM specification. Make sure you grok classloaders and related issues when you begin your journey in Java if Mastery is what you are after.

I used to be an Eclipse user, then something shocking happened; I moved to NetBeans, which has been tolerable since around 6.0 and actually very nice since around 6.1. I do recommend taking a look if you're still trying to pick an IDE.
–
RobMay 5 '09 at 0:53

7

-1 I disagree 100%. As a novice, you should absolutely NOT start out with a big IDE until you've written and run at least a few not completely trivial programs using nothing but a text editor and the command line tools. Otherwiese, you'll be too dependant on the IDE and helpless when the underlying mechanincs (that you don't understand) shine through.
–
Michael BorgwardtMay 5 '09 at 10:45

5

No no no Michael! I used to teach Java (corporate training). I had started using command-line tools and a simple editor. The students had to deal with the language and the tools at the same time. When I started using VisualAge for Java for the classes, the students more quickly picked up the language concepts and ideas, and when I introduced the command line tools later, it was much easier for them. So much better to think of "package" as an organizational concept than a directory structure... IDEs FTW!
–
Scott StanchfieldMay 5 '09 at 17:09

String a = "wow, not the same";
String b = "wow, not the same";
String c = new String("wow, not the same");
if (a == b) { //happens to evaluate to true, but you shouldn't do this
...
}
if (a == c) { //evaluates to false, which is why you shouldn't do it
...
}
//This is how you *should* do this
if (a.equals(b)) { //evaluates to true
...
}
if (a.equals(c)) { //evaluates to true
...
}

That'll execute the conditional branch, because string literals are interned, and thus both a and b refer to the same object.
–
RobMay 5 '09 at 0:35

3

Actually, in the example above the two strings would be referentially equal because string literals are interned.
–
Bobby EickhoffMay 5 '09 at 0:36

Where this will really nail you is that that condition could in some cases be true. Also, you didn't say what you should do instead, which is say if(a.equals(b)) { ... }
–
Brandon YarbroughMay 5 '09 at 0:36

1

But they are the same. Why would they not be? Now, if you replaced the "wow, not the same" with new String("wow, not the same"), then they wouldn't be the same.
–
Chris Jester-Young♦May 5 '09 at 0:36

1

@Olafur: The point to take away from the comments others and I have left on this answer is that you should always just use the String.equals() method to compare strings; under some circumstances (the "string interning") mentioned above, == will actually work, despite the fact that, semantically speaking, it is not performing a string comparison as it might in some other languages, such as PHP, Python, etc.
–
RobMay 5 '09 at 0:43

Register to JavaBlackBelt and start doing tests over there. As you can see quickly from just browsing the front page, they cover just about anything from the most simple things to the incredibly advanced topics.

And don't be ashamed of failing any of the tests, failing just tells what you should learn more about before continuing :)

Obsessing over Design Patterns! I would not worry too much about design patterns to begin with. It is good if you are aware of their existence so that you will know what other members of your team talk about, but what is important right now is just exploring the Core Java APIs. When you feel comfortable with them I'd really put an effort into learning how to write clean and self-documenting code. This will save you a lot of time and effort in the future when you go back and need to remember what you were doing.

Now compile both, then change "Foo" and recompile Foo but not Bar. Bar will still print out the old value of A_STRING. To experience this for yourself, run locally in eclipse, which silently recompiles all of your classes, and then do an incremental update on a server. Hey, where'd my changes go?

+1; depending on what "other languages" you're talking about, Java is either a hell of a lot different, or not very, and the degree to which it differs varies according to what aspect you're comparing (typing, paradigms, design ethos, etc.)
–
RobMay 5 '09 at 0:51

Some mistakes I have seen people make who are experienced at programming but not at Java:

Classes implicitly extend Object

Classes implicitly import java.lang.*

instanceof doesn't require a not null check

Upcasting, e.g. ((Object)new Integer(1)).toString(), is almost never useful as it doesn't affect dynamic method selection

Strings are immutable. There is no need to copy or clone them.

Don't rely on the garbage collector or finalize() to perform resource (rather than memory) management. Resources, e.g. files, should be closed explicitly.

Swing components, once displayed, should only be accessed from the AWT event thread (typically using SwingUtilities.invokeLater()).

In general, be very, very careful when multiple threads share the same mutable/stateful objects. Either copy your objects first, or be prepared to use a while lot of synchronized blocks, wait() and notify().

Don't use wait/notify, they're antiquated compared to the java.util.concurrent classes available with Java 5. Many cases of wait and notify are used by people who want a blocking queue; in such cases, use the queue implementations provided by Java.
–
Chris Jester-Young♦May 5 '09 at 13:12

Avoid being more specific than you need to. You might be tempted to think of your storage object as a HashMap:

HashMap myStore = new HashMap();

But I would recommend thinking of it only as a Map (interface):

Map myStore = new Hashtable();

The rest of your code does not need to know how we implemented myStore, it just needs to know that myStore is some kind of Map. This way we can change the implementing type later (HashMap,Hashtable,...), and only one line of code will be affected.

And I chose Hashtable as an example, over HashMap, because Hashtable is thread-safe. In a multi-threaded app, this avoids the problem that two threads reading and changing the same HashMap concurrently can start throwing Exceptions.

No, if you want a thread-safe HashMap, use ConcurrentHashMap, not Hashtable (which, like Vector, is slightly obsolete). In fact, ConcurrentHashMap was designed as a straight drop-in replacement for Hashtable.
–
Chris Jester-Young♦May 5 '09 at 13:15

Also, the Collections.synchronizedMap wrapper (similar exist for list and set too) is your friend when you want thread safety for general containers and don't mind locking.
–
Chris Jester-Young♦May 5 '09 at 13:17

3

The first point you make is good, and I'd vote this up if it didn't advocate use of Hashtable... :)
–
JonikMay 5 '09 at 16:05

I'm not going to vote this down, but this is one of the ideas I consider really dumb. I have never changed type of a collection when the original type was well-chosen. I use interfaces only when the called function really does expect more than one type of class.
–
JoshuaMay 5 '09 at 18:11

3

@Joshua: Read Item 52 of Effective Java 2nd ed. You'll see why using the interface type is usually the best choice.
–
Chris Jester-Young♦May 6 '09 at 11:28

Can you reword that a little? At first read I almost downvoted you because it sounded like you were spouting the evil "objects are passed by reference" instead of knocking it down. ObPlug: see my article on this: javadude.com/articles/passbyvalue.htm
–
Scott StanchfieldMay 5 '09 at 17:11

From my experience, people new to Java never ever override equals, hashCode and toString methods, no mater what the objects purpose is. Also nobody ever bothers with setting up simple logging system. When I see System.out.println I feel like I'm ready to break fingers! But lot of seasoned coders are putting pin into thous tasks too.

On more advanced note get used to coding where Specs come first followed closely by unit testing - but this is more generic not just for Java. But again lots of people put pin into this.