Навигация
 
  •  Главная
•  Программирование
•  Веб-программирование
•  Заработок в сети
•  Продвижение сайта
•  Дизайн
 
 
 
 
 
 
 
 
 
 
 
   
 
 
 
 
 
 
Навигация
 
  •  Главная
•  Форум
•  Доска объявлений
•  Биржа труда
•  О нас
 
 
 
     
  •   Программисты.kz » Программирование » Java » Уроки Java » Writing and Using Code for Classes  

      Реклама на сайте:
Голосуй за Programmers.kz

  Writing and Using Code for Classes  
    |   18-12-2009, 19:32   |   Опубликовал: КазКиберГетик  : 190  
 

Java Unit 4

Writing and Using Code for Classes

4.1  Instance Variables, Constructors, and Methods

4.2  Copying and Using Object References

4.3  The Null Reference

4.1  Instance Variables, Constructors, and Methods

There are three major components of a class definition.

1.      Instance variables (called fields in the API documentation).

2.      Constructors.

3.      Methods.

The following notes will show how to write code for a user designed class, dealing with each of those three parts in order.  In Unit 1 the idea of a class was introduced by means of a cup containing seeds.  This will be the basis for the following example.

In order to be used by a program, a user written class will be public, like a program class.  The term encapsulation refers to the idea that certain parts of an object should not be directly accessible from the outside.  For example, in general it is desirable that instance variables only be accessible by means of methods.  In order to enforce encapsulation, instance variables are declared private.  Shown below is code for a very simple cup class.  It is syntactically correct, but without methods there is little that could be done with such a class.

public class Cup1

{

  private int seedCount;

}

In order to create instances of the class, constructors are needed.  If the programmer provides no constructors, as in the previous example, the system supplies one by default.  In order to be able to use a constructor or write one of your own it is necessary to understand their characteristics:

1.      They are declared public.

2.      They do not have a type.  They always return a reference to an instance of the class.

3.      They have exactly the same name as the class, including capitalization.

4.      They may have 0 or more parameters.

5.      There can be more than one constructor.  They all have the same name, but the system can distinguish between them if their parameters lists differ according to data types.

6.      The code inside constructors initializes instance variables.

Here is the second example of the Cup class, this time with constructors included.  It is clear that an instance of the class could be created in a program, but without methods it is still not very useful.

public class Cup2

{

  private int seedCount;

  public Cup2()

  {

       seedCount = 0;

  }

  public Cup2(int initialValue)

  {

       seedCount = initialValue;

  }

}

            The code for a constructor is written as a separate block enclosed in braces inside the class definition.  The example shows two possibilities:  A constructor that doesn’t take a parameter, and one that does take a parameter.  In the first, the instance variable is initialized by assigning it a hard-coded value, 0.  In the second, the instance variable is initialized by assigning it the value of the parameter.  In a program using the class, both of the following calls would construct Cup2 objects:

Cup2 mycup = new Cup2();

Cup2 yourcup = new Cup2(4);

            In order to make use of constructed objects, methods are necessary.  Methods generally fall into 2 categories:

  1. Accessor methods.  These are “get” methods, which return the value of an instance variable without changing it.
  2. Mutator methods.  These are “set” methods, which allow the value of an instance variable to be changed.

Here is the example class with some methods added to it:

public class Cup3

{

  private int seedCount;

  public Cup3()

  {

       seedCount = 0;

  }

  public Cup3(int initialCount)

  {

       seedCount = initialCount;

  }

  public int getSeedCount()

  {

       return seedCount;

  }

  public void setSeedCount(int newCount)

  {

       seedCount = newCount;

  }

}

The following observations can be made about methods:

  1. In order to be used by programs outside of the class definition, they are declared public.
  2. After the declaration of public, a type is given.  The type may be a simple data type, a reference, or void if the method does not return anything.
  3. Methods may or may not take parameters.
  4. It is customary to use some naming convention that allows you to quickly tell a “get” method from a “set” method.

In particular, the following observations can be made about getSeedCount():

  1. It is declared public.
  2. It is typed int.  In order to be syntactically and logically correct, the code for such a method has to end with a return statement that returns either a constant or some variable of that type.
  3. It takes no parameters.

