Monday, July 4, 2011

Java Common Mistakes (Part 3)

1. Accessing non-static member variables from static methods (such as main)
Particularly when first introduced to Java, Many programmers have problems with accessing member variables from their main method. The method signature for main is marked static - meaning that we don't need to create an instance of the class to invoke the main method. For example, a Java Virtual Machine (JVM) could call the class MyApplication like this :-

MyApplication.main ( command_line_args );

This means, however, that there isn't an instance of MyApplication - it doesn't have any member variables to access! Take for example the following application, which will generate a compiler error message.

public class MyApplication {
public String my_member_variable = "somedata";
public static void main (String args[]) {
// Access a non-static member from static method
System.out.println ("This generates a compiler error" + my_member_variable );
}
}

If you want to access its member variables from a non-static method (like main), you must create an instance of the object. Here's a simple example of how to correctly write code to access non-static member variables, by first creating an instance of the object.

public class MyApplication {
public String my_member_variable = "somedata";
public static void main (String args[]) {
MyApplication myApplication = new MyApplication();
// Access member variable of myApplication
System.out.println ("This WON'T generate a compilation error" + myApplication.my_member_variable);
}
}


2. Null pointers
Null pointers are one of the most common errors that Java programmers make. Compilers can't check this one for you - it will only surface at runtime, and if you don't discover it, your users certainly will.

When an attempt to access an object is made, and the reference to that object is null, a NullPointerException will be thrown. The cause of null pointers can be varied, but generally it means that either you haven't initialized an object, or you haven't checked the return value of a function.

Many functions return null to indicate an error condition - but unless you check your return values, you'll never know what's happening. Since the cause is an error condition, normal testing may not pick it up - which means that your users will end up discovering the problem for you. If the API function indicates that null may be returned, be sure to check this before using the object reference!

Another cause is where your initialization has been sloppy, or where it is conditional.

Sometimes your variables (the array of strings) will be initialized, and other times they won't. One easy solution is to check BEFORE you attempt to access a variable in an array that it is not equal to null.

3. Confusion over passing by value, and passing by reference
This can be a frustrating problem to diagnose, because when you look at the code, you might be sure that its passing by reference, but find that its actually being passed by value. Java uses both, so you need to understand when you're passing by value, and when you're passing by reference.

When you pass a primitive data type, such as a char, int, float, or double, to a function then you are passing by value. That means that a copy of the data type is duplicated, and passed to the function.
If the function chooses to modify that value, it will be modifying the copy only. Once the function finishes, and control is returned to the returning function, the "real" variable will be untouched, and no changes will have been saved. If you need to modify a primitive data type, make it a return value for a function, or wrap it inside an object

When you pass a Java object, such as an array, a vector, or a string, to a function then you are passing by reference. Yes - a String is actually an object, not a primitive data type. So that means that if you pass an object to a function, you are passing a reference to it, not a duplicate. Any changes you make to the object's member variables will be permanent - which can be either good or bad, depending on whether this was what you intended.

On a side note, since String contains no methods to modify its contents, you might as well be passing by value.


4. In Java, a single equal sign ( = ) is an entirely different operator than a double equal sign ( == ). In most cases, use the double equal sign when creating a loop or conditional statement and use the single equal sign everywhere else. For example:
To compare a and b for equality, use a==b; (note the double equal sign).
Where b has the same value as a, use a=b; (note the single equal sign).

5. Forget to initialize Object Arrays
A Java array declared for an object type is really an array of object references. Creating the array, with new, simply creates empty references. The elements of the array are all set to null. You have to set each element to a real object reference in order to fill the array. Many students misunderstand this and they think that creating an object array creates all the actual objects. (In many cases, this is a concept that the student carries over from C++, where creating an array of objects does create all the objects by calling their default constructor.)

In the following example, the student wants to create three StringBuffer objects to hold some data. This code will compile, but will throw a NullPointerException on the last line where one of the (non-existent) objects is used.

Mistake Example:

// Create an array of data buffers
StringBuffer[] myTempBuffers;
myTempBuffers = new StringBuffer[3];
myTempBuffers[0].append(data);

To correct this problem, it is important to remember to initialize the elements of any Java array.

