tags:

views:

1100

answers:

23

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)

+3  A: 

There's always:

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
    ...
}
altCognito
That'll execute the conditional branch, because string literals are interned, and thus both `a` and `b` refer to the same object.
Rob
Actually, in the example above the two strings would be referentially equal because string literals are interned.
Bobby Eickhoff
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)) { ... }
CaptainAwesomePants
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
Say what? So you use a.equals(b) ?
Ólafur Waage
a.equals(b) is fine as long as you ensure that a is not null first.
Chris Jester-Young
@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.
Rob
Gotcha : P
Ólafur Waage
I tried to resurrect this answer. (off-topic.. should I even be doing that on SO?? it makes the comments illogical to later readers, and it allows the guy that wrote the bad answer to get rep from upvotes on the resurrected answer. if this is bad SO practice feel free to roll back my edits..)
Kip
There is no rep on Community Wiki posts :) So that's why the post gave you most of the credit. It's a very nice addition :)
Ólafur Waage
Indeed, I really fouled this one up. Thanks.
altCognito
+10  A: 

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.

Oh, and don't compare strings with the == operator.

Rob
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
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
Kip
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.
Rob
It's fine :) I think i'll look at Effective Java when i can.
Ólafur Waage
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.
CaptainAwesomePants
I scrolled down and was going to comment to recommend effecitve java, and then I noticed it had already been menitioned in the post and recommend in CaptainAwesomePants's comment. Definately get Effective Java, it doesn't teach you Java but it teaches you the right way of doing things, the "Effective" and efficient, readable and professional-looking way of programming in Java. I was able to apply it to my own code right away.
Mk12
Those are not just noobs, but advanced programmers do fall into them also
OscarRyz
+6  A: 

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.

Greg Hewgill
Could you elaborate?
Ólafur Waage
int a = 300, b = 300;Integer c = 300, d = 300;assert a == b; assert c != d;
Chris Jester-Young
"scalar"? That's a Perl term, isn't it? What about byte, float and double?
Tom Hawtin - tackline
I think "primitive" is a more Java-esque term for "scalar"
Adam Paynter
To add to Chris Jester-Young's comment: Integer a = 128, b = 128, c = 127, d = 127; assert a != b; assert c == d;
Michael Myers
You forgot the floating-point types.
Konrad Rudolph
@mmyers: Correct, that's why I picked 300 and not 1. :-) However, the point is that int and long values between -128 and 127 get cached (return the same object when boxed), as do all boolean and byte values, and all ASCII characters. Maybe some other types too.
Chris Jester-Young
@adam you're right, they're referred to as the primitive types.int,byte,char,float,short,long,double,boolean
Aaron
@Chris Jester-Young: I just ran across this yesterday in the JLS §5.1.7 (http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7 ): "If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2." So you had it right, except that it's short and not long that gets cached.
Michael Myers
+2  A: 

what are the things Java does differently than other languages? (on a basic level)

On a basic level it's not different to other OOP language. However, comparing to plain procedural programming it's a whole new world... or a evolved one.

ktulur
+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.)
Rob
+3  A: 

Use Eclipse for Java editing/development/debugging. Or some other IDE maybe, but for God's sake don't use Notepad & command line.

Kip
Indeed. If you never use Eclipse for anything else, it is king of basic Java programming.
CaptainAwesomePants
Not as long as IntelliJ is alive and well.
duffymo
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.
Rob
I have Eclipse set up, a lot of buttons to configure and press :) It's still fine though... took a while to find the dial to speed up the autocomplete delay.
Ólafur Waage
Personally, I turned off auto-autocomplete and learned to hit ctrl+space frequently.
CaptainAwesomePants
@CaptainAwesomePants, why type thousands of extra characters when it does it for you painlessly?
Simucal
No matter wheter it's NetBeans, IntelliJ or Eclipse, as long as you use an IDE it's all good.
Esko
-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 Borgwardt
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 Stanchfield
i had been an eclipse guy till europa, but when netbeans 6.1 and ganymede came out almost simultaneously, netbeans was a clear winner
Midhat
+5  A: 

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.