The following observations can be made about setSeedCount():

  1. It is declared public.
  2. It is typed void.  The code for the method does not contain a return statement.
  3. It takes a parameter, and just like in a constructor, the parameter has to be typed.  The method assigns the value of the parameter to the instance variable of the object.

Keep in mind that in a program it isn’t possible to access or change the value of seedCount in an object like mycup except through calls to the methods getSeedCount() and setSeedCount().  However, in the code contained within the class definition you have direct access to the instance variables of that class.  This line of code in the setSeedCount() method illustrates this fact:

     seedCount = newCount;

It is now possible to write a fragment of program code that illustrates the construction and use of an object of this class:

Cup3 mycup = new Cup3();

int mycount = mycup.getSeedCount();

myterminal.println(myvalue);

mycup.setSeedCount(4);

myvalue = mycup.getSeedCount();

myterminal.println(myvalue);

            You would get the following output from this fragment:

0

4

For system supplied classes we have seen that it is possible to make a call to the println() method with an object of such a class as a parameter.  The output of such a call is textual information telling which class the object is an instance of, along with the names and values of instance variables in square brackets.  What happens when you make a call like this using an object from a class you’ve created?

myterminal.println(mycup);

You’re hoping for something like this:

Cup3[seedCount=4]

Instead, you get something like this:

Cup3@5d87b2

            A class has to have its own implementation of a method called toString() in order for the println() call to give the results hoped for.  Since the Cup3 class doesn’t have this, a system supplied toString() method is called, which gives the results shown.  This version of the method only shows the name of the class, followed by the “@” symbol, followed by what is known as the hash code of the object.  How your class has access to the system supplied version, and how to write your own version of toString() will be covered later.

Now consider a fragment of code where more than one instance is created:

Cup3 mycup = new Cup3();

Cup3 yourcup = new Cup3();

mycup.setSeedCount(4);

yourcup.setSeedCount(5);

Method code resides in the class.  Each object shares the same copy of code.  Each object has its own instance variables.  However, the names of the instance variables of each object of the class are the same.  The line of code in the setValue() method reads:

     seedCount = newCount;

      When this line of code is executed, which object’s seedCount is changed?  It is now important to explain more completely the meaning of the model shown here:

object.method(parameters);

     For any execution of the method, the object that the method is called on, and only that object, is the one whose instance variable is changed.  Up to this point we’ve referred to the things inside the parentheses simply as parameters.  They are values which are used in the execution of the method.  From now on, when being specific, they will be known as explicit parameters.  This is because the object in such a call is also a parameter.  It is something which can also be used in the execution of the method.  It is known as the implicit parameter.  It is the implicit parameter which tells the system which object’s instance variable is to be changed by a call to method code shared in the class definition.  There is a keyword that makes it possible to show the use of the implicit parameter.  Here is the line of code from the setSeedCount() method, rewritten with this keyword:

this.seedCount = newCount;

The keyword “this” is the name of the reference to the implicit parameter for any particular execution of the method.  If, for example, this call is made:

mycup.setSeedCount(4);

Then inside setSeedCount() “this” refers to “mycup”.

Methods can be more complicated than the ones shown so far.  A simple example would be a method that allowed you to increase the current seed count by a given amount.  Here is such a method:

  public void increaseSeedCount(int addedNumber)

  {

       seedCount = seedCount + addedNumber;

  }

     A class can be written, saved, and compiled separately from any program that might use it.  Just as with program classes, the name of the file a class is saved in has to agree exactly with the name of the class, including capitalization, and it has to have the .java extension.  A user written class will be available to any program that needs to use it if it is stored in the same folder as the program.

            The logic of a class can only be tested by a program that uses it.  A complete test program would make use of every constructor and method defined in the class and print output that would allow the user to determine whether those elements were having the desired effect.  Here is a test program for the Cup3 class.  Several remarks follow the program.

/*  This program tests all of the constructors and

    methods of the Cup3 class.  */

public class TestCup3

{

     public static void main(String[] args)

     {

          MyTerminalIO myterminal = new MyTerminalIO();

          Cup3 mycup;

          Cup3 yourcup;

          int avalue;

          /*  Test the constructor that doesn’t take a parameter and the set and get methods.  */

          mycup = new Cup3();

          myterminal.println("Enter an integer:");

          avalue = myterminal.getInt();

          mycup.setSeedCount(avalue);

          avalue = mycup.getSeedCount();

          myterminal.println("mycup seedCount: " + avalue);

          /*  Test the constructor that does take a parameter.  */

          myterminal.println("Enter an integer:");

          avalue = myterminal.getInt();

          yourcup = new Cup3(avalue);

          avalue = yourcup.getSeedCount();

          myterminal.println("yourcup seedCount: " + avalue);

          /*  Test the increaseSeedCount() method.  */

          myterminal.println("Enter an integer:");

          avalue = myterminal.getInt();

          mycup.increaseSeedCount(avalue);

          avalue = mycup.getSeedCount();

          myterminal.println("mycup seedCount: " + avalue);

     }

}

     It should be noted that the variable, avalue, passed from the calling program to the methods, does not have the same name as the parameters, newCount and addedNumber,  in the method definitions.  The system can distinguish between variables with the same name if they are declared in different places, so it would be possible to have a newCount variable in a program as well as a method.  However, this is not a good idea because it may confuse the programmer.

When starting to write programs it is important to plan the order in which things need to happen in the program.  Beginning programmers often make the following mistake when writing a program that tests a constructor that takes parameters:  They try to construct the object before getting the needed parameter(s) from input.  In most cases it is possible to write test programs that use plain numeric values rather than input from the terminal.  The example also was given with prompts in order to show the sequence of events if interactive input is used.

4.2  Copying and Using Object References

When simple variable types are declared, a memory location is set aside for them where values of that type can be stored.  Consider the following lines of code:

double var1;

double var2;

var1 = 100.0;

var2 = var1;

At the end of the sequence there are two copies of the value 100.0 stored in two different locations in memory, and each location is referred to by a different name in the program, var1 and var2.

Object references do not work the same way.  Consider the following lines of code:

Cup3 mycup;

Cup3 yourcup;

mycup = new Cup3(4);

yourcup = mycup;

Only one object is created, and so only one object exists.  However, there are two valid references and they both refer to that one single object.  The diagram below illustrates this idea.  The boxes on the left represent the named references in the program.  The box on the right represents the actual object as stored in the computer’s memory at run time.  The line segments ending in solid dots graphically represent the relationships between the named references and the object.

  In the following examples assume that the declarations have been made.  Now consider these lines of code:

mycup = new Cup3(4);

mycup = new Cup3(5);

This time two objects are created, but there is only one reference.  A reference can only refer to one object at a time.  As a result, when the second object is created and its reference is assigned to mycup, the first object no longer has a reference to it.  Here is a diagram illustrating this situation.

When this happens, the object without a reference still exists in the system, but it can no longer be used in the program because the program has lost its handle on it.  It is possible to do this accidentally, but in generally it’s perfectly all right to do this intentionally.  In Java, the system searches for objects that are no longer accessible and disposes of them.  This is referred to as “garbage collection”, and you as a programmer don’t have to worry about it.

Now consider the following lines of code:

mycup = new Cup3(4);

yourcup = new Cup3(5);

yourcup = mycup;

In this case there are two objects and two references, but when the assignment, or copying of mycup to yourcup takes place, the reference to the object that yourcup originally referred to is lost.  Both yourcup and mycup now refer to the same object.  Here is a diagram illustrating this situation:

Unlike the assignment of variable values, the copying of object references does not result in a new copy of the object.  It simply results in multiple references to the same object.  If a copy is desired, it is possible to write a method that will return a reference to a copy.  This is referred to as cloning and will be taken up later.  In the meantime, it is already possible to make copies of simple objects using the constructors and methods we have.  Consider the following lines of code:

mycup = new Cup3(4);

yourcup = new Cup3(5);

int someValue = mycup.getSeedCount();

yourcup.setSeedCount(someValue);

At the end of the sequence, the instance variables of mycup and yourcup have the same values, but these references refer to separate objects.  The two objects are faithful copies of each other.  However, there is no link between them, and further actions could cause their contents to differ again.  Here is a diagram illustrating this situation:

4.3  The Null Reference

It is possible to declare names for object references and not assign object references to them.  Such names literally refer to nothing at all.  It is also possible for a reference to be assigned the special value “null”.  Although no object exists, this is not the same as referring to nothing at all.  A programmer can make such an assignment and in certain situations the system will make such an assignment by default.  Even if you choose not to use null in your code, you need to know about it since the system may make use of it.  Various errors can arise from improper use of null references, and it is important to be able deal with these errors, and distinguish them from errors arising from references to nothing at all.  Here is a null reference assignment:

Cup3 mycup;

mycup = null;

This could be used, for example to dispose of a previously constructed object without creating a new one:

Cup3 mycup;

mycup = new Cup3(4);

mycup = null;

            What follows is a class definition and a set of examples showing various different things that can happen within programs that use the class.  These things are either the result of an object name referring to nothing at all, or a null reference.  Here is the class:

public class Shampoo

{

     private String kind;

     private int rating;

     public Shampoo(String initkind)

     {

          kind = initkind;

     }

     public Shampoo(int initrating)

     {

          rating = initrating;

     }

     public void setKind(String akind)

     {

          kind = akind;

     }

     public String getKind()

     {

          return kind;

     }

     public void setRating(int newrating)

     {

          rating = newrating;

     }

     public int getRating()

     {

          return rating;

     }

}

            Here is the first example.  It illustrates that using an object name as a parameter in a method call does not work if the object does not exist.  The compiler can detect a problem like this.

public class Test1

{

  public static void main(String[] args)

  {

    MyTerminalIO myterminal = new MyTerminalIO();

    Shampoo myshampoo;

    myterminal.println(myshampoo);

  }

}

This is the compiler output from the first example:

A:\Test1.java:8: variable myshampoo might not have been initialized

          myterminal.println(myshampoo);

                             ^

1 error

Tool completed with exit code 1

If the compiler ends with such an error, no program is created.  Shown here is the type of error message you would receive if you mistakenly tried to run this anyway.  It does not say anything about an uninitialized variable.  It simply says that the program class doesn’t exist.

Exception in thread "main" java.lang.NoClassDefFoundError: Test1

Press any key to continue . . .

            Here is the second example, which illustrates a similar situation.  An object name is declared, but no object exists, and a method is called on that name.

public class Test2

{

  public static void main(String[] args)

  {

    MyTerminalIO myterminal = new MyTerminalIO();

    Shampoo myshampoo;

    int somerating = myshampoo.getRating();

    myterminal.println(somerating);

  }

}

            The second example generates exactly the same kind of compiler error as the first example, and no program results.

            Now consider the third example.  It is similar to the first example, in that it considers the case where an object reference is to be passed as a parameter.  No object exists but in this case the reference has been given the value null.

public class Test3

{

  public static void main(String[] args)

  {

    MyTerminalIO myterminal = new MyTerminalIO();

    Shampoo myshampoo = null;

    myterminal.println(myshampoo);

  }

}

            The program compiles and runs successfully.  It prints out the value of the reference myshampoo with no problem.  Here is the output:

null

            Now consider the fourth example.  It is similar to the second example, in that it considers the case where a method is to be called on an object reference.  No object exists but in this case the reference has been given the value null.

public class Test4

{

  public static void main(String[] args)

  {

    MyTerminalIO myterminal = new MyTerminalIO();

    Shampoo myshampoo = null;

    int somerating = myshampoo.getRating();

    myterminal.println(somerating);

  }

}

            This program compiles successfully but it will not run successfully.  The compiler is not all-knowing.  It detects the fact that the object reference is initialized and doesn’t complain.  It does not detect the fact that a method call is made on a null reference.  It is not possible to make a method call on a null reference.  This is the error message that would result if you tried to run the program:

Exception in thread "main" java.lang.NullPointerException

        at NullTest.main(Test4.java:8)

Press any key to continue . . .

            The first four examples are relatively straightforward.  They illustrate problems that a beginning programmer should be able to manage.  However, there is a more subtle source of null references in programs.  The Shampoo class has an instance variable that is a string.  Since String is a class, this instance variable is an object reference.  The Shampoo class has a constructor that takes a single int as a parameter.  In the code for that constructor, nothing is done to explicitly initialize the String instance variable.  If any initialization does occur, it is by default.  The key point is that the system will initialize the String instance variable by default, to the value null.  Now consider the fifth example, which makes use of this constructor.

public class Test5

{

  public static void main(String[] args)

  {

    Shampoo myshampoo;

    MyTerminalIO myterminal = new MyTerminalIO();

    String somekind;

    int somerating = 5;

    myshampoo = new Shampoo(somerating);

    somekind = myshampoo.getKind();

    myterminal.println(somekind);

  }

}

This is the output from the fifth example:

null

            This program runs successfully because it is possible to have a null reference as an explicit parameter.  However, it illustrates that null references can arise in programs from unexpected sources.  The sixth example illustrates how a program may fail due to a null reference that was obtained from elsewhere.

public class Test6

{

  public static void main(String[] args)

  {

    Shampoo myshampoo;

    MyTerminalIO myterminal = new MyTerminalIO();

    String somekind;

    int somerating = 5;

    myshampoo = new Shampoo(somerating);

    somekind = myshampoo.getKind();

    myterminal.println(somekind);

    int length = somekind.length();

    myterminal.println(length);

  }

}

The program runs correctly through this line of code:  myterminal.println(somekind);

It causes this output in myterminal:

null

            The program then encounters a problem in this line of code:

      int length = somekind.length();

This causes the following run time error in the DOS prompt window:

Exception in thread "main" java.lang.NullPointerException

          at NullTest6.main(Test6.java:18)

Press any key to continue . . .

The occurrence of null in the output comes from the first, successful call to println().  The error comes from the call to somekind.length().  It is not possible to call a method on a null reference.   Notice that this is the kind of thing which the compiler can’t see in advance.  Only the programmer can foresee and avoid problems like this, or correct them after they have been discovered.

References that refer to nothing and null references are possible in Java.  The default initialization of instance variables in objects can cause null references in programs.  This is a subtle source of problems that the programmer needs to be aware of.  The examples above are not exhaustive, but they show some representative cases and the results that they lead to.  If you encounter an error message similar to one of those shown above, you may be able to figure out what your problem is by looking at the examples again.


Download MyTerminalIO class

Author: Kirk Scott

Look official permission!


Ключевые теги: Classes, Using, Writing, Уроки Java
 
 
 
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Обсудить на форуме


Другие статьи по теме:


 
 
 (голосов: 0)
 

  Информация  
     
  Посетители, находящиеся в группе Гости, не могут оставлять комментарии в данной новости.  


 
 
Вход на сайт
 
логин :
пароль :
Напомнить пароль?
Вы не зарегистрированы? Регистрация здесь
 


Наш опрос
   


Статистика
  Всего на сайте: 11
Гостей: 7
Пользователи: - отсутствуют
Роботы: crawl Bot, Google AdSense, crawl Bot, Yahoo Bot

 


Олимпиады
  2010/09/15 - 21:00, Ср Member SRM 482
Начало: 2010/09/15 - 21:00, Ср Длительность: 1 ч 35 м

2010/09/25 - 22:00, Сб SRM 483
Начало: 2010/09/25 - 22:00, Сб Длительность: 1 ч 35 м

2010/10/06 - 07:00, Ср SRM 484
Начало: 2010/10/06 - 07:00, Ср Длительность: 1 ч 35 м

2010/10/21 - 17:00, Чт Member SRM 485
Начало: 2010/10/21 - 17:00, Чт Длительность: 1 ч 35 м

2010/10/26 - 21:00, Втр SRM 486
Начало: 2010/10/26 - 21:00, Втр Длительность: 1 ч 35 м

 


Партнёры
 
Freeway.kz
Образование в Казахстане и за рубежом: Uchi.kz
Benchmark.kz - компьютерный портал
wWw.informatik.kz
Информационный портал Hi-Tech
 


Реклама
 
 


 
 
 
 
Главная страница   |   Регистрация   |   Добавить новость   |   Правила сайта   |   Статистика   |   Обратная связь
Copyright © 2009 КазКиберГетик & AlexanderMS . Все права защищены...
Made in DLETemplates.Com and by КазКиберГетик © 2009 for programmers.kz. Modifications by КазКиберГетик
  Rambler's Top100