DEVTOME.COM HOSTING COSTS HAVE BEGUN TO EXCEED 115$ MONTHLY. THE ADMINISTRATION IS NO LONGER ABLE TO HANDLE THE COST WITHOUT ASSISTANCE DUE TO THE RISING COST. THIS HAS BEEN OCCURRING FOR ALMOST A YEAR, BUT WE HAVE BEEN HANDLING IT FROM OUR OWN POCKETS. HOWEVER, WITH LITERALLY NO DONATIONS FOR THE PAST 2+ YEARS IT HAS DEPLETED THE BUDGET IN SHORT ORDER WITH THE INCREASE IN ACTIVITY ON THE SITE IN THE PAST 6 MONTHS. OUR CPU USAGE HAS BECOME TOO HIGH TO REMAIN ON A REASONABLE COSTING PLAN THAT WE COULD MAINTAIN. IF YOU WOULD LIKE TO SUPPORT THE DEVTOME PROJECT AND KEEP THE SITE UP/ALIVE PLEASE DONATE (EVEN IF ITS A SATOSHI) TO OUR DEVCOIN 1M4PCuMXvpWX6LHPkBEf3LJ2z1boZv4EQa OR OUR BTC WALLET 16eqEcqfw4zHUh2znvMcmRzGVwCn7CJLxR TO ALLOW US TO AFFORD THE HOSTING.

THE DEVCOIN AND DEVTOME PROJECTS ARE BOTH VERY IMPORTANT TO THE COMMUNITY. PLEASE CONTRIBUTE TO ITS FURTHER SUCCESS FOR ANOTHER 5 OR MORE YEARS!

Classes in Java

Remember this?

import java.util.Random;

public class BetterShape {
	public static void main(String[] args) {
	
		Random rnd = new Random();
		
		final String[] shapeNames = {"Triangle",
 "Square", "Pentagon",
				 "Hexagon", "Heptagon",
 "Octogon", "Nonagon", "Decagon"};
		final int[] shapeSides = {3,4,5,6,7,8,9,10};
		
		int sides = rnd.nextInt(shapeNames.length);
		
		System.out.print("The shape of the day is a ");
		System.out.println(shapeNames[sides]);
		System.out.println("It has " +
			shapeSides[sides] +" sides");
	}
}

There are two arrays containing information about shapes – but the trouble is that information about a single thing is split across two structures: the name is in one; the number of sides is in another. This is not ideal: we would prefer to group data about single ‘things’ together. Most programming languages have a way to do this – often called records, or structures. In Java and other object oriented languages we do this (and more) with classes. We’re going to develop a playing card class in stages to show both the thinking behind classes, and what they can do in Java. Obviously we’ve seen classes before – the first line of every program has started:

public class SomeName {

But we’ve only ever had one – most ‘serious’ programs contain several (usually many).

The First Card Class

We’re going to build a playing card class that includes a value, a name and a suite. Values will range from 1 to 10; names will be the traditional names of playing cards; and suites will be one of ‘spades’, ‘clubs’, ‘hearts’, ‘diamonds’. Here’s the code of the first version.

public class Card1 {
	String name;
	String suite;
	int value;
}

Here’s a main method:

public static void main(String[] args){
			
		Card1 card = new Card1(); 
		
		card.name = "Ace";
		card.value = 1;
		card.suite = "Spades";
			
		System.out.println("Card: " + card.name + "
of " + card.suite);
		System.out.println("Value: " + card.value);
		
		Card1 anotherCard = new Card1();
		anotherCard.name = "King";
		anotherCard.value = 10;
		anotherCard.suite = "Hearts";
		System.out.println("Another Card: " +
			anotherCard.name + " of " +
			anotherCard.suite);
	}
}

The first line:

Card1 card = new Card1();

creates a new Card1 object.

KEY POINT: Classes and Objects

Classes are like templates – they define what is possible. Objects are instances of classes – they are the actual ‘things’. As an analogy think about cars: a particular model of car (say a Ford Focus) is like a class; actual real cars of that model are like objects.

KEY POINT: Creating Objects from Classes

In general, when we create a class we write something like this: ClassName objectName = new ClassName(…);

where we may pass in some parameters (in place of the …). When we do this we are calling a piece of code called a constructor – more about these later. There are other ways of creating objects but this is the most common and basic. It should be clear that we’ve seen this many times already. For example:

Scanner in = new Scanner(System.in);

creates a new object (in) of the Scanner class.

Accessing Elements of a Class

If you look at the main method above you will see the lines:

card.name = "Ace";
		card.value = 1;
		card.suite = "Spades";

This is the way we access elements – or members – of a class. The name of the object (card in this case) goes before the ‘.’ and the name of the member (name, value, suite) go after it. We can both assign to members:

card.suite = "Spades";

and read their values:

System.out.println("Card: " + card.name + " of 
" + card.suite);

which in this case prints out ‘Ace of Spades’.

Printing out an Object

In the example above, the line:

System.out.println("Card: " + card.name + " of " + card.suite);

prints out ‘Ace of Spades’. But this seems a bit clumsy. What happens if we just do:

		System.out.println(card);

If you try this, you get something like:

		Card2@eb42cbf

which seems like gibberish. Actually, it’s the name of the class (Card), followed by ‘@’ and then the memory address where the particular object is stored in hexadecimal (so if you try this, you’ll get a different number). This isn’t very helpful, so we need to change it (and will in a bit).

Classes and Methods

As well as variables, classes can contain methods – and they actually come with some ‘for free’ that we don’t have to write. One of these is called toString() which is called when ever you do something with a class that ‘expects’ a value that’s a string (like printing it). You can also call this method explicitly if you want – this:

		System.out.println(card);

is the same as this:

		System.out.println(card.toString());

Writing our Own toString

The default toString() method is not very useful – we don’t really want to know what it tells us. However, we can write our own and replace the default one.

The Second Card Class

Here’s a new version of Card with a toString() method

public class Card2 {
	
	String name;
	int value;
	String suite;

	- why ‘public’ – see later
	public String toString(){
		return (name + " of " + suite);
	}
}

And here’s how we can use it:

	public static void main(String[] args){
			
		- As before...
		Card2 card = new Card2(); 
			
		- Same again
		card.name = "Ace";
		card.value = 1;
		card.suite = "Spades";
			
		- We'll leave this for now
		System.out.println("Card: " + card.name + "
of " + card.suite);
		System.out.println("Value: " + card.value);
		
		- We'll skip the other card here
		
		- Here's our version of toString():
		System.out.println(card);
		- Suddenly not gibberish!
	}

Now printing out out card directly generates ‘Ace of Spades’ automatically – so we don’t have to print it out in the old, clumsy, way.

Advanced Aside: Skip on First Reading if New to Programming: Inheritance and Overriding

So far we’re written two classes apparently ‘from scratch’ – but we can actually write classes that build on, or inherit from, others. For example, suppose we had a class Car, and wanted a new class SportsCar – however, most things about a SportsCar are just like a Car – we want to be able to say ‘A SportsCar is like a Car with Less Seats’ (or something similar). We can do this in Java using inheritance. We’re not going to do it much here but: • As well as doing it explicitly, it’s happening automatically whenever we create a class: any new class inherits from a ‘base’ class called Object. It’s in this base class the the original toString() method is defined. • When we wrote the toString() method above we are actually replacing the original one – not all the methods we will write will do this, but it’s something we do sometimes do. This is called overriding. Java has a way of telling the compiler you know you are doing this (or think you are…) by using the annotation @Override:

	@Override
public String toString(){
		return (name + " of " + suite);
	}

You don’t have to do this – but it has two advantages: • It tells the reader what you are doing. • If you make a mistake and get the name wrong, so you’re not actually overriding, then the compiler will tell you.

The Third Card Class

The way we’ve been assigning values to our Card objects is like this:

Card2 card = new Card2(); 

		card.name = "Five";
		card.value = 5;
		card.suite = "Spades";

But there are two problems with this: • It’s redundant – once we know the name the value follows automatically from that. We don’t really want to have to set the name and the value. • It’s error prone – there’s nothing to stop us writing:

card.name = "Five";
		card.value = 10;
		card.suite = "Lemon";

or any other nonsense – because any strings (for name and suite) and integers (for value) are permitted by Java. We’ll start with the first problem.

We’re going to write a method to set the value from the name:

public class Card3 {
	
	String name;
	int value;
	String suite;
	
	-  Here's our method
	public void setNameValue(String cardName){
		name = cardName; - sets the name
		switch(value) {
		case “Ace”: 	value = 1;
				break;
		case “Two”:	value = 2;
				break;
		- others skipped to make it shorter
		case “King”:	value = 10;
				break;
		default:	value = -1; - An error value
				name = “error”; 
				break;
		}
	}

	-  We'll leave in toString()
	public String toString(){
		return (name + " of " + suite);
	}
}

As an aside notice the error value of -1 and an error name of “error”– this is used whenever an illegal value for the name gets used. (This does raise a tricky question – is this a good way to handle errors? This isn’t something we’re going to deal with yet.)

Here’s how you call it:

	public static void main(String[] args){
			
		- As before...
		Card3 card = new Card3(); 
			
		- Now we set name and value
		card.setNameValue("Ace");
		card.suite = "Spades";
			
		System.out.println(card.toString());
		System.out.println(card.value);
	}

This now means that provided we pick a legal value for the name we get the correct value. And if we pick an illegal name, we get an error value for both the name and value. Which leads on to the suite – which should only have one of four possible values – Spades, Diamonds, Hearts and Clubs. The next version will add a method to enforce that.

The Fourth Card Class

Instead of repeating the whole class, we’ll just write the extra method we need.

public void setSuite(String suite){
		
		if(suite.equalsIgnoreCase("Hearts") ||
suite.equalsIgnoreCase("Diamonds") ||
suite.equalsIgnoreCase("Clubs")  ||    suite.equalsIgnoreCase("Spades")) {
			this.suite = suite;
		} else {
			this.suite = "error";
		}
	} 

This sets the value of the suite to “error” if any try to call a suite anything other that Spades, Clubs, Diamonds or Hearts are used. Here’s how we would call it:

	public static void main(String[] args){
			
		- As before...
		Card4 card = new Card4(); 
			
		- Now we set name and value
		card.setNameValue("Ace");
		card.setSuite("Spades");
	
		System.out.println(card);
		
		-  Lets test the 'error handling'
		Card5 wrongCard = new Card5();
		
		wrongCard.setNameValue("Lemon");
		wrongCard.setSuite("Grapes");
		
		System.out.println(wrongCard.toString());
	}

The output of this will be – for the first card:

	Ace of Spades

and for the second – wrong – one:

	error of error

The Fifth Card Class

This is all great – we now have methods that enforce some rules on the data held by our class, making it harder to end up with incorrect or inconsistent data. However, there’s a problem. Suppose we create a new class and call our methods like above:

<pre>

Card4 card = new Card4();

		
	card.setNameValue("Ace");
	card.setSuite("Spades");

</pre> There’s nothing to stop us, after we’ve done this, from simply overwriting the values we used (and checked with our methods) by directly writing to the vraiables (or, remember, fields) in the class.

		card.name = "Lemon";
		card.value = 1066;
		card.suite = "Lemon";

This is like putting up a really secure front door but leaving all your windows open. To stop this we need to restrict access to the fields name, value and suite. The way we do that is with the private keyword.  

public class Card5 {
	
	private String name;
	private int value;
	private String suite;
	
	public void setNameValue(String cardName){
		name = cardName; - sets the name
		switch(value) {
		case “Ace”: 	value = 1;
				break;
		case “Two”:	value = 2;
				break;
		- others skipped to make it shorter
		case “King”:	value = 10;
				break;
		default:	value = -1; - An error value
				name = “error”; 
				break;
		}
	}

public void setSuite(String suite){
		if(suite.equalsIgnoreCase("Hearts") ||
suite.equalsIgnoreCase("Diamonds") ||
suite.equalsIgnoreCase("Clubs")  ||    suite.equalsIgnoreCase("Spades")) {
			this.suite = suite;
		} else {
			this.suite = "error";
		}
	}

public String toString(){
		return (name + " of " + suite);
	}
}

KEY POINT: Public, Private Etc.

By now the point of the keyword public should also be clearer: Anything preceded by public is visible outside whatever it’s in (in our case, outside the class Card5. Anything preceded by private is not visible outside the (in this case) class – only inside.   There are actually four possible options we can have in Java

Option Meaning Comment public Visible outside the class of the item it is attached to – in our case, field or method Use this whenever you want something to be accessed from outside a class private Not visible outside the class of the item it is attached to Use this whenever you don’t want something to accessed from outside a class protected Visible outside the class but only to other things in the package or to subclasses Best not to use this since we haven’t done subclasses and packages nothing Visible outside the class but only to other things in the package See above

In practice, we should stick to public and private – they have meanings that make sense in terms of what we’ve done. Using protected (which basically means “a bit less public than public” or nothing at all (“ bit less public than protected”) doesn’t really help us here.

Here’s an example of using Card5:

	public static void main(String[] args){
		Card6 card = new Card5(); 
			
		- Now we set name and value
		card.setNameValue("Ace");
		card.setSuite("Spades");
			
		System.out.println(card.toString());
		
		System.out.println(card.value);
		System.out.println(card.name);
		System.out.println(card.suite);
	}

This seems straightforward enough – we have created our Card5 class, initialized a card to be the Ace of Spades, and then printed it out using both toString() and by printing the value, name and suite directly The trouble is it does not compile! You get an error message something like this (exact text will depend on the name of the file you use to test your card class).

TestCard5.java:16: error: value has private access in Card6
		System.out.println(card.value);
		                       ^
TestCard5.java:17: error: name has private access in Card6
		System.out.println(card.name);
		                       ^
TestCard5.java:18: error: suite has private access in Card6
		System.out.println(card.suite);
		                       ^
3 errors

This is because, of course, we made value, name and suite private! We can no longer (directly) access them. We can set them because setSuite() and setNameValue() are public; we can also print them as a string because toString() is also public. But they themselves are private – the way to fix this is to add accessor, or getter, methods. These are just methods to access the values stored in private fields. In the case of Card5 we just need to add these three:

public String getName() {
		return name;
	}
	
	public int getValue() {
		return value;
	}
	
	public String getSuite() {
		return suite;
	}

These three methods are public so can be called from outside the class – so we can update the method that did not compile:

public static void main(String[] args){
		Card6 card = new Card5(); 
			
		- Now we set name and value
		card.setNameValue("Ace");
		card.setSuite("Spades");
			
		System.out.println(card.toString());
		
		System.out.println(card.getValue());
		System.out.println(card.getName());
		System.out.println(card.getSuite());
	}

Now we are calling our public getter methods we can access the values in the fields – because the methods return those values.

KEY POINT: Get/Set, Accessor/Mutator, Getter/Setter Methods

As stated above methods that return values from a class are called one of get methods, accessor methods, or getter methods – they have names that start with get. There is nothing special about them – they are just methods – or of names starting with get – it just indicates to the reader what they do. Similarly, methods that set the value of things are called (one of ) set methods, mutator methods, or setter methods – they have names starting with set. Again, this is not special – it’s just a standard convention to make reading programs easier. A special variation on using get with getter methods is when the value being returned is a boolean. Then the name usually starts with is. For example, the ArrayList method

isEmpty()

which returns true when an ArrayList is empty.

VITAL KEY POINT: Why Are We Bothering With This?

This is absolutely standard good practice in object oriented programming – you never, never, EVER, let other directly access the values of fields (variables) from outside the class they are in.

The reasons for this are: • Abstraction – we are hiding details about how things work: by only letting the calling code know about the methods, it only has to know what the code does and not how it works. • Encapsulation – the term for this practice is encapsulation: grouping together operations and data, and then hiding the details about how the data is actually stored or manipulated. • Software Reuse – doing this helps software reuse. Provided we don’t change the methods, we can update the way things work (and make it better) without affecting those using it. The last point might seem far-fetched, but we can even change how Card5 works in this way. First I’m going to repeat all the code, with the public bits highlighted in bold.

public class Card5 {
	
	private String name;
	private int value;
	private String suite;
	
	public void setNameValue(String cardName){
		name = cardName; - sets the name
		switch(name) {
		case “Ace”: 	value = 1;
				break;
		case “Two”:	value = 2;
				break;
		- others skipped to make it shorter
		case “King”:	value = 10;
				break;
		default:	value = -1; - An error value
				name = “error”; 
				break;
		}
	}

public void setSuite(String suite){
		if(suite.equalsIgnoreCase("Hearts") ||
suite.equalsIgnoreCase("Diamonds") ||
suite.equalsIgnoreCase("Clubs")  ||    suite.equalsIgnoreCase("Spades")) {
			this.suite = suite;
		} else {
			this.suite = "error";
		}
	}

public String getName() {
		return name;
	}
	
	public int getValue() {
		return value;
	}
	
	public String getSuite() {
		return suite;
	}

public String toString(){
		return (name + " of " + suite);
	}
}

Next, we’re going to change it so that we don’t store the value – instead we calculate it when getValue() is called.

public class Card5 {
	
	private String name;
	private String suite;
	
	public void setNameValue(String cardName){
		name = cardName;
	}

public void setSuite(String suite){
		if(suite.equalsIgnoreCase("Hearts") ||
suite.equalsIgnoreCase("Diamonds") ||
suite.equalsIgnoreCase("Clubs")  ||    suite.equalsIgnoreCase("Spades")) {
			this.suite = suite;
		} else {
			this.suite = "error";
		}
	}

public String getName() {
		return name;
	}
	
	public int getValue() {
		int value;
		switch(name) {
		case “Ace”: 	value = 1;
				break;
		case “Two”:	value = 2;
				break;
		- others skipped to make it shorter
		case “King”:	value = 10;
				break;
		default:	value = -1; - An error value
				break;
		}
		return value;

	}
	
	public String getSuite() {
		return suite;
	}

public String toString(){
		return (name + " of " + suite);
	}
}

The public interface is exactly the same – but now setNameValue() only actually sets the name; we calculate the value every time the getValue() is called (and we don’t even have a private field for it anymore). Provided we call it with legal values, this code behaves exactly the same even though it works differently. (If we call it with incorrect values, it does something slightly different though – see if you can spot it.)

At the end of the last chapter, we’d got to the point where we could create classes that (within limits) included error checking and did not allow access to the internal detail of how it worked. However, to create a card had to do things like this:

Card card = new Card();
card.setNameValue(“Ace”);
card.setSuite(“Spades”);

But if we look at how we created a Scanner, we just had to do this:

Scanner in = new Scanner(System.in);

It looks like we should be able to create a new Card like this:

Card card = new Card(“Ace”, “Spades”);

And we can – but we need to write a constructor first.

Constructors

Constructors are the code that gets called when we create a class – and we’ve already been calling them with code like this:

Card card = new Card();

because Card() is the constructor for the Card class – we did not write this constructor though: it’s the default constructor we get if we don’t provide our own.

Default Constructors

“If you cannot afford a lawyer, one will be provided for you.” All classes need a constructor, and if you don’t write one a default no-argument constructor will be created automatically – this will set up the basic (internal) things needed for the object that is being created needs. So far all the classes we’ve written just use that one. But now we need to write our own. Constructors look like this:

 
public class SomeClass {

	public SomeClass(…) {
		…
	}
	…
}

At first sight the constructor looks like a method. But it does have differences: • Constructors don’t have a return type (not even void). • Constructors have the same name as the class.

The Sixth Card Class

Here’s a version of the card class with a constructor:

public class Card6 {
	
	private String name;
	private int value;
	private String suite;
	
	-  Constructor
	public Card6(String cardName, String cardSuite) {
		-  Rather than repeating code in the methods to
-  set the name, value and suite we just call
		-  them - but see important note below
		setNameValue(cardName);
		setSuite(cardSuite);
	}
	
	-  setNameValue sets the name and value
	public void setNameValue(String cardName){
		
		… code left out to save space
	}
	
	-  setSuite sets the suite. 
	public void setSuite(String suite){
		
		… code left out to save space
}

	-  get methods
	public String getName() {
		return name;
	}
	
	public int getValue() {
		return value;
	}
	
	public String getSuite() {
		return suite;
	}

	public String toString(){
		return (name + " of " + suite);
	}
}

In our constructor, we’ve called the methods we defined already. But notice the syntax was a bit different. When we called them from outside the class, we had to put the object name in front (e.g. card.setNameValue(“Ace”)) but inside the class we didn't. This is simply because when we call a method from outside, we have to say which object we mean. For example, if we've created two Card objects - card and lemon - and we want to find out the suite of both of them, we need to differentiate between card and lemon - card.getSuite() and lemon.getSuite(). But within a class, we don't need to do that. Advanced Aside – Private Constructors Another point - we put the keyword 'public' in front of the constructor. Given that it seems that the whole point of a constructor is that it's called from outside the class, then it seems there would be no point in it being private, so why to we have to say it's public - couldn't that just be assumed? In fact although constructors are very nearly always public there is a reason to make constructors private – and we won't go into details here (but it's useful if you want to create a fixed group of one or more constant objects).

Here’s how we call this constructor:

public static void main(String[] args){
			
		- Not quite as before...
		Card7 card = new Card7("Ace", "Spades"); 
			
		System.out.println(card);
		System.out.println(card.getValue());
		
		card.setSuite("Hearts");
		
		System.out.println(card);
	}

Notice we can still call the method setSuite() which in this case will change the suite of the card from ‘spades’ to ‘hearts’.

Multiple Constructors

Suppose we wanted to create a card and, say, new what name we wanted but didn’t know what suite we wanted. To do this we would need a different constructor – and, in fact, we can have more than one constructor for a class (and most classes in the standard Java library do) provided the arguments are different so that Java can tell them apart. (In fact, we can also have methods with the same name in a class – provided, again, that the arguments, or return type, are different so that Java can distinguish them.)  

Seventh Card Class

Here’s our next card class with multiple constructors:

public class Card7 {
	
	private String name;
	private int value;
	private String suite;
	
	-  Here's the constructor from Card6.
	public Card7(String cardName, String cardSuite) {
		setNameValue(cardName);
		setSuite(cardSuite);
	}
	
	/* This one only sets the name and value; we will 
	 * have to call setSuite() later to set the suite.
	*/
	public Card7(String cardName) {
		setNameValue(cardName);
	}

	
	-  Here's the 'no-argument' constructor
	public Card7 (){
	}
	
	-  setNameValue sets the name and value
	public void setNameValue(String cardName){
		… code left out to save space	}
	
	-  setSuite sets the suite. 
	public void setSuite(String suite){
		… code left out to save space	}

	-  get methods
	… code left out to save space
}

Now we have three constructors: • One that creates a complete card – the same one we wrote in version 6. • One that only creates a card with name and value – you have to set the suite later. • One that has no arguments.

Wait… Didn’t we get the one with no argument’s ‘for free’ already?

Notice we’ve written a constructor in Card7 that doesn’t have any arguments.

KEY POINT: Write a Constructor, Lose the Free One

As soon as you write your own constructor, you no longer get the one that has no arguments automatically and have to write your own if you want one – and since it doesn’t need to actually do anything that doesn’t happen automatically, in this case it’s empty.

public Card7 (){
	}

We could though if we wanted to put some code in – for example, we could say that the ‘default’ card is the ‘two of clubs’ – for example:

public Card7 (){
	setNameValue(“Two”);
	setSuite(“Clubs”);
	}

Here’s an example of calling two of the constructors in Card7:

public static void main(String[] args){
			
		- The 'normal' constructor
		Card8 card = new Card7("Ace", "Spades"); 
			
		System.out.println(card);
		
		- The empty one:
		Card8 emptyCard = new Card7();
		- prints ‘null of null’ unless we use 2nd 
		- constructor above and then it
		- prints ‘Two of Clubs’
		System.out.println(emptyCard); 
	}

Why Would We Ever Change a Card? Private Methods

When you think about it, playing cards are not something you would ‘change’ – having made one:

Card card = new Card(“Five”, “Diamonds”);

it doesn’t seem to make sense to then do this:

card.setSuite(“Clubs”);

because you would reasonably assume that changes like this would not be allowed. To do this, we can simply change the methods that set the suite, name and value to be private.

Eighth Card Class

Here’s a new version that has private methods – marked in bold so they stand out.

public class Card8 {
	
	private String name;
	private int value;
	private String suite;
	
-  Since we're don’t allow the fields to be set
	-  after an object has been created,
	-  this is the only construtor that makes 

	public Card8(String cardName, String cardSuite) {
		setNameValue(cardName);
		setSuite(cardSuite);
	}
	
	
	-  setNameValue sets the name and value
	private void setNameValue(String cardName){
		… code left out to save space	}
	
	-  setSuite sets the suite. 
	private void setSuite(String suite){
		… code left out to save space
}

	-  get methods
	… code left out to save space
}

We’ve skipped the extra constructors here and only have the one that sets all the properties of a card – in fact, because out set methods are now private, this is the only one that makes sense: because if we don’t set them when we create the card, we can never set them because we can’t write directly to the variables (fields), and we can’t call the methods either because they’re private.

Final Fields

Now that we can’t change cards once we’ve made them, we are only actually setting the values of the fields once – so we should make them final. Telling Java that all the fields in a class are final is a good idea (if that makes sense of course) because by doing so Java can work out that objects of that class are immutable – and that means it can make significant efficiency changes when it generates the executable code. This does not make sense for all classes – for example, we are going to look later at a BankAccount example and it would be unhelpful if the bank balance could not change. Also, consider ArrayLists – it makes no sense not to be able to change them. However, it’s more common than you might think that once created, objects do not need to change.

Ninth Card Class

Here’s the ninth example – we’ve changed the fields to be final.

public class Card9 {
	
	private final String NAME;
	private int VALUE;
	private String SUITE;

	public Card9(String cardName, String cardSuite) {
		setNameValue(cardName);
		setSuite(cardSuite);
	}
		
	private void setNameValue(String cardName){
		… code left out to save space		}
	
	-  setSuite sets the suite. 
	private void setSuite(String suite){
		… code left out to save space	
}

	-  get methods – left in this time
	public String getName() {
		return NAME;
	}
	
	public int getValue() {
		return VALUE;
	}
	
	public String getSuite() {
		return SUITE;
	}

	public String toString(){
		return (NAME + " of " + SUITE);
	}
}

Static

We’ve now nearly explained all the things we’ve been writing for weeks without explanation:

public class SomeClass {
	public static void main(String[] args) {…

This is a public (visible everywhere) class called SomeClass, containing a method called main, also public (visible everywhere) which has an array of strings as an argument. However, we haven’t explained the word static. And if you look back at the examples of methods in classes in this chapter and the previous one, the only time we’ve used the keyword static is for the main method. So what does it do? Class Data vs Object Data All the classes in this chapter and the last have included three data items, or properties – name, value and suite. And in each case, these values belong to objects: a particular card will have it’s own values for these. For example, in:

Card card  = new Card(“Six”, “Hearts”);

has value = 6, name = “Six”, and suite = “Hearts”, while:

Card anotherCard = new Card(“Queen”, “Clubs”);

has value = 10, name = “Queen”, and suite = “Clubs”.

However, in any particular pack of cards there will be, generally, a fixed number of cards – typically 52. It would be helpful (probably) to have this value available in the code – probably as a final variable. But this value does not ‘belong’ to any individual object: it’s a property of the class itself and not of an object of that class. It is for things like this that we use the static keyword – static means data (or methods) that don’t depend on data stored in any particular object. In the Card example, we can create a static final variable that tells us how many cards are in a pack:

public class Card10 {
	
	- Here's our static field - the number of cards
	private static final int CARDS_IN_DECK = 52;
	
	private String name;
	private int value;
	private String suite;
	
	… constructor left out to save space
	
	- Here's the static method to access the static field
	public static int getCardsInDeck() {
		return CARDS_IN_DECK;
	}
	… code left out to save space 
}

How do we access the static method getCardsInDeck()? Because it doesn’t depend on a particular object we would normally use the class name instead of the name of an object – however we can do either:

Card10 aceHearts = new Card10(“Ace”, “Hearts”);

- We can do this

int numCards = Card10.getCardsInDeck();

or this:

int moreNumCards = aceHearts.getCardsInDeck();

More About Static – Maths and main

In the past I’ve often asked questions about static in exams and understanding has not been great… So here’s a bit more information to help with that. Objects and classes make a huge amount of sense to lots of things we need to do – they combine data with operations on that data. But there are some things that don’t fit. One example is mathematical functions – which are pure functions that only depend on the data passed directly to them. So in the Java class that contains mathematical functions – called Math – all the methods are static and you’ll be using one for the coursework: Math.sqrt(). The other case to consider is the main method that is the starting point of all Java programs – and which is also static. For a method not to be static, you have to have first created an actual object or you can’t call it – if you look back at all the non-static examples in this chapter and the last, you’ll see that the way we called them was always:

objectName.methodName(…)

In the case of main, when we start running a program we haven’t had a chance to create any objects, so it to be static – otherwise there would be no way to call it. For the same reason, all the example methods in the chapter on methods were static: we had not created any objects of the relevant class. For example, in this case:

class SquareExample {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		System.out.print("Number? ");
		while(in.hasNextInt()) {
			int squareValue = in.nextInt();
			int result = square(squareValue);
			System.out.println("The square of "
+ squareValue +
			     " is " + result);
			System.out.print("Another number “ +
(anything else to quit)? ");
		}	
	}
	
	static int square(int num) {
		return num * num;
	}	
}

for square() to be non-static, there would have to be a line in the main method like this:

SquareExample squareObject = new Square();

Since there isn’t the only way to be able to access the square() method is to make it static.

Classes and Methods – Nouns and Verbs

One way to think about classes and objects is that they represent things – cards, ArrayLists, Scanners, bank accounts, details about people. Some of these things are software models of real things (cards); and some are only software things (ArrayList) – but they are all in at least some sense things. This means that the names of classes (and objects) tend to be nouns – words used to name things. Conversely, the methods in a class represent actions – you call them to do something. This means their names tend to be ‘verbs’ – words used to represent actions. I’ve put ‘verbs’ in ‘’ because most method names are made up of more than one word so, strictly, they can’t in linguistic terms be actual verbs – but they do represent actions. For example, consider this example from the last chapter:

Card card = new Card();
card.setSuite(“Hearts”);
card.setNameValue(“Ace”);

String cardName = card.getName();
int cardValue = card.getValue();

The names of the class (Card) and object (card) represent things so they have names, which are nouns. On the other hand, all the methods describe actions (they are ‘verb-like’) because they all represent something that is being done.

KEY POINT: Naming Classes, Objects and Methods

• When choosing the names of classes and objects use nouns – words that represent names of things. • When choosing the names of methods either use verbs for single-word names; or sequences of words that describe actions – also see the two points below. • When choosing names to set or get the values of properties (variables or things that could be variables),start them with set and get respectively unless they return values which are boolean. • When choosing the names of methods that return boolean values, begin them with is.

Computer Science


QR Code
QR Code classes_java (generated for current page)
 

Advertise with Anonymous Ads