JRL
Nice tip :) Thanks.
Ólafur Waage
Or just bookmark the javadocs (see my other answer). of course, google can be faster a lot of times :)
Kip
download the javadocs... and use firefox's Quick Find to quickly find the classes
Carlos Heuberger
+3  A: 

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.

CaptainAwesomePants
Very nice tip regarding package-private. I knew about static and non static actually... but that's a good tip as well for others who might stumble upon this question.
Ólafur Waage
+6  A: 

Bookmark javadocs: http://java.sun.com/javase/6/docs/api/index.html

Better yet, install them locally and bookmark the page on your local machine for faster lookup and offline browsing.

Kip
+1  A: 
JRL
+8  A: 

Saying that objects are passed by reference.

Actually, methods work only with copies of object references..which are passed by value.

Java only works with pass by value.

Also worth reading: Is-java-pass-by-reference?

omgzor
+1: Please read my article on this: javadude.com/articles/passbyvalue.htm (it's ref'd in the "is-java-pass-by-reference" link there)
Scott Stanchfield
+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.
uriDium
http://stackoverflow.com/questions/40480/is-java-pass-by-reference
dhackner
+1  A: 

I would have to say.

One of most common noob pitfalls phrases like "parameters on methods are always passed as reference, because Object variables are references, right?"

so when you see something like:

public void foo(String str){
      str="yeah, this should work!";
}

String str = "";
foo (str);

System.out.println(str);

You can hear a "Wait, WTF !" coming from a noob.

In my experience, java noobs don't know about StringBuffer / StringBuilder. Neither on inmutable objects.

Tom
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: http://javadude.com/articles/passbyvalue.htm
Scott Stanchfield
+2  A: 

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.

+2  A: 

Look here.

dhiller
+2  A: 

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.

Have a look at http://java.sun.com/developer/technicalArticles/Interviews/devinsight%5F1/

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 :)

Thorbjørn Ravn Andersen
+3  A: 

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 :)

Esko
+2  A: 

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

  1. Classes implicitly extend Object
  2. Classes implicitly import java.lang.*
  3. instanceof doesn't require a not null check
  4. Upcasting, e.g. ((Object)new Integer(1)).toString(), is almost never useful as it doesn't affect dynamic method selection
  5. Strings are immutable. There is no need to copy or clone them.
  6. Don't rely on the garbage collector or finalize() to perform resource (rather than memory) management. Resources, e.g. files, should be closed explicitly.
  7. Swing components, once displayed, should only be accessed from the AWT event thread (typically using SwingUtilities.invokeLater()).
  8. 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
@CJ-Y: Funny you mention the blocking queue; this question (http://stackoverflow.com/questions/826161/java-thread-wait-and-notify ) about wait and notify just popped up, and sure enough it was about a blocking queue!
Michael Myers
+4  A: 

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.

McDowell
Nice, thanks :)
Ólafur Waage
+1  A: 

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.

joeytwiddle
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
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
The first point you make is good, and I'd vote this up if it didn't advocate use of Hashtable... :)
Jonik
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.
Joshua
@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
+2  A: 

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.

willcodejavaforfood
+1; Too many people think "Oh, I could probably use a Visitor here; how do I fit this into the Visitor pattern?"
Adam Jaskiewicz
+1  A: 

Static finals can get baked into the class.

i.e.

public class Foo {
  public static final String A_STRING="A_STRING";
}

public class Bar { 
  public void printString() { System.out.println(Foo.A_STRING);}
}

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?

Steve B.
+5  A: 

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.

Jonik
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 Jaskiewicz
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!! ;)
mezmo
A: 

Make sure that you understand OOP instead of making everything static. And find out about stack overflow to ask questions :-).

Mk12
A: 

Combining equals() with autoboxing can get really crazy:

Integer X = 9000;
Integer Z = 9000;
short y = 9000;
boolean b1 = (X == Z);  
boolean b2 = (X == y);    
boolean b3 = (X.equals(Z));
boolean b4 = (X.equals(y));
System.out.println(b1 + " " + b2 + " " + b3 + " " + b4);

outputs:

false true true false
FarmBoy