As a teacher of some computer programming languages and database for some time now, I cannot help but notice the difficulty of students during the initial learning of programming in Java. These difficulties are related to the amount of resources, rules and details of Java itself. However, once these main difficulties are overcome, the student has an excellent working tool to demonstrate their full potential and explore the almost endless possibilities only limited by his/her creativity.
The context of this third and last part focus on practical aspects of programming in Java. We discuss details of some Java statements that beginners can't understand right away and explain how to address this difficulty.
Technical difficulties in Java
One of the major technical difficulties that every beginner in Java go through is the rigor required when using characters in upper and lower case, also known as case sensitivity. This means that if an identifier, such as a variable for example, is defined by the word help the programmer may not refer to this identifier as Help. This rule where uppercase and lowercase letters make different elements of the language is applied in various parts of the program as identifiers for variables, methods, classes, interfaces, etc. Beginners will feel very hard to follow this strict rule, especially those who have programmed in HTML where there is no such restriction.
Another technical aspect that frustrates many developers new to Java is the complexity required to analyze and find out where is the error in the program after receiving a message from the compiler. Although there are several features in IDEs like Eclipse and NetBeans, there are situations where a simple syntax error can cause a lot of errors messages returned from the compiler. The indication of the line number and file where the error is helps, but unfortunately you must have tons of experience to discovering where is the location of the code that is generating one or more errors detected by the compiler. The recommendation here is get more experience in recognizing the main error messages until it becomes something like the gear shifting in a car with manual transmission: when we learn to drive a car with manual transmission we need to look at and see where the right exchange position of the lever to each gear is. As we gain experience driving we automatically memorized the position of the gears and do not need to look at the lever again.
The creation of jar files is another topic that confuses many beginners. This concept of grouping compiled files together into a single compacted package is not intuitive and is something that was introduced by Java in order to facilitate the deployment process and also to organize the files generated during compilation. However, who is learning to create jar files find this process hard because the association between compound names of packages and operating system folders and the complicated steps required to compile and build the package. Obviously, these tasks are facilitated by tools, however I try to insist on manual creation of package for Java classes because once a student learns well how to do in the manual way he/she hardly to forget the procedure.
The use of access modifiers is also something that confuses many students especially when a variable is defined with only the data type and without an explicit access modifier. In this case, the variable will have an access modifier which is different from the private access modifier. For example, suppose the two packages presented in Figure 1. The package called One contains two classes: Alpha and Beta. The package called Two contains two classes called AlphaSub and Gamma. The class AlphaSub inherits from class Alpha.
Figure 1. Packages One and Two with the classes Alpha, Beta, Gamma and AlphaSub.
If we created an attribute within the class Alpha to represent some characteristic of this class, what would be the accessibility of this attribute? This depends on its access modifier. Table 1 shows what would be the accessibility of this new attribute in the Alpha class over other classes according to the types of access modifiers available in Java.
Table 1. List of access modifiers and accessibility of a new attribute in the class Alpha..
According to Table 1, if an attribute of the Alpha class was created without an access modified it could be accessed within the classes Alpha and Beta because they are from the same package. If this same attribute had been defined with private access modifier it could only be accessed within the class Alpha. Table 1 shows that identifiers, such as variables or methods, without access modifiers do not have the same accessibility of identifiers with the access modifier private.
Another technical aspect of language that causes confusion is the syntax for doing casting in Java, i.e. the implicit conversion. Suppose the following lines from a Java source code:
long bigValue = 99L;
int squashed = (int)(bigValue); // Do the casting from long to int
The second line makes a casting in the variable bigValue to convert its integer type and places the converted value in the new variable called squashed. The way to do this casting through the use of the type for which you want to convert in parentheses and in the right side of the equal operator is not unique to Java, but it is confusing to many students who are beginning to use this language. The reason for the confusion is related to the use of parentheses that are usually associated with function calls and also to indicate what should be done first in a complex arithmetic expression. Thus, this syntax requires the student to remember that the use of parentheses for casting is regarded as an operator that overloads the definition of already widespread use of parentheses in method calls and functions explained in logic programming courses that use pseudo-code. The complexity increases when a student finds many castings chained that call a method from the object that was obtained after the application of a casting, something like ((int)(bigValue)).Method().
Besides the aspects of syntax also there is also a great difficulty to understand codes that contain complex programming logic and that was not commented. For example, the code in Listing 1 shows an excerpt from a Java program that works with arrays.
Listing 1. Example of search an item inside an array.
public static void main(String args) throws IOException
arr = new int;
int nElems = 0;
arr = 77; // Insert 10 elements in the array
arr = 99;
arr = 44;
arr = 55;
arr = 22;
arr = 88;
arr = 11;
arr = 00;
arr = 66;
arr = 33;
nElems = 10; // Put the number of elements in the variable nElems
searchKey = 66; // Search for the index that contain the element with the 66 value
for(j=0; j<nElems; j++) // Do a loop in the array
if(arr[j] == searchKey) // Found the item?
break; // If found, get out of the loop
if(j == nElems) // Ask if the element was found
System.out.println("Não achou o elemento: " + searchKey); // Did not found it
System.out.println("Encontrou. Índice do array:" + j); // Found it
The code in Listing 1 first creates an array of integers and then inserts ten values in the array. Then the code inserts the value 66 in the variable searchKey and creates a loop that finds the index of the element in the array searched.
The difficulty encountered by students in understanding the code in Listing 1 is related to the logic of the programmer, who developed this code in such a way that if the element was found in the array the value of the loop counter variable j is equal to the index of the searched element. If the element is not found the value of the counter variable j is equal to the number of array elements, which is equal to the last array index + 1, whose value is stored in the variable nElems. This kind of logic makes it easy to check after the loop, because the if statement only asks if the value of j is equal to the total number of array elements. If so, the element was not found. If not the element's index is equal to the value of j. Although the program code is short it becomes complex to understand especially for those who are starting to program and have some difficulty with the Java syntax.
Finally, one of the difficulties encountered by those who program in Java for the Web is related to the amount of tasks needed to be performed when you do not use an IDE. When you are programming Servlets must first understand the context of implementation, the class to be inherited and the method to be overridden. In addition, you must compile the file, put it in a Servlet Container inside a Server that meets the J2EE specification and configure the XML file with the descriptor.
For the student who is beginning to program in Java there are many tasks to be performed and even with the use of facilitators such as annotations or tools that deploy servlets automatically the programmer still need to remember many details related to the execution context. Unfortunately, Java technology requires that the student knows piles and piles of concepts that end up overshadowing the primary goal of any developer: the resolution of a problem in a systematic way.
When the student is beginning to learn how to program he/she has bear in mind that the main goal is to solve a problem. However, it is common to find students that when they finish reading the statement of the problem they already start to write code without even thinking a little bit in the structure of the problem. To avoid this kind of behavior is recommended to always think in the basic three blocks of a program: input, processing and output. Usually the input is related to the capture of data from the keyboard, treatment of parameters or reading from a data source. The processing is related to what needs to be done and is commonly composed of conditional structures (ifs, switches, etc.) and loops (for, while, do, etc.). The output usually takes the form of messages on the screen, writing to a resource or the return of a value.
The lack of thought in object oriented programming is another relatively common error among beginner Java students. Usually this habit is identified by methods with a lot of code, excessive use of attributes, classes that do not have relationships (inheritance, aggregation, composition, etc.) and the wide use of basic parameters types like int, String, and boolean. A tip to help think about object oriented programming instead of structured programming is increasingly focusing on modeling, specification and abstraction and leave the encoding in the background until the model is good enough.
Another common mistake made by students concerns the desire to produce code readable only by the original creator of the program. Programming is a task that has increasingly become a collective activity. This means that if the code is readable for those who did not create it this code could be considered better. This error is solved by applying rules and checking metric values that reinforce techniques such as refactoring, use of commentaries, application of design patterns, code review and pair programming.
The lack of tests that cover various possible flow of execution of the code is another very common mistake made by beginners and some experts programmers. When programming is common to create conditional and repeating structures that depend on values generated from the use of the program to generate the flow of execution, such as upper limits in the for statement, variables used in logical expressions of the if statement and others. However, students often make the mistake of not carrying out enough tests to ensure that all program instructions are executed, regardless of where in the program these instructions are. Failing in these tests represents a great risk when the program is run by a user because the data, system, or application in which this program is part may be damaged in some way.
This article discussed some aspects related to the difficulty of beginners in Java programming. The focus of this article was to present what are the difficulties encountered by beginners as well as some solutions to facilitate the learning of Java programming. The article pointed out some ideas for solving conceptual and technical difficulties that students and learners encounter when they are starting to program in Java.
Finally, I would like to quote a passage from a book that talks about how to solve problems. Although this book focuses on mathematical examples, one can easily translate what is presented in the book to the area of programming.
"When a student makes mistakes really stupid or is annoyingly slow the cause is always the same: he/she has no desire to solve the problem, do not even want to understand it properly and, as a consequence, was not even considered it. Therefore, the teacher who really wants to help the student must first of all stimulate their curiosity, embed in him/her a desire to solve the problem. The teacher should also give the student some time to make the decision and to dedicate herself/himself to the task.
Teach problem solving is to educate the will. In solving problems that are not very easy the student learns to persevere in spite of failures, to appreciate little progress, to wait for the essential idea and to concentrate their full potential when it appears. If the student does not have, at school, the opportunity to become familiar with the various emotions that arise in the struggle for the solution his/her mathematical education has failed in the single most vital point. "
These two paragraphs above were taken from the second edition of the book "How to Solve It" written by the mathematician G. Polya, Princeton University Press, 1957.
This article ends here with some advice for the beginner in Java: the difficulties encountered when starting to learn Java also have been experienced by others. This means that is normal to encounter some bumps along the way when you're learning something new. But it is important not to give up and keep walking forward without looking back.
The Karatsuba algorithm used for the multiplication of two integers.