Bookmark Topic Watch Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Report post to moderator
[level: beginner]

This page is for all those newbies who are overwhelmed by the prospect of writing a new class, maybe one that's a bit more complex than those you've tackled up to now. You've read those instructions and you just want to shout "Mummy!!".

It won't tell you what to write, but it will (hopefully) give you an easy way to avoid errors and get to a good starting point.

It's quite long, but that's mostly because we'll be taking you through the process step-by-step; there's nothing wildly complicated about it.

Hopefully, you'll also pick up some useful tips along the way.

PREREQUISITES  

You are assumed to:

  • Have at least seen a few Java classes, probably from your textbooks or tutorials. Specifically, you must know what a Java array declaration looks like and what a main() method looks like. This is simply so that the code you see here isn't complete gibberish.
  • Know how to use a basic editor (like Notepad).
  • Know where (ie, in what directory) you're going to put your class. In general your tutor, or the book or tutorial you're following, will have given you this information.
  • Know how to use javac (the Java compiler) to compile your code. Again, this should normally be part of your course or tutorial.


  • Other than that? Nothing. Read and enjoy.


    YOUR 'INSTRUCTIONS'...  

    Chances are that if you're working from a book or course material, you will have been given explicit instructions about what they want you to do. And it's here where newbies often start throwing their hands up.

    An example might look something like this, and it's the one we'll be using:

    "1. Create a class called Dice to represent a pair of dice and the totals of their rolls. It should have two integers to hold the results of rolling each die. It should also have an array of integers to represent the possible totals of rolling two dice. This array will be used to count the number of times each total comes up.

    The class should also have the following methods:

  • initCounts() - to initialize all "total" counts to zero.
  • roll() - to roll each die once, and add one to the correct totals element.
  • printCounts() to "print" - ie, display to the console - the number of times each total has come up over a number of rolls.


  • 2. Add a main() method that creates a Dice object, initializes its totals, rolls the dice a number of times (say, 10,000), and then prints out the results."


    Ooof. Does it look daunting?

    Almost certainly that's because you're already thinking about how you're going to code it:

  • How to I initilaize an array?
  • How do I roll a dice?
  • How to I update counts?
  • How do I display an array?

  • And my advice is (and it's a really hard habit to get into):

    DON'T.

    Remember what I said at the start? This tutorial is NOT going to tell you what to code, it's going to show you how to get to a point where you can start coding; but there's quite a bit to do before you can get there.


    FIRST LESSON - The compiler is your friend  

    At a rough guess, I'd say that at least 80% of the problems we get on the 'Beginners' forum boil down to one basic fact:

    Beginners don't compile enough.

    You're just dying to "dive into code", so you start bashing away at the keyboard.

    50 or a hundred lines later (probably when you've hit some roadblock), it suddenly occurs to you that you might want to compile.

    So, you run javac, and what happens?

    You get a pile of error messages. And I do mean a pile - often as many errors as you have lines of code.

    Java is a complex language, and the compiler is NOT forgiving. Can you type 20 lines of code without a spelling mistake? or a missing brace? or bracket? or semicolon? or import statement? ...

    I know I can't - and I've been at this lark a long time.


    So: COMPILE OFTEN. It may seem like a pain in the rear when you're just itching to plough ahead but, believe me, it'll save you a LOT of grief in the long run.

    My rules of thumb are:

  • Compile once for every 10 lines of code you write.
  • Compile at the end of every major step you complete.
  • Compile after each method you write.

  • and they are additive - ie, stick an "AND" between them.

    And - most important of all - when I say "COMPILE", I mean:  

    Keep compiling and correcting your code until you have NO ERRORS LEFT.


    Here endeth the First Lesson.


    THE CLASS  

    Right, so you've got your instructions and you've read the first lesson. Now it's time to create your class. I don't propose to go into great detail about the nuts and bolts, since these will probably be in your book or tutorial, but you're creating a Dice class, so it needs to go into a file called Dice.java.

    Not dice.java or DICE.java or Dice.JAVA, but: Dice.java.

    Java is case-sensitive. Remember that, because it's very important.

    OK, so you've created your file, now let's add the class declaration:



    Why final? Because you don't know if you're going to subclass it or not. It's a tip you won't find in too many books, but it's a very good one to remember:

    Make your classes 'final' unless you know you're going to subclass them.

    You can always remove it later on if you do decide to subclass, but you can't add it.


    The only other thing that's probably worth doing, since your requirements said you will need to create a Dice, is to add a constructor for it, viz:



    The super() call isn't strictly necessary, since the compiler will add it for you if you forget. Indeed, that entire constructor (called a "no-args" constructor) isn't actually required either, since the compiler will add it too - in fact, it will add precisely the code we just wrote - but I always like to put it in myself so I can see what's going on.


    Just one final thing: You might assume from that declaration that your Dice class exists in a vaccuum - well it doesn't. It extends Object. All Java classes do, unless they extend something else.

    And again, the compiler will put it in for you if you forget; but I like to put it in explicitly, just to remind myself what's going on:



    And there you have it: one Dice class declaration. And for the moment that's it. You may need to add other stuff to it later on, but right now you don't know what that is.


    And what should you do now? COMPILE. Hopefully, you shouldn't have any errors, but just in case you're a bad typist...


    FIELDS  

    The next thing the requirements asked you to do was to add some fields, so let's do that.

    The first thing it asked for was two integers to hold the dice results, so:



    And here we have another important point:

    Always, always, always make your fields 'private', unless you've been specifically told not to.

    And if you have, you might want to think about getting another book (or tutor).

    Allowing others access to the internals of your class is a bit like walking around with your flies undone - not something you want to do too often.



    Another point to remember: Use meaningful names.

    We could have called those fields d1 and d2, or just x and y, if we wanted, but it would be bad programming.

    Programs are meant to be read by human beings, and if you ever run into problems and need someone else to look over your code, they're going to have a hard time deciphering it if you constantly use cryptic names.

    You don't need to go overboard:

    is definitely overkill - but still MUCH better than d1.

    Remember: You know what you were thinking when you wrote your code, but other people don't; and the surest way to get it consigned to the garbage bin is to make it hard to follow.


    And one last point: Follow standard naming practises.

    Field and method names should start with a lowercase letter; class names with an uppercase letter. It's only a convention, but it's almost universally accepted, so start using it NOW.


    The instructions also told you to add an array of integers to hold counts of each total for your two dice.

    Now here you do have to do a bit of thinking: What are the possible totals you can get from two dice? Well, the lowest is obviously 2 (each dice showing a 1) and the highest is 12 (each dice showing a 6), so there are 11 possible totals.

    So, in the spirit of derring-do, you simply bash out:



    (I'm presuming that you're familiar with how to create an array)


    Now there's absolutely nothing wrong with this, and it will work just fine; but what you now have is an array with elements numbered from 0 to 10 (Java array indexes start from 0).

    That means that every time you come up with a total, you'll have to subtract 2 from it to get it into the right element, and every time you display your totals, you'll have to add 2 to the element index to show the total it's for. A bit pointless don't you think? It's just one more thing to go wrong, and it doesn't really add any value.

    What about an array where we could just plug the total directly into an element? So, for a total of 7 it goes into element 7. Much nicer. But now that means that you have to have an "element 12". And this is where beginners often slip up.

    Java array indexes start from 0.  

    So, in order to have an "element 12" you'll need at least 13 elements, ie:




    "But what about elements 0 and 1?" I hear you ask, "they'll never be used."

    True, but you know what? My clunky 8-year old Dell has 3 gigabytes of memory, so I doubt it's going to be too worried about a couple of wasted ints.


    Now admittedly, we have started to think about how we're going to write this, which I specifically said we wouldn't; but very occasionally it's worth doing. Just don't make a habit of it.


    It might also be worth adding a little comment to explain what's going on, so:



    Another good habit to get into: Document a LOT - especially if something isn't obvious - and it follows on from the point above.

    Make your programs easy for other people to understand.


    And what should you do now? (I bet you forgot): COMPILE.


    METHODS  

    And now we come to the bit that's probably been causing you sleepless nights: Writing those methods.

    Well, you know what? We're not going to...YET. Remember: this tutorial is only about getting you to the starting line, not writing the code.

    So, how do we write a method without writing a method? Easy: write one that does nothing.

    It's a technique called "stubbing" (at least, that's what I call it). You write a method that will compile, but won't actually do anything until you add the proper code, and my approach is simple:

    Make it throw an Exception.

    Luckily, there's wonderful Exception already built into the SDK that does exactly what we want:

      UnsupportedOperationException (< click) - often shortened to "UOE".

    The beauty of it is that your class will never work (or will keep throwing Exceptions) until you've replaced ALL of them with real code.

    Furthermore, you can throw an Exception from ANY method, providing it's the only thing you do. And lastly: UOE is defined in java.lang, so it's always available to you.


    Let's have a look at our first method: initCounts()

    Although we're not going to be writing any code for it (yet), we do need to think about what it will look like, and for that we need a method signature; and in Java that means 5 things:


  • Its name.  
  • Its arguments (or parameters) - ie, the things we're going to need to pass to it.
  • What it's going to return.
  • It's visibility.
  • It's finality.


  • That last one is a thing that a lot of people (not just beginners) forget. Well don't, because it's important (more on that later).


    So: What does this method need to do? Note: what, not how - we're not writing any real code yet, remember?

    Happily, our requirements told us precisely: "initialize all total counts to zero".

    So taking each point in turn:


  • We already have its name: initCounts.
  • Does it need any arguments? Well, since it's just going to be initializing our totalCount array to 0's - probably not.
  • What should it return? Again, since it's only initializing our totalCount array - probably nothing.
  • Visibility: A very important (and neglected) thing. Does anything outside our class need to be able to call it? I'd say the answer is: we don't know.
  • Finality: Are we likely to want anything overriding it? Well, since it's initializing our totalCount array, which is private - answer: No.


  • and from that we get:




  • Why private? - because we don't know if anyone else needs to call it; and in that case we shouldn't let them. As with final on our class, we can always change to something less restrictive later if we choose, but we can't make it more restrictive. And making it private doesn't stop our class from calling it.
  • We don't want it to be overridden, so it should be final.
  • It doesn't need to return anything, so we specify void as the return type.
  • It doesn't take any arguments, so we write empty brackets.


  • And to turn it into a "stub"?



    Remember that 'new'; otherwise you'll get a compiler error (and I still miss it out, even after 12 years
    ).

    And adding that to our class:



    And what do we do now? COMPILE.



    roll()  

    I thought I'd run through this one as well, because it's slightly different from the previous one. Remember, we want a method signature, and for that, we need to think about those 5 points.


  • We know the name: roll.
  • Does it need any arguments? Well, since it's just rolling our "dice" - No.
  • What should it return? This is a judgement call. It will work perfectly well if it doesn't return anything, but I personally prefer methods that return something. Call it the mathematician in me (although I'm not one), or maybe just that I'm too lazy to write two calls - one to "do it", a second to get the result - but I generally find it helps to return something if you can. In this case, why not simply have it return the total of our two dice? It's no skin off our nose, and it might be useful to somebody.
  • Visibility: Now here we have something that other classes are likely to want to call, so - public.
  • Finality: Are we likely to want anything overriding it? Again, since it's simply rolling our (private) dice - answer: No.


  • And from that we get (as a stub):



    (Again: remember that new)

    And adding it to our class:



    And what do we do? COMPILE. Sorry if it sounds like a broken record, but it's really important.


    THE FINAL CLASS  

    I'm skipping the last two methods because hopefully you understand the process by now:


  • Find out what the method should do.
  • Work out what it should look like, and write a signature - and when you do, remember those 5 points.
  • Turn it into a stub by adding the line to throw a UOE.
  • (in case you'd forgotten) COMPILE.


  • And just in case you're worried that you absolutely have to get that method signature right first time - don't sweat it too much. You can always go back and change it if you need to (at least until you have a class that other people are using). But do think about it. It's important that you get a sense of what these methods are supposed to do before you start bashing out code for them.

    And it's quite possible that some ideas for that code might occur to you while you're going through this process, so it's usually not a bad idea to have a notepad beside you to scribble down notes. Just make sure that none of them end up in your class ... YET.

    You should end up with something like this:



    Quite a bit of code, eh? And yet we haven't written ONE LINE of actual "proper code" yet.


    CONCLUSION  

    It may seem as though we've just gone through a lot of effort for nothing. After all, what we've written won't actually do anything. On the other hand, what we DO have is a skeleton class that:


  • WILL compile.
  • WON'T work until you replace all those UOE's with proper code.


  • And what's more, there is hardly any wasted effort. We would eventually have had to write every single line in it except for the UOE ones - and we plan on replacing them anyway.


    And just in case you don't follow how useful that is, let's have a crack at writing that main() method. What did our requirements say?

    "Add a main() method that creates a Dice object, initializes its totals, rolls the dice a number of times (say, 10,000), and then prints out the results."

    OK, let's do it:




    And plug it into our class:



    And what do we do now? Broken record time: COMPILE.

    And you know what? Unless you typed something wrong, it WILL compile. Without errors.


    It won't run of course - or rather, it will run, but it'll just throw a UOE for the time being. But that main() method sure looks right to me. We've followed our instructions to the letter, so it's highly unlikely that we'll have to change it once we get those other methods coded.

    Do you see what's happened? Because we have an error-free skeleton with all our methods coded as stubs, we're free to tackle the actual code any way we see fit. I bet you thought you'd have to code all those other methods before you even thought about coding main().


    Furthermore, The process we've been through has:


  • Allowed you to do write a lot of useful stuff without worrying about how you're going to code a single method.
  • Forced you to think about what each method will look like BEFORE you start bashing out code for them.
  • Allowed you to deal with one thing at a time - in this case: Creating an error-free skeleton class.


  • And that last point is very important. Part of the art of programming is something called problem isolation - breaking down a problem (or process) into discrete chunks so that you can concentrate on each one individually.

    Hopefully, it's also taught you one other very important lesson:

    You don't need to know HOW you're going to do everything when you start.

    If you don't know how to do something, put it off - and the easiest way to do that is to write a stub. Procrastination may be the thief of time, but it's no bad thing when you're writing programs.



    You now have a skeleton class that (as you've seen) you can start to "fill out" with real code. And you can do it incrementally, sure in the knowledge that the rest of it will compile. So, if you get any errors, they're from what you typed in since your last compile.

    So remember: COMPILE EVERY 10 LINES.

    Now the rest is up to you.

    Good luck.


    AND FINALLY...  

    This is just a rehash of some of the other tips that you've (hopefully) learned in this tutorial.

    1. Protect your code - If you don't know how a certain aspect of your class will be used, err on the side of caution. So:

  • Make your classes final.
  • Make your fields private.
  • Make your methods private AND final.

  • You can always relax them all later on if you find you need to, but you can't add them.

    2. Don't let the compiler "write code" for you.

  • Add an explicit no-args constructor.
  • Add an explicit super() call to your constructors.
  • Add extends Object to your class definition (unless of course it extends something else).


  • 3. The '5 points' of a method signature - Just because you don't know exactly what you're going to code doesn't mean that you shouldn't think about what a method will look like.

    4. Don't use cryptic names. ANYWHERE (ie, fields, methods, OR classes). And follow standard naming conventions.

    5. Document A LOT.

    6. COMPILE, COMPILE, COMPILE (you didn't think I'd let you forget that one did you?
    ) - Every 10 lines; every method; and every other major step you complete.


    FURTHER READING  

    Some pages that might help you in the future, or if you run into any more problems:


  • StopCoding
  • WhatNotHow
  • MainIsAPain
  • UserInput
  • FirstClasses




  • CategoryWinston
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
      Bookmark Topic Watch Topic
    • New Topic