TDDC69 Objektorienterad prog. och Java
Labb 1: Introduktion
Den första laborationen är utformad för att ge er en chans att börja med vissa praktiska aspekter av objektorienterad programmering i Java så tidigt som möjligt, så att vi kan varva teori (föreläsningar) med praktik (labbar) istället för att vänta till de flesta föreläsningar är avklarade.
Eftersom vi börjar så tidigt går vi ännu inte särskilt djupt i de objektorienterade begreppen i denna labb. Istället ligger fokus på att ge ett första smakprov på Java och att demonstrera användbara funktioner i utvecklingsmiljön, vilket ni kan ha stor nytta av under senare laborationer och under projektet. Laborationen är i "tutorial"-form där ni ges konkret ledning i varje steg.
Uppgifterna ni får här kan verka väldigt enkla. Det är meningen! Poängen är just att ni får praktisk erfarenhet av de enklaste aspekterna av Java samtidigt som ni lär er utvecklingsmiljön. När det steget är taget går vi vidare och ökar komplexiteten gradvis.
Den utvecklingsmiljö som används är IntelliJ IDEA. Läs även sidan om utvecklingsmiljöer innan ni går vidare.
Just denna labb är för närvarande på engelska. Resterande labbar kommer att vara på svenska.
Starting IDEA, Creating a Project
Use the following command to copy a couple of necessary files for IDEA:
~TDDC69/bin/installidea.sh
Then use the following command to start IDEA:
~TDDC69/idea/bin/idea.sh
If you get warnings about the encoding 'UTF-8', please ignore them.
After a while, you will see the IDEA startup screen, which looks approximately like this. (In this screenshot, IDEA is running on a Sun machine but windows are displayed on an X server on a Windows 7 machine.)
Follow these steps to create your first IDEA project.
- Click "Create New Project" or select .
- In page 1 of the resulting dialog window, "Create project from scratch" should be preselected. Press Next.
-
On page 2, give your project a name, for example "TDDC69-lab1".
Tell IDEA where the project files should be stored (including all the source code you will write). The default location, a folder named IdeaProjects in your home directory, may not be ideal if you already have a directory structure for your courses.
Change the project file format to ".ipr".
An IDEA project consists of a set of modules, where each module can be used in multiple projects. You will use a single Java module for this project. Leave the checkmark indicating that a module should be created. Change the name to "lab1", but leave the content root and module file location unchanged.
Press Next.
-
Page 3: IDEA wants to know where to store source files for this project. Leave the default path unchanged and press Next.
-
Page 4: IDEA wants to know which JSDK, Java Software Development Kit, you want to use. No JSDK is configured at this point, so press the configure button and navigate to /usr/jdk/instances/jdk1.7.0. Press OK and then Next.
-
Page 5: IDEA wants to know if you need any web-related frameworks or class libraries. You don't so leave all checkboxes empty and press Finish.
You have now created a project. IDEA loads the project files and begins scanning and indexing the Java Development Kit files in the background. This may take a while, but you can continue working with most tasks in parallel.
(If you get a "tip of the day" dialog, you can dismiss it.)
The project view may be hidden by default. If so, open it by pressing Alt+1, clicking "1: Project" at the top left, or selecting View | Tool Windows | Project. This will display the structure of your project. You can expand the view to show all relevant directories and files, including a set of external libraries that your project uses – at this point, only the JDK.
Exercise 1: Shape, Circle, and Rectangle
In this exercise, you will implement a few simple Java classes. We assume that you have already started IDEA and created an IDEA project as shown above.
Note again that the entire point of doing this lab is learning how to use IDEA. The end result does not matter -- we want you to explore some of the functionality available in the environment, and therefore you should make sure you actually use code generation, navigation and other features as described below. Just typing everything from scratch might get you through this tiny lab more quickly, but you won't learn as much and you will waste time during the much larger project.
First, a Shape class.
-
Follow the instructions below to create a class called
se.liu.ida.youremail.TDDC69.lab1.Shape, where youremail is your e-mail address (noone123) or possibly two e-mail addresses (abcde123.fghij456)To create a Java class (or interface) in IDEA, first determine (1) the name of the package that should contain the class and (2) the name of the class. Right now you want to create a class called
Shapein a package named something likese.liu.ida.noone123.tddc69.lab1.The left-hand side of the screen should show the project pane. If it doesn't, select .
In the Project tab of the project pane, you see all modules within your project (though in this course you only use one module). If you double-click the module (a folder icon with a blue cube), you should see a directory/file hierarchy. You can also see the Java class libraries used for your project. This corresponds to the CLASSPATH for a command line system.
[-] ### Lab1 (module, folder with blue cube) | | ### src (src subdirectory) | +--### Lab1.iml (module definition file, may not appear until later) +--### Lab1.ipr (project definition file) +--### Lab1.iws (personal workspace config file) [+] ### External Libraries
Since this is the first time you create a class, you don't have any packages yet. It is time to create the package that should contain your new class. Right-click the src node. It is blue to indicate that it is a source path -- you can have more than one, but yellow directories are just plain directories. Select to create the package, "se.liu.ida.noone123.tddc69.lab1" (with your own account name, of course).
You will see the package hierarchy as a directory tree. If you think this tree is too deep, you can flatten it using one of the toolbar icons in the project pane.
Now right-click the destination package and select to create a new class in the package. Specify the name of the class you want to create, for example "
Shape". The full name of the class is then "se.liu.ida.noone123.tddc69.lab1.Shape". -
The class should have a constructor without arguments,
Shape(), which prints "A shape is constructed".Position the cursor where you want the constructor (you may have to insert a few newlines). Select . Select "Constructor". An empty constructor is generated.
In the constructor, enter sout and press TAB. The "sout" live template is automatically expanded to
System.out.println();and the cursor is within the quotes. Enter the rest of the text: "A shape is constructed".Notice the syntax highlighting. For example, IDEA knows that
System.outis a static field, and highlights it accordingly. The highlighting can be adjusted in the settings ().Try pressing Ctrl-Q when the cursor is in
System, inoutandprintln. This shows a "quick javadoc" popup.Also try pressing Ctrl-B when the cursor is in
println. Ctrl-B (or ctrl-mouse-click) navigates to the definition of an element. In this case, it navigates to the source code for one of the overloadedprintlnvariations in classPrintStream.Press Alt-Left to return to where you were.
-
The class should also have a method
void draw()which is bothpublicandabstract. Like methods in interfaces, abstract methods have no implementation: They end with a semicolon instead of with a block of code.Add this method manually.
Since the class is not declared abstract,
public class Shapewill be underwaved in red, and the little square in the top right corner of the editor will be red. There will also be a red error stripe in the stripe bar located close to the scroll bar. The position of this error stripe corresponds to the proportional position of the error within the current source file.Go to the error using . You will notice a small yellow or red light bulb popping up. This is the indication that an intention action is available — an action that helps you fix an error by guessing what you meant to do. (No, this is not like the MS paperclip — the suggestions are usually useful...)
Click the light bulb or press to pop up the intention menu. You will see one entry: "Make 'Shape' abstract". Click this or press to select it. The class is now abstract.
If you instead click the right arrow within the menu, or press cursor right, a set of options related to the intention action should pop up. One option should be to turn off the intention action so that it does not pop up automatically in the future. The intention action can still be invoked by pressing alt-enter with the cursor placed appropriately, after which you can turn the intention action on again if you want.
Then, a Circle class.
-
Create a concrete class
Circlein the same package, as a subclass ofShape.Create the class just like before. Add
extends Shapemanually. The declaration is now underwaved in red. This is because we have not yet implemented the abstract method inShape. Ignore this error for now. -
The class should have three public int fields — an x coordinate, a y coordinate, and a radius.
Add these fields manually. -
Add a constructor with three arguments (x, y and radius), which saves the values of the arguments in the three fields and prints "A circle is constructed".
Like before, create this constructor by placing the cursor where the constructor should be and using
Code | Generate | Constructor: Alt-Insert. Mark the fields whose values should be initialized by the constructor (click the first, shift-click the last; using the keyboard: go to the first, press shift-down to extend the selection downwards) and press OK. Initializers are added automatically. Use sout to add the printout. -
Implement a concrete
draw()method that prints "A circle is drawn".To implement an abstract method, place the cursor where the method should be and use . Select the method(s) to be implemented in the dialog. Use sout again.
The third shape class is called Rectangle. Do you
remember how you did this before?
-
Create a concrete class
Rectangleas a subclass ofShape. The class should have four public integer fields — an x coordinate, a y coordinate, a width, and a height. -
Add a constructor with four arguments (x, y, width, and height), which saves the values in the four fields and prints "A rectangle is constructed".
-
Add a
draw()method that prints "A rectangle is drawn".
-
Create another class
ShapeTest, which has a main method.Use the template psvm to create the main method.
-
In the main method, you should allocate a
Shape[]array with 4-6 elements and fill it with circles and rectangles (created usingnew).Try using IDEA's "introduce variable" function. First, type the expression you want:
new Shape[5]. Then, use to introduce a new variable for this expression. You can enter a name for the new variable, or just accept the default name. Press Enter.This function is quite useful when you want to refactor a very long expression and separate it into smaller parts. Just select a subexpression and use to introduce a variable.
Note that the new variable is highlighted. This is because it is currently unused.
-
Make sure you didn't just allocate the
Shape[]array but that you actually created few circles and rectangles to place in the array! -
Then, iterate over all elements in the array and call their
draw()methods.Use the itar live template to iterate over a native Java array. Select and select itar from the menu; this is another way of selecting a live template.
Now you see why it is called a live template. A number of places in the generated code are outlined in red; these parts can be edited as part of the template. The first one, where the cursor is, is the loop variable, which is usually called
i; try typing "index" to rename the variable. Press TAB to reach the array over which we iterate; as you can see IDEA has correctly identified the two arrays that are available in this scope (argsand your own array). Pressing TAB again takes you to the variable in which each element is stored. Pressing TAB a final time deactivates the template and puts the cursor where you want to continue typing your code. -
Extend the code within the loop. If the shape is an instanceof Circle, you should also print the circle's x and y coordinates.
Start using IDEA's code completion. Type "if (sh[ctrl-space, select shape] inst[ctrl-space] Cir[ctrl-space]) {[enter]".
Try printing the value of the x field:
System.out.println("X coordinate is " + shape.x);As you notice, you can't do this because you must first cast
shapeto aCircle. Place the cursor within the wordshapeand press Ctrl-W. This selects a single word; repeated invocations select larger and larger structures, and Ctrl-Shift-W unselects one step at a time – try it!When you have selected
shape, select and then select "((type)expr)". You will get most likely getprintln(((Circle)shape).x), because IDEA analyzes the preceding code and sees that you have just checked whetherShapewas aCircle. If IDEA was correct, you press TAB; if it was wrong, you can select another type from the dropdown or simply overwrite the suggested type.Do the same thing for the y field.
What is printed when you run ShapeTest (see instructions below)? Which
methods and constructors are executed, and in which order? Make sure that you
understand why.
Compiling a project in IDEA
You can compile the entire project using , or use (Ctrl-F9) to only recompile the files that have changed and the files that depend on them.
Running a Java program in IDEA
Running a program (a class with a main() method) in IDEA requires a run configuration. You can create new run configurations in the following way:-
Select . In the dialog window, press the "+" button to create a new application configuration. Give it a name, and specify a main class (use the "..." button to select a class!).
"VM parameters" are given to the Java virtual machine. Normally this box can be left empty.
"Program parameters" are the command line parameters specified for your program (given as arguments to the main() method).
The "working directory" is the directory where your program is started, and is only relevant if your program opens files relative to the current directory.
In "Use classpath of module:" you should select the module the program "belongs" to. In your case this is quite simple: You only have one module.
Click .
You can then run your program by selecting a run configuration in the drop-down menu beside the green "play" button in the toolbar, and then pressing the "play" button.
As a shortcut, you can also create a temporary run configuration for any program with a main() method, and then immediately execute this run configuration, in the following way:
-
Right-click the editor for the class you want to run. Select "Run MyClass.main()".
Exercise 2: Data Hiding
In the previous exercise, all the fields you created were public. Now you realize your mistake: They should have been private! Make them private, introduce getters for all the fields (and setters, if you want to), and make sure that you use the getters and setters wherever this is necessary.
Go to the Circle class:
Select and type
"Cir" (which is auto-expanded), followed by Enter.
Choose .
Select the checkboxes for x, y
and radius to encapsulate these three fields.
Select Get Access to create getters, and unselect
Set Access (you do not want to create setters). Make the
encapsulated fields' visibility private, and the accessor methods'
visibility public. Unselect
Use accessors even when field is accessible, so that you
don't have to use the accessors within Circle, only
outside the class. Click . You
will get a refactoring preview, where the two uses of x and y in
ShapeTest are shown. Here you can unselect items that you don't
want to change, if any. Then you click .
Do the same thing in Rectangle. Since we never used
Rectangle's fields outside its class, the
refactoring preview only contains the fields themselves.
Exercise 3: Changing the Internal Representation
In this exercise, you will extend the program you wrote in Exercise 1
(Shape, Circle, Rectangle).
Create a new class Point. This class should have:
-
Two private integer fields,
xandy. -
A constructor with two arguments,
xandy.Use Generate Constructor as before.
-
Two accessor methods
getX()andgetY()that return thexandycoordinates.Create these methods by placing the cursor where they should be and then using (mark the fields for which you want to generate getters).
Rewrite ("manually") the Circle class so that it uses
a Point object instead of the old x
and y fields. The old constructor should still exist,
and should still take x and y arguments,
but instead of saving x and y directly, it
should create a new Point object that it stores in
a Point field. You must also rewrite the two getters.
Rewrite the Rectangle class in the same way.
Exercise 4: Implement equals() and HashCode
In this exercise, you will extend the program you wrote in exercise
3 by implementing equals() and hashCode() methods
for Point,
Rectangle and Circle. (If you don't know
what a hash code is, you could take a look at the definition in
the Java
Glossary or maybe
in Wikipedia.)
To automatically generate equals() and hashCode() methods in a
class, select and then select equals() and
HashCode(). Select the fields that should be included in the
comparison for
equals and then for hashCode. Should you
select all fields or only a few? This depends on which fields you
think have to be equal for two objects to be considered equal!
If there are non-primitive fields (object-type fields such as
the Point field in Circle
and Rectangle, then IDEA will ask you for a set of
non-null fields. A non-null field is a field whose value cannot
be null, so that IDEA does not have to insert a null check for
this field. If in doubt, do not select any non-null fields at
all. This is always safe, but may be slightly slower. In this
example, though, we know that the center of a Circle
is never null (always an actual Point).
Take a close look at the methods that are generated and ensure that they are what you intended. Never trust a code generation tool completely. Always double-check what has been generated. Tools are no substitute for knowing what you're doing!
Exercise 5: Using the Collections Framework
In this exercise you will begin using the Java Collections Framework. This framework will be part of lecture 4 in TDDC69, but the lab should provide sufficient guidance for you to continue even without having seen that lecture.
Your main task is to create two new data structures,
a Queue and a Stack. These structures
will use
the ArrayList
class of
the Java Collections
Framework, but unlike a plain ArrayList, they will not allow the
user to add or remove inner elements: you can only push and pop
elements at the correct "end".
-
Create a
Queueclass which does not extend any class. -
Add a
Listfield:private List myList.Since you haven't imported
java.util.List, IDEA will ask you whether you want to do so now. Press Alt-Enter to accept and choose the correct List class (the one from java.util). -
Add a constructor with no arguments, which creates an ArrayList.
If you use Generate Constructor as before, note that you should not mark any fields to be initialized by the constructor -- because the ArrayList should not be given as a parameter to the constructor, it should be created inside the constructor. Use "Select None" in the field dialog.
-
There are some methods from
ArrayListthat should be available inQueuetoo. For example, thesize()method should be available inQueue. You can forward or delegate these method calls to theQueueby adding a methodpublic int size()which simply returnsmyList.size(). (Keep reading!)The methods you should delegate to
ArrayListaresize(),isEmpty(),clear(), andcontains(Object).Select . Select the target
myList. Select the methods you want to delegate (click the first one, ctrl-click the second, ctrl-click the third, and so on). Press OK. -
Add the two new methods
void push(Object obj), which adds an object at the end of the list, andObject pop(), which both returns and removes the first object in the list.
Then write a Stack class, which is similar except that
pop() returns and removes the last object in the
list.
Press F5 while visiting the Queue class to create a clone of that
class. Select Stack as the new name. Change the new class according
to the instructions above.
Finally, you should write a test program that uses your new classes. For example,
you could write a test program that adds some strings to a Queue using
push(), and then pop()s all the strings, one at a time,
and prints them to the screen. Do the same thing using a Stack.
Exercise 6: The Collections Framework: Sorting and Iteration
Write a program that sorts all its command line arguments in alphabetical order and prints them to the screen.
First, create a list
(ArrayList
or LinkedList)
and add all command line arguments to that list.
Then, sort the list using the static utility
method Collections.sort(List list). This method is
placed in the utility class Collections rather than
in any specific list data type because it can be used
for any List.
After typing "Collections.sort(", press
ctrl-shift-space to see all items of the appropriate type, that
is, all items of type List. This is called
SmartType Completion and automatically filters out all items
except those of the correct type.
The reason for not using SmartType Completion always is that you
may have to go through an intermediate step before you reach the
intended type. For example, if you had wanted to
type Collections.sort(foo.getBar().getList()), you
would have had to use Basic Completion to
complete foo and
getBar(), and then you could have used SmartType
Completion to complete getList().
Finally, print the resulting list by iterating over it using the specialized "for" loop for arrays and collections.
To test this program, run it with some command line parameters to sort.
Create a new run configuration as described earlier in these instructions. Add your command line parameters in the "Program parameters" field. Do not add them in "VM parameters"; those parameters are given to the Java virtual machine, not to your program.
Exercise 7: Rename some Fields
Finally, you just realized that you don't want the x and y
coordinate fields in
Point to be named simply x
and y. Instead, they should be
named xCoord and yCoord. Rename them.
Let's suppose you were in the Circle class when you
got this idea. If you're not already there, go
to Circle using Ctrl-N.
Hold down Ctrl as you move the mouse around the code. You will see tooltips showing information about the items over which the pointer is hovering.
Now ctrl-click Point in the code. You will
automatically be moved to the Point class.
In Point, go to the x field and select
. Enter
the new name for this field and press Enter. IDEA will ask you
whether it should also rename the getter; please do so.
If you have referred to x in "plain text", for example in comments, you will get a refactoring preview where you can choose which occurrences of "x" should be changed – IDEA knows what to change in the code, but in comments, it is impossible to tell whether a certain "x" refers to the field Point.x or to something else. After verifying that everything is correct in the refactoring preview, click .
Do the same thing for y.
The end
That's it: You've finished the IDEA exercise. You should now ask the lab assistant to take a look at your code. When this is done, you can hand in the code according to the instructions. If no lab assistant is available right now, simply continue with the next lab.
| © 2005-2012 Jonas Kvarnström |
Sidansvarig: Jonas Kvarnström
Senast uppdaterad: 2012-08-31