// Create an array of data buffers and initialize it.
StringBuffer[] myTempBuffers;
myTempBuffers = new StringBuffer[3];
for (int ix = 0; ix < myTempBuffers.length; ix++)
myTempBuffers[ix] = new StringBuffer();
myTempBuffers[0].append(data);

6. Putting several public classes in one file
Java source code files have a special relationship to the classes in those files.
The rules can be summarized as follows:

1. Any Java class is defined in exactly one source file
2. At most one public class may be defined by any one source file
3. If a public class appears in a source file, the name of the file and the name of the class must be the same (case sensitive).

Sometimes, a student will forget the second rule in their rush to code up a lab exercise or project. They'll put two or more public classes into a source file.

7. Forgetting to make sure that system resources (network or database connections, streams) are freed by calling close() in a finally block. Assuming that you can't produce a memory leak in Java because it has garbage collection

8. Using the Singleton design pattern in an environment with multiple class loaders

9. Omitting break from case statements

10. Using a variable before it is given a value

11. Forgetting that arguments are passed by reference to methods if they are objects

12. Mistyping the name of a method when overriding

13. Forgetting that Java is zero-indexed

14. Capitalization errors
This is one of the most frequent errors that we all make. It's so simple to do, and sometimes one can look at an uncapitalized variable or method and still not spot the problem. You can easily train yourself to make less of them. There's a very simple trick you can learn :-

1. all methods and member variables in the Java API begin with lowercase letters
2. all methods and member variables use capitalization where a new word begins e.g - getDoubleValue()

15. Hashtable, HashMap and HashSet are overrated
These classes are extremely popular. Because they have great usability for the developer. Unfortunately they are also horribly inefficient. Hashtable and HashMap wrap every key/value pair into an Entry wrapper object. An Entry object is surprisingly large. Not only does it hold a reference to key and value, but also stores the hash code and a forward reference to the next Entry of the hash bucket. When you look at heap dumps with a memory analyzer you will be shocked by how much space is wasted by them in large applications like an application server. When you look at the source code of HashSet you will see that the developers were extremely lazy and just used a HashMap in the backend!

Before using any of these classes, think again. IdentityHashMap can be a viable alternative. But be careful, it intentionally breaks the Map interface. It is much more memory efficient by implementing an open hashtable (no buckets), doesn't need an Entry wrapper and uses a simple Object[] as its backend. Instead of a HashSet a simple ArrayList may do similarly well (you can use contains(Object)) as long as it's small and lookups are rare.
For Sets that contain only a handful of entries the whole hashing is overkill and the memory wasted for the HashMap backend plus the wrapper objects is just nuts. Just use an ArrayList or even an array.

Friday, July 1, 2011

The Principles of Object Oriented Design/Classes

The principles of object oriented design are abbreviated under the acronym SOLID which stands for:

S - The Single Responsibility Principle (SRP)
O - The Open Closed Principle (OCP)
L - The Liskov Substitution Principle (LSP)
I - The Interface Segretation Principle (ISP)
D - The Dependency Inversion Principle (DIP)

These principles represent
1. a set of rules that allows us to improve the way we design and
2. set up the dependencies between our classes and
3. it allows us to create more flexible, maintainable, reusable and robust code.

Thursday, March 10, 2011

Inheritance and Polymorphism

Inheritance and polymorphism are really just two ways of looking at the same class relationship. Inheritance is looking at the class hierarchy from the bottom up. A subclass inherits behaviors and attributes from its superclass. A subclass automatically possesses certain behaviors and/or attributes simply because it is classified as being a subclass of an entity that possesses those behaviors and/or attributes.

Inheritance is useful from a code reuse perspective. Any (non-private) code in the superclass does not have to be replicated in any of the subclasses because they will automatically inherit those behaviors and attributes. However, one must be very careful when transferring common code from the subclasses to the superclass, as the proper abstraction represented by the superclass may be broken.

Polymorphism, on the other hand, is looking at the class hierarchy from the top down. Any subclass can be used anywhere the superclass is needed because the subclasses are all abstractly equivalent to the superclass. Different behaviors may arise because the subclasses may all have different implementations of the abstract behaviors defined in the superclass.

