Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, July 24, 2012

Java O-O Concepts

                                       Classes and objects                                      
class describes the data and the methods of its objects. Every object belongs to some class.
An object contains data (instance variables) representing its state, and instance methods, which are the things it can do.
A class may also contain its own data (class variables) and class methods. The keyword static denotes such data and methods.
An object "knows" what class it belongs to, and can use class data and class methods, but a class does not "know" about its objects.
Classes form a hierarchy (tree), with Object at the root. Every class, except Object, has one and only one immediate superclass, but that class has its own immediate superclass, and so on all the way up to Object at the root, and all of these are superclasses of the class. The keyword extends denotes the immediate superclass.
A class contains one or more constructors for making new objects of that class. If (and only if) the programmer does not write a constructor, Java provides a default constructor with no arguments. The default constructor sets instance variables as follows: numeric types are set to zero, boolean variables are set to falsechar variables are set to '\0', and object variables are set to null.
The purpose of a constructor is to create an object in a valid state. No other work should be done in a constructor.
When a constructor executes, the very first thing it does is call the constructor for its superclass. You can write this constructor call explicitly, with super(...);, or you can let it implicitly call the default constructor.
A constructor for a class can call another constructor for the same class by putting this(...); as the first thing in the constructor. This allows you to avoid repeating code.
Objects are declared just like primitive values, with the syntax ClassName objectName; but are not defined (allocated space and given a value) until you create one by calling the constructor with the keyword new.
Classes inherit all the data and all the methods of their superclasses, but do not inherit constructors.
You can assign an object of a class to a variable (that is, variable = object) declared to be of that class or any of its superclasses (thus, you can assign any object to a variable of type Object). If you have an object in a more general variable or expression (for example, a String value in an Object variable), you can cast it to the correct type with the syntax (type)variable or (type)(expression).
Casting an object to a more general type is called upcasting, and is always legal. Casting an object to a more specific type is called downcasting, and Java inserts a run-time check to ensure that the cast is legal. Casting does not affect what the object is, it only changes what fields and methods are available on the object at the position the cast occurs.
A class that is declared as final may not be extended by subclasses.
The instanceof operator tests whether its left operand (an object) is an instance of its right operand (a class or interface). The result will be true if the right operand is the class or any superclass of the object. Well-designed programs have very little need for the instanceof operator.
A Java source file may contain only one public class, though it may contain additional non-public classes. The name of the file must be the same as the name of the class, but with the .java extension.
Classes should be as self-contained and independent as it is reasonable to make them. The interface (the fields and methods it makes available outside the class) should be kept small.
An object is responsible for keeping itself in a valid state. Therefore, it should limit write access to essential fields.
                               Access                                                   

Variables and methods are accessed by name.
There are three dimensions to accessing names: namespaces, scope, and access modifiers.
Java uses six different namespaces: package names, type names, field (variable) names, method names, local variable names (including parameters), and labels. Identical names of different types do not conflict; for example, a method may be named the same as a local variable. However, it's best to avoid reusing names in this manner.
The scope of a name is the part of a class in which it can be seen.
  • A variable declared anywhere in a class can be seen everywhere in a class.
  • The scope of a method's formal parameters is the entire method.
  • The scope of a variable declared in a block (indicated by braces, { }) extends from the declaration to the closing brace. A method body is always a block.
  • The scope of a variable declared in the initialization part of a for loop is the entire for loop.
Class variables and class methods (denoted by the keyword static) can be used anywhere within the class.
Instance variables and instance methods can be used anywhere within the class except in static methods.
Within an instance method, the keyword this refers to the object currently executing the method.
When an instance variable and a formal parameter have the same name, the name refers to the formal parameter; prefix the name with this. to refer to the instance variable.
To refer to an instance name in a different object, use the syntax otherObject.name. To refer to a class (static) name in a different class, use the syntax OtherClass.name.
You can refer to a name (class or instance) in another class if and only if you have access privileges. Possible access privileges are:
  • public : You can access it from anywhere.
  • protected : You can access it from any other class in the same directory (folder), or from any subclass.
  • package (default) : You can access it from any other class in the same directory.
  • private : You cannot access it from outside the class.
You can refer to a name in a class in another package in either of two ways:
  • You can use the fully-qualified name, for instance java.awt.Color.red
  • You can import a specific class or (with *) all classes in a given package, then use the name as if you had defined it yourself.

Methods


method is a named executable chunk of code.
All executable statements must be in methods. (Exception: "initialization blocks," not covered here.)
A method has a signature consisting of its name and the number and types of its parameters (also called "arguments"). The parameters in the method declaration are its formal parameters.
A method has a return type, which is not part of its signature. If the return type is other than void, then the method must return a value of the specified type.
A method may have local variables (also called method variables). These follow the scope rules, and are never available anywhere outside the method. The concepts staticpublicprotected, package, and private do not apply to local variables. Formal parameters are a kind of local variable.
Every method must have a signature that is unique within its class. Methods in other classes (even superclasses and subclasses) may have the same signature.
An instance method is executed by sending a message to its object. The message consists of: a reference to the object (typically its name), a dot, the name of the method, and zero or more actual parameters enclosed in parentheses.
A class method is executed by sending a message to the class. The message consists of: the name of the class, a dot, the name of the method, and zero or more actual parameters enclosed in parentheses.
When a message is sent, and before the method executes, the values of the actual parameters are copied into the corresponding formal parameters. Then the method body executes. Then the return value replaces the message, and all local names are forgotten.

Polymorphism

The two kinds of polymorphism are overloading and overriding.Overloading occurs when a class declares two or more methods with the same name but different signatures. When a message is sent to an object or class with overloaded methods, the method with the best matching signature is the one that is used ("invoked").
  • If the message and the method have a different number of parameters, no match is possible.
  • If the message and the method have exactly the same types of parameters, that is the best possible match.
  • Messages with specific actual parameter types can invoke methods with more general formal parameter types. For example if the formal parameter type is Object, an actual parameter of typeString is acceptable (since a String value can be assigned to an Object variable). If the formal parameter is type double, an actual parameter of type int can be used (for similar reasons).
  • If there is no clear best match, Java reports a syntax error.
Overriding occurs when a class declares a method with the same signature as that of an inherited method. When a message is sent to the object (or class, if it's a class method), the locally-defined method is the one that is used.
  • Overriding is commonly used to make methods more specific.
  • When a method name is overridden, you can still invoke the superclass' method (from inside the class) with the syntax super.name(parameters).
  • From outside the class, you can cast an object to its superclass and then invoke the method, with the syntax ((Superclass)object).name(parameters).
  • Although the return type is not part of the signature, an overriding must have the same return type as the method it overrides.
  • The overriding method may not throw any exception types in addition to those thrown by the method it overrides (although it may throw fewer exception types).
A class can declare a variable with the same name as an inherited variable, thus "hiding" or shadowing the inherited version. (This is like overriding, but for variables.)
  • Shadowing should be avoided.
  • When shadowing does happen, you can access the superclass name by either the syntax super.name or by casting the object to its superclass, with the syntax ((Superclass)object).name.
Interfaces and abstract classes

The purpose of interfaces and abstract methods is to ensure that any classes derived from them will share the same set of methods.An abstract method is a method that is declared but not defined. It is declared with the keyword abstract, and has a header like any other method, but ends with a semicolon instead of a method body.
An abstract class is one that contains one or more abstract methods; it must itself be declared with the abstract keyword. A class may be declared abstract even if it does not contain any abstract methods. A non-abstract class is sometimes called a concrete class.
An abstract class cannot be instantiated; that is, no objects of that class can be created. Instead, you can create subclasses that define (in the usual way) the inherited abstract methods, and these subclasses can be instantiated.
An interface is declared with the keyword interface instead of the keyword class. An interface may contain only abstract methods and definitions of constants (that is, final variables). The keywordabstract before each method is optional.
A class may extend only one other class, but it may implement any number of interfaces. The syntax is: class Class extends Superclass implements Interface1,Interface2, .... When a class extends an interface, it may implement (define) some or all of the inherited abstract methods. A class must itself be declared abstract if it inherits abstract methods that it does not define.
A variable may be declared to have a type that is an abstract class or an interface; any object whose type implements or extends the variable's type may be assigned to that variable. The instanceofoperator may take a class, abstract class, or interface as its right operand.

Inner classes

An inner class is a class declared within another class. The four kinds of inner class are: (1) member class, (2) static member class, (3) local inner class, and (4) anonymous inner class. Unlike "outer" classes, the usual scope rules apply to inner classes.
member class is defined at the top level of the class, along with fields and methods. It may have the same access modifiers as variables (publicprotectedpackagestaticfinal), and is accessed in much the same way as variables of that class.
static member class is defined like a member class, but with the keyword static. Despite its position inside another class, a static member class is actually an "outer" class--it has no special access to names in its containing class. To refer to the static inner class from a class outside the containing class, use the syntax OuterClassName.InnerClassName. A static member class may contain static fields and methods.
local inner class is defined within a method, and the usual scope rules apply to it. It is only accessible within that method, therefore access restrictions (publicprotectedpackage) do not apply. However, because objects (and their methods) created from this class may persist after the method returns, a local inner class may not refer to parameters or non-final local variables or of the method.
An anonymous inner class is one that is declared and used to create one object (typically as a parameter to a method), all within a single statement. The anonymous inner class may either extend a class or implement an interface; the syntax is the same: new Super(parameters){methods}, where Super is the name of the extended class or implemented interface, parameters are the parameters to the constructor for that class or interface (usually just ()), and methods override any inherited methods.
The keyword static may not be used within any inner class except a static member class.


Thursday, March 15, 2012

Java 7:Top Features

Java 7 (codename Dolphin) is a major update to Java that was launched on July 7, 2011.

The Java 7 release initially included many JSRs with exciting features, like support for closures, which were later deferred to Java 8 in order to release JSRs that are already done.

Java Releases

Here’s a quick snapshot of the past Java release dates (table 1). There are several small new features and enhancements in Java 7. Out of the 28 features that I looked at, here are the ones that I found useful.


 New features and enhancements

#1 Strings in switch

In programming, we often encounter situations where we need to do different things based on different values of a variable. For Boolean variables, an if-then-else statement is the perfect way of branching code. For primitive variable types we use the switch statement. However, for String variables, we tend to resort to using multiple if-then-else branches as follows.

Java 6 and Before
One workaround for this is to convert the String into an enum and then switch on the enum.

Java 7

Java 7, however, has added a language level support for String in switch. Now you can rewrite the same code more elegantly:
 
 Not only does this help us write more readable code, but it also helps the compiler generate more efficient byte code as compared to the if-then-else by actually switching on the hashcode() and then doing an equals() comparison. Please note that you will get a NullPointerException if the variable language in the above example resolves to null. I like this feature, but unlike some of the other enhancements in the past (like Generic in Java 5), I don’t anticipate using this feature a lot. Practically, I find myself using if-then-else for one or two values and resort to an Enum when the number of values are higher.

#2 try-with-resources statement

One of the most useful additions in Java 7 is the auto closing of resources like InputStream which helps us reduce boiler plate code from our programs. Suppose we were writing a program which reads a file and closes the FileInputStream when it’s done, here is how you would write the program:

With Java 6 and Before

I want to point out a couple of things in this code. Firstly, notice that we declare the FileInputStream outside the try block just so that it can be accessed in the finally block. The second observation is that we need to initialize the InputStream to null, so that it is guaranteed to be initialized when we access it in the finally block. Last but not the least, the is.close() in the finally block may throw an Exception as well, thereby hiding the original Exception thrown in the try block Exception from the caller. What we probably want is to handle the Exception thrown from is.close() and throw the original IOException.
 

The above code still has a shortcoming that the Exception thrown from finally is supressed and not accessible to the calling code. I’m not sure how often we want to get both the original Exception and also the Exception thrown from the finally block, but if we did want it, we could do always do something like this:
 
SuppressedException above is a user written Java bean with a field named suppressed of type Exception. The calling code can then call SupressedException.getThreadLocal().getException() to get the Exception that was supressed in the finally clause. Great, we solved all the problems associated with the try-catch-finally! Now we must remember to repeat this exact sequence with each use of try-catch-finally when handling files or other resources which need to be closed. Enter Java 7, and we can do the above without the boiler plate code.

With Java 7

 
try can now have multiple statements in the parenthesis and each statement should create an object which implements the new java.lang.AutoClosable interface. The AutoClosable interface consists of just one method.

Each AutoClosable resource created in the try statement will be automatically closed! If an exception is thrown in the try block and another Exception is thrown while closing the resource, the first Exception is the one eventually thrown to the caller. The second Exception is available to the caller via the ex.getSupressed() method. Throwable.getSupressed() is a new method added on Throwable in Java 7 just for this purpose.

Mandatory catch block when using the try statement

Note that if you are creating AutoClosable resources in the try block, you are required to declare a catch block to catch the concrete exception thrown from the actual AutoClosable. close() method. Alternatively you need to throw the Exception. Think of the close() method as implicitly being called as the last line in the try block. So, if an application has its own AutoClosable class as follows:


Then, the following will cause a compile error:


To fix the above, you need to catch or throw the Exception from the calling method.


Syntax for declaring multiple resources

The try statement can contain multiple statements separated by semicolon. Each statement must result in an AutoClosable object.


It is illegal to declare any variable which isn’t an AutoClosable.

 Output

ERROR: try-with-resources not applicable to variable type
required: AutoCloseable
found: long

AutoClosable vs Closable

The old Closable interface introduced in Java 5, which also has the same method that now extends from AutoClosable, implying that all Closable classes are automatically Auto-Closable. Those classes automatically become resources that can be created in the try statement. The slight difference in AutoClosable and Closable is that unlike Closable.close(), AutoClosable.close() is not supposed to be idempotent, which means that calling it twice can have side effects. The second difference is that since exceptions thrown from AutoClosable. close() are suppressed, AutoClosable.close() should not throw exceptions which can cause problems when suppressed, like the InterruptedException.

#3 More precise rethrow

There are often situations when we want to catch multiple exceptions of different types, do “something” with them, and rethrow them. Let us consider this example, where we have some code which throws IOException and SQLException.





In the above example, we are logging each type of exception being thrown by the try block before rethrowing them. This results in a duplication of code in the catch blocks. Before Java 7, to get around the code duplication issue we would catch the base exception as follows:


However, this requires us to rethrow the base Exception type java.lang.Exception from the calling method.
public static void main(String[] args) throws Exception {

With Java 7

Java 7 has added the “precise rethrow” feature which lets you catch and throw the base exception while still throwing the precise exception from the calling method.

 
Note the keyword final in the above catch clause. When a parameter is declared final, the compiler statically knows to only throw those checked exceptions that were thrown by the try block and were not caught in any preceding catch blocks.

#4 Multi-catch

There is no elegant way with Java 6 to catch multiple exceptions of different types and handle them in the same way.

You can always catch the parent Exception in order to avoid duplication of code, but it is not always suitable especially if the parent is java.lang.Exception. Java 7 lets you catch multiple Exceptions in a single catch block by defining a “union” of Exceptions to be caught in the catch clause.


Note that the pipe ‘|’ character is used as the delimiter. The variable ‘ex’ in the above example is statically typed to the base class of Ex1 and Ex2, which is java.lang.Exception in this case.

#5 Binary integral literals

With Java 7, you can now create numerical literals using binary notation using the prefix “0b”

int n = 0b100000;
System.out.println("n = " + n);

Output

n = 32

#6 Underscores in numeric literals

With Java 7, you can include underscores in numeric literals to make them more readable. The underscore is only present in the representation of the literal in Java code, and will not show up when you print the value.

Without underscore

int tenMillion = 10000000;
System.out.println(“Amount is “ + tenMillion);

Output

10000000

With underscore

int tenMillionButMoreReadable = 10_000_000;
System.out.println("Amount is " + tenMillionButMoreReadable);

Output

10000000

More rules and examples

1. Consecutive underscores is legal.

int n = 1000______000;

2. Underscores can be included in other numeric types as well.

double d = 1000_000.0d;
long l = 1000_000l;
int hex = 0xdead_c0de;
int bytes = 0x1000_0000;

3. Underscore can be included after the decimal point.

double example8 = 1000_000.000_000d;

4. It is illegal to start a literal with an underscore


5. It is illegal to end a literal with an underscore.


6. It is also illegal to have underscore be just before or after a decimal point.


7. Improved type inference for generic instance creation

Java 5 introduced generics which enabled developers to write type safe collections. However, generics can sometimes be too verbose. Consider the following example where we are creating a Map of List of String.

With Java 5 and 6

Map<String, List<String>> retVal = new HashMap<String, List<String>>();

Note that the full type is specified twice and is therefore redundant. Unfortunately, this was a limitation of Java 5 and 6.

With Java 7

Java 7 tries to get rid of this redundancy by introducing a left to right type inference. You can now rewrite the same statement by using the <> construct.

Map<String, List<String>> retVal = new HashMap<>();

This does make the code a little less verbose. You can also use <> construct when returning a newly created object.


This, in my opinion, goes only half way. The full solution would have been a right to left full type inference.

Map map = new HashMap<String, String>();

The above would have made the code even less verbose. Though this enhancement can still be done in a later version.

#8 More new I/O APIs for the Java platform (NIO.2)

A new set of I/O APIs and features were introduced in Java 1.4 under the java.nio package. This addition was called the New I/O APIs, also known as NIO. Naming something New is always short-sighted because it will not remain new forever. When the next version comes along, what should the new version be called, the NEW NEW I/O? Java 1.7 offers a rich set of new features and I/O capabilities, called NIO.2 (New I/O version 2?). Here are the key highlights of NIO.2.

a) Package

The most important package to look for is java.nio.file. This package contains many practical file utilities, new file I/O related classes and interfaces.

b) The java.nio.file.Path interface

Path is probably the new class that developers will use most often. The file referred by the path does not need to exist. The file referred to does not need to exist. For all practical purposes, you can think of replacing java.io.File with java. io.Path.

Old Way

File file = new File("hello.txt");
System.out.println("File exists() == " + file.exists());

New Way

Path path = FileSystems.getDefault().getPath("hello.txt");
System.out.println("Path exists() == " + Files.exists(path));

c) The java.nio.file.Files class

The Files class offers over 50 utility methods for File related operations which many developers would have wanted to be a part of earlier Java releases. Here are some methods to give you a sense of the range of methods offered. • copy() – copy a file, with options like REPLACE_EXISTING, NOFOLLOW_LINKS public static Path copy(Path source, Path target, CopyOption... options);

move() – move or rename a file public static Path move(Path source, Path target, CopyOption... options);

newInputStream() – create input stream public static InputStream newInputStream(Path path, OpenOption... options);

readAllBytes() – similar to the Apache IOUtils.readFile-ToByteArray public static byte[] readAllBytes(Path path) throws IOException;

createSymbolicLink() – creates a symbolic link, if supported by the file system public static Path createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException


d) WatchService API

WatchService API is a new feature introduced in Java 1.7. It provides an API that lets you “listen” to a certain type of file system events. Your code gets called automatically when those events occur. Examples of event types are captured by StandardWatchEventKinds class.

• ENTRY_CREATE:an entry is created or renamed in the directory
• ENTRY_DELETE:an entry is created or renamed out of the directory
• ENTRY_MODIFY:a directory entry is modified

Example
Here’s a full example of how to watch a directory and print any newly created files.


Run the above program. Then create a file ‘new.txt’ in the directory ‘logs’. The program will print:
logs: new file created new.txt



Links: