21

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)

Community
  • 1
  • 1
Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198

23 Answers23

16

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.

finnw
  • 47,861
  • 24
  • 143
  • 221
Rob
  • 47,999
  • 5
  • 74
  • 91
  • 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. – C. K. Young May 05 '09 at 00: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 – Kip May 05 '09 at 00: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. – Rob May 05 '09 at 00:44
  • 1
    It's fine :) I think i'll look at Effective Java when i can. – Ólafur Waage May 05 '09 at 00:46
  • 9
    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 Yarbrough May 05 '09 at 00:58
  • 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 Aug 17 '09 at 23:33
14

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?

Community
  • 1
  • 1
andandandand
  • 21,946
  • 60
  • 170
  • 271
  • +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 May 05 '09 at 17:04
  • +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 May 06 '09 at 08:30
  • 1
    http://stackoverflow.com/questions/40480/is-java-pass-by-reference – dhackner Oct 20 '10 at 16:44
11

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
  • 76,767
  • 18
  • 98
  • 146
  • 1
    Or just bookmark the javadocs (see my other answer). of course, google can be faster a lot of times :) – Kip May 05 '09 at 01:14
  • 2
    download the javadocs... and use firefox's Quick Find to quickly find the classes – user85421 May 05 '09 at 13:54
10

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
  • 107,154
  • 87
  • 232
  • 265
10

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
  • 80,077
  • 70
  • 264
  • 372
  • 3
    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 May 05 '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!! ;) – mezmo Jul 15 '10 at 15:21
9

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
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 1
    int a = 300, b = 300; Integer c = 300, d = 300; assert a == b; assert c != d; – C. K. Young May 05 '09 at 00:41
  • 1
    "scalar"? That's a Perl term, isn't it? What about byte, float and double? – Tom Hawtin - tackline May 05 '09 at 11:41
  • 6
    I think "primitive" is a more Java-esque term for "scalar" – Adam Paynter May 05 '09 at 11:48
  • 1
    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 May 05 '09 at 18:02
  • You forgot the floating-point types. – Konrad Rudolph May 05 '09 at 18:20
  • @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. – C. K. Young May 06 '09 at 11:36
  • @adam you're right, they're referred to as the primitive types. int,byte,char,float,short,long,double,boolean – Aaron May 10 '09 at 01:34
  • @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 Jun 05 '09 at 13:55
8

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_1/

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
  • 73,784
  • 33
  • 194
  • 347
8

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
  • 107,573
  • 31
  • 204
  • 267
7

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.

Brandon Yarbrough
  • 37,021
  • 23
  • 116
  • 145
  • 1
    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 May 05 '09 at 00:58
7

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.

alphazero
  • 27,094
  • 3
  • 30
  • 26
5

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
    ...
}
Kip
  • 107,154
  • 87
  • 232
  • 265
cgp
  • 41,026
  • 12
  • 101
  • 131
  • 4
    That'll execute the conditional branch, because string literals are interned, and thus both `a` and `b` refer to the same object. – Rob May 05 '09 at 00:35
  • 3
    Actually, in the example above the two strings would be referentially equal because string literals are interned. – Bobby Eickhoff May 05 '09 at 00: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 Yarbrough May 05 '09 at 00: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. – C. K. Young May 05 '09 at 00:36
  • Say what? So you use a.equals(b) ? – Ólafur Waage May 05 '09 at 00:37
  • a.equals(b) is fine as long as you ensure that a is not null first. – C. K. Young May 05 '09 at 00:39
  • 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. – Rob May 05 '09 at 00:43
  • 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 May 05 '09 at 00:49
  • 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 May 05 '09 at 00:56
  • Indeed, I really fouled this one up. Thanks. – cgp May 05 '09 at 02:02
5

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

Kip
  • 107,154
  • 87
  • 232
  • 265
  • 2
    Indeed. If you never use Eclipse for anything else, it is king of basic Java programming. – Brandon Yarbrough May 05 '09 at 00:46
  • 4
    Not as long as IntelliJ is alive and well. – duffymo May 05 '09 at 00:52
  • 3
    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 May 05 '09 at 00:53
  • 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 May 05 '09 at 00:54
  • Personally, I turned off auto-autocomplete and learned to hit ctrl+space frequently. – Brandon Yarbrough May 05 '09 at 00:56
  • @CaptainAwesomePants, why type thousands of extra characters when it does it for you painlessly? – mmcdole May 05 '09 at 06:17
  • No matter wheter it's NetBeans, IntelliJ or Eclipse, as long as you use an IDE it's all good. – Esko May 05 '09 at 06:43
  • 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 Borgwardt May 05 '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 Stanchfield May 05 '09 at 17:09
  • 1
    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 May 05 '09 at 17:55
5

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
  • 29,022
  • 11
  • 55
  • 82
5

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().
  • 3
    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. – C. K. Young May 05 '09 at 13:12
  • 1
    @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 May 05 '09 at 18:10
5

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
  • 43,223
  • 17
  • 81
  • 111
5

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.
  • 55,454
  • 12
  • 93
  • 132
4

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.

cort
  • 1,088
  • 1
  • 11
  • 20
  • 1
    +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 May 05 '09 at 00:51
3

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
  • 43,810
  • 29
  • 138
  • 169
  • 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 May 05 '09 at 17:11
2

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

mk12
  • 25,873
  • 32
  • 98
  • 137
2

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
Eric Wilson
  • 57,719
  • 77
  • 200
  • 270
2

Another pitfall: figuring that a debugger is a debugger, and using the Eclipse debugger without spending time learning all about it.

Since you said you're using Eclipse, there's a series of 7 excellent video tutorials on the debugger here. I highly recommend spending the time (7*15 minutes) watching them.

JRL
  • 76,767
  • 18
  • 98
  • 146
2

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
  • 29,306
  • 13
  • 121
  • 110
  • 1
    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. – C. K. Young May 05 '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. – C. K. Young May 05 '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... :) – Jonik May 05 '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. – Joshua May 05 '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. – C. K. Young May 06 '09 at 11:28
0

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.

MatBanik
  • 26,356
  • 39
  • 116
  • 178