Polymorphism is arguably the more useful perspective in an object-oriented programming paradigm. Polymorphism describes how an entity of a lower abstraction level can be substituted for an entity of a higher abstraction level and in the process, change the overall behavior of the original system. This will be the cornerstone that enables us to build OO systems that are flexible, extensible, robust and correct.

Thursday, December 23, 2010

UML one liner

1. The UML gives everyone from business analyst to designer to programmer a common vocabulary to talk about software design.
2. Use Case diagrams help you specify the user goals that the system must carry out.
3. Class diagrams show the physical structure of the objects in the system and their static relationships.
4. Sequence and collaboration diagrams show the dynamic interactions between instances used to carry out a single use case.
5. Use case diagrams describe what a system does from the standpoint of an external observer. The emphasis is on what a system does rather than how.
6. A model is an abstraction of the underlying problem.
7. The domain is the actual world from which the problem comes.
8. Models consist of objects that interact by sending each other messages.
9. Objects have things they know (attributes) and things they can do (behaviors or operations). The values of an object's attributes determine its state.
10. Classes are the "blueprints" for objects. A class wraps attributes (data) and behaviors (methods or functions) into a single distinct entity.
11. Objects are instances of classes.
12. An actor is a person, organization, or external system that plays a role in one or more interactions with your system.
13. Use Cases are used to specify the functional requirements of the system.

Wednesday, December 22, 2010

UML: Unified Modeling Language

Unified Modeling Language or UML is the standard language for describing, visualizing, and documenting the object-oriented (OO) systems. UML is a collection of a variety of diagrams for different purposes and each type of diagram models a particular aspect of OO design in an easy to understand and visual manner.

The UML standard specifies exactly how the diagrams are to be drawn and what each component in the diagram means. UML is not dependent on any particular programming language, instead it focuses one the fundamental concepts and ideas that model a system.

It is a standardized language in which to specify the artefacts and components of a software system, how the diagrams are to be drawn and what each component in the diagram means. It is important to understand that the UML describes a notation and not a process. It does not put forth a single method or process of design, but rather is a standardized tool that can be used in a design process.

The UML gives everyone from business analyst to designer to programmer a common vocabulary to talk about software design.

Friday, October 1, 2010

Programmatic instantiation of Components like servlets, filters, and listeners

With programmatic definition, we can instantiate components programmatically and then configure them. Servlet 3.0 Specification supports dynamic instantiation of servlets and filters.

In this example, we will see how you might programmatically instantiate servlets, filters, and listeners.

@WebListener
public class MyServletContextListener implements ServletContextListener {

public void contextInitialized(ServletContextEvent sce) {
LOG.info("Context Listener Initialized");
doProgrammaticRegistration(sce.getServletContext());
}

private void doProgrammaticRegistration(ServletContext sc) {

// servlet definition
ServletRegistration.Dynamic dynaServlet = sc.addServlet(
"MyProgrammaticServlet",
"com.servlets.MyProgrammaticServlet");
dynaServlet.addMapping("/myprogrammaticservlet");

// filter definition
FilterRegistration.Dynamic dynaFilter = sc.addFilter(
"MyProgrammaticFilter",
"com.filters.MyProgrammaticFilter");
EnumSet dispatcherType = EnumSet.of(
DispatcherType.REQUEST, DispatcherType.FORWARD);
dynaFilter.addMappingForServletNames(dispatcherType, true,
"MyProgrammaticServlet");
}
}

As shown, during context initialization, we instantiate a new servlet and returned class ServletRegistration.Dynamic instance is used to configure the appropriate servlet mapping. We do the similar steps with a filter. These steps are similar to what would have happened when a servlet container encountered the <servlet>, <servlet-mapping>, <filter> and <filter-mapping> elements in a web deployment descriptor.

As it can be seen in the next code listings, the servlet and filter are rather straightforward. Since the configuration occurs programmatically, they do not even need any annotations to be used.

//Note: not even an annotation is required
public class MyProgrammaticFilter implements Filter {
private final Logger LOG = Logger.getLogger("MyProgrammaticFilter");

public void destroy() { }

public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws ServletException, IOException {

LOG.info("Filtering: " + ((HttpServletRequest)req).getRequestURI());
chain.doFilter(req, resp);
}

public void init(FilterConfig config) throws ServletException {
LOG.info("Filter: " + "Initializing ProgrammaticFilter");
}
}

//Note: not even an annotation is required.
public class MyProgrammaticServlet extends HttpServlet {
private final Logger LOG = Logger.getLogger("MyProgrammaticServlet");

protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
LOG.info("Within request : " + getServletName());
String html = "Added programmatically (no annotation/web.xml entries): " + new Date();

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(html);
}
}

Hope this will help.

Servlet 3.0 Annotations

Servlet 3.0 Specification has a number of new features and one of them is annotation. When an application loads, all classes into the application are examined for presence of the annotations. When these annotations are found on a particular class, the container registers instances of the classes as Listeners, Servlets, or Filters based on the annotation.
Servlet 3.0 Specification Annotations are as follows.

* @WebServlet
* @WebFilter
* @WebInitParam
* @WebListner
* @MultipartConfig

@WebServlet
This annotation is used to define a Servlet component in a web application and defines the metadata about the servlet being declared.
Classes annotated with @WebServlet annotation must extend javax.servlet.http.HttpServlet class.
@WebServlet annotation annotation has the following attributes.
* name
* description
* value
* urlPatterns
* initParams
* loadOnStartup
* asyncSupported
* smallIcon
* largeIcon
Note: the spec mandates either value or urlPatterns attribute be specififed.

Example:
@WebServlet(name = "myservlet", urlPatterns = { "/myservlet" })
public class MyServletExample extends HttpServlet {
}

@WebFilter
This annotation is used to define a filter in web application. The classes annotated with @WebFilter annotation must implement javax.servlet.Filter interface.
The @WebFilter annotation has the following attributes
* filterName
* description
* displayName
* initParams
* servletNames
* value
* urlPatterns
* dispatcherTypes
* asyncSupported

Example:
@WebFilter(filterName="samplefilter", urlPatterns={"/foo/*", "/bar"})
public class MyServletSampleFilter implements Filter {
}

@WebInitParam
This annotation is used to specify any init parameters that must be passed to the Servlet or the Filter.
The annotation defines the following attributes:
* name
* value
* description

Example:
@WebServlet(value="/hello",
initParams = {
@WebInitParam(name="name1", value="Hello "),
@WebInitParam(name="name2", value=" World!")
})
public class MyHelloServletExample extends HttpServlet {
}

@WebListner
This annotation is used to define a listener. The @WebListener annotation is used to register the following types of listeners
1. Context Listener (javax.servlet.ServletContextListener)
2. Context Attribute Listener (javax.servlet.ServletContextAttributeListener)
3. Servlet Request Listener (javax.servlet.ServletRequestListener)
4. Servlet Request Attribute Listener (javax.servlet.ServletRequestAttributeListener)
5. Http Session Listener (javax.servlet.http.HttpSessionListener)
6. Http Session Attribute Listener (javax.servlet.http.HttpSessionAttributeListener)

@WebListener is the easiest to use. Registering ServletContextListener.

Example:
@WebListener()
public class MySampleContextListner extends ServletContextListner {
public void contextInitialized(ServletContextEvent event) {
//do some thing on application init
}

public void contextDestroyed(ServletContextEvent event) {
//do some thing on application destroy
}
}

@MultipartConfig
Servlet 3.0 specification comes with the built in file upload support. This annotation, when specified on a Servlet, indicates that the request it expects is of type mime/multipart. The HttpServletRequest object of the corresponding servlet makes available the mime attachments via the getParts and getPart methods to iterate over the various mime attachments.

The @MultipartConfig annotation can be used to specify the location where the files can be stored, maximum size of the file being uploaded, maximum request size and the size threshold after which the file will be written to the disk. There is any equivalent element in web.xml that can be used for the same purpose.

@MultipartConfig annotation declares the following attributes:
* location
* maxFileSize
* maxRequestSize
* fileSizeThreshold

Example:
@WebServlet(name="UploadServlet", urlPatterns={"/upload"})
@MultipartConfig(location="d://tmp")
public class MyServletExample extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//target directory and location are the same.
req.getPart("content").write("file.txt");
}
}

Hope this will help.