Personal notes on Java
For other technologies like HTML, CSS, .NET, PHP, etc. check my other blog

TODO



Online documentation:


static imports (since java 5)

A static import declaration (a new feature of J2SE 5.0) enables programmers to refer to imported static members as if they were declared in the class that uses them—the class name and a dot (.) are not required to use an imported static member.

You can import a particular static member:
import static java.lang.Math.PI; 
import static java.lang.Math.abs;

You can import all static members of a class:
import static java.lang.Math.*;

Note that static import declarations import only static class members
. Regular import statements should be used to specify the classes used in a program.

Full Example:
import static java.lang.Math.*;
public class StaticImportsTest {    
    public void fazCoisas(){
        abs(-1);
        sqrt(4);        
    }   
}


Varargs - Optional arguments

Prior to java 1.5, a method that took an arbitrary number of values required you to create an array and put the values into the array prior to invoking the method.
It is still true that multiple arguments must be passed in an array, but the varargs feature automates and hides the process.
The three periods after the parameter's type indicate that the argument may be passed as an array or as a sequence of arguments.
If the method has more than one argument: Varargs can be used only in the final argument position.
Example:
public class MyClass {    
    public  void doSomething(String... parametros){        
        for(String s : parametros){
            System.out.println(s);
        }        
    }
}

you can call the method using optional arguments:
     doSomething();
     doSomething("Hello");
     doSomething("Hello", ",", "World", "!"); 

Date and Time

Class java.text.SimpleDateFormat

It is possible to both parse dates from strings, and format dates to strings, using Java's java.text.SimpleDateFormat class. The SimpleDateFormat class works on java.util.Date instances. Here are two simple examples
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String dateString = format.format( new Date()   );
Date   date       = format.parse ( "2009-12-31" );
More info here: Parsing and Formatting Dates in Java


Primitive types

Autoboxing

As any Java programmer knows, you can’t put an int (or other primitive value) into a collection. Collections can only hold object references, so you would have to box primitive values into the appropriate wrapper class (which is Integer in the case of int). When you take the object out of the collection, you get the Integer that you put in; if you need an int, you would need to unbox the Integer using the intValue method. BUT, all of this boxing and unboxing is done automaticly by the compiler: autoboxing!

Example:
public class Test{
   public static void main(String args[]){
      Integer x = 5; // boxes int to an Integer object
                     // note how you dont need "new Integer(5)"
      x =  x + 10;   // unboxes the Integer to a int
      System.out.println(x); 
   }
} 




Reference type and Primitive type

Primitive types
There's 8 primitive data types (6 of them are numeric) supported by the Java programming language:
  • boolean;
  • char: a single 16-bit Unicode character;
  • byte: 8-bit signed integer. minimum value of -128 and a maximum value of 127 (inclusive);
  • short: 16-bit signed integer. minimum value of -32,768 and a maximum value of 32,767 (inclusive);
  • int: 32-bit signed integer. minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive);
  • long: 64-bit signed integer. minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive);
  • float;
  • double;
Notes:
  • In addition to the 8 primitive data types listed above, the Java programming language also provides special support for character strings via the java.lang.String class.
    The String class is not technically a primitive data type, but considering the special support given to it by the language, you'll probably tend to think of it as such.
  • For each of this primitive types there is and equivalent reference type (wrapper classes) in the java.lang package like: java.lang.Integer for int; java.lang.Double for double, etc.
Its generally considered bad programming style not to explicitly initialize variables but the default values are:
Data Type Default Value (for fields)
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
String (or any object)   null
boolean false

Reference types
all inherit from java.lang.Object.
Classes, enums, arrays, and interfaces are all reference types.
Examples of reference types include java.lang.String, all of the wrapper classes for primitive types such as java.lang.Double, the interface java.io.Serializable, and the enum javax.swing.SortOrder.

Passing Primitive Data Type Arguments VS Passing Reference Data Type Arguments

  • Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost.
  • Reference data type parameters, such as objects, are also passed into methods by value (but this value is actually the parameter reference/pointer). This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.
Note: some exceptions are the int Vs Integer, since Integer is of type object but it has the same behavior has the int primitive type when they are passed into methods.

Example:
public class ObjectVsPrimitive {
    public static void main(String args[]) {
        //initialize bouth vars to "1"
        MyObject myObject = new MyObject();
        myObject.setI(1);
        int myInt = 1;      

        //change bouth vars to "2" inside a method
        processObject(myObject);
        processInt(myInt);
       
        System.out.println(myObject.getI()); //prints 2
        System.out.println(myInt); //prints 1
    }

    public static void processObject(MyObject obj) {
        obj.setI(2);
    }

    public static void processInt(int i) {
        i = 2;
    }
}

java.lang.Number

ref: The Numbers Classes - learning trail


The java.lang.Number is an abstract class.
Classes that extend java.lang.Number are:

  • The blue nodes are primitive data types wrappers (check the primitive data types section for notes) located on the java.lang package;
  • The green nodes (BigDecimal and BigInteger) are located on the java.math and are used for high-precision calculations;
  • The red nodes (AtomicInteger and AtomicLong) are located on the package java.util.concurrent.atomic and are used for multi-threaded applications.



Misc

  • instanceof
    if (!(anotherPerson instanceof Person))
          throw new ClassCastException("A Person object expected.");
     
  • clone()
    Objects in Java are referred using reference types, and there is no direct way to copy the contents of an object into a new object.
    The assignment of one reference to another merely creates another reference to the same object. Therefore, a special clone() method exists for all reference types in order to provide a standard mechanism for an object to make a copy of itself. Here are the details you need to know about cloning Java objects.

    Why create a local copy?
    The most probable reason for creating a local copy of an object is because you plan to modify the object, and you don't want to modify the method caller's object. 
     
  • package java.lang is the default package for java language. It provides classes that are fundamental to the design of the Java programming language, and this is why you don't need to import it explicitly with import java.lang.*
     

Instance variable VS Class variable (they ar both member variables)

  • Member variable (aka member field): both instance and class variables are member variables!
    A member variable  is a variable that is associated with a specific class, and accessible for all its methods. If there is only one copy of the variable shared with all instances of the class, it is called a class variable or static member variable. If each instance of the class has its own copy of the variable, the variable is called an instance variable.
      
  • Instance variable (aka instance field, instance data member): In object-oriented programming with classes, an instance variable is a variable defined in a class (i.e. a member variable), for which each object of the class has a separate copy. They live in memory for the life of the object.
    Ex.:
    public class MyClass {
      private int count = 1;
  • Class variable (aka static field, class property, class field, or class data member): In object-oriented programming with classes, a class variable is a variable defined in a class (i.e. a member variable) of which a single copy exists, regardless of how many instances of the class exist. A class variable is the opposite of an instance variable. It is a special type of class attribute (or class property, field, or data member). In Java, C#, and C++, class variables are declared with the keyword static, and may therefore be referred to as static member variables.
    Ex.:
    public class MyClass {
      private static int count = 1;



Anonymous Classes

When you instantiate and define the class all at once.
Example:
Notice how we are instatiating an object ("myObject") of type MyInterface and declaring the class definition in loco.
public interface MyInterface {
    String nome();
    int idade();
}

public class Teste {
    public static void main(String args[]) {       

        MyInterface myObject = new MyInterface() {           
            public String nome() {
                return "Tom";
            }          

            public int idade() {
                return 12;
            }
        };


        System.out.println(myObject.nome()

                + " - " + myObject.idade());
    }
}

This kind of classes can be very useful in certain circumstances:



java.io.Serializable

ref: Bean Persistence
The mechanism that makes persistence possible is called serialization. Object serialization means converting an object into a data stream and writing it to storage. Any applet, application, or tool that uses that bean can then "reconstitute" it by deserialization. The object is then restored to its original state.
For example, a Java application can serialize a Frame window on a Microsoft Windows machine, the serialized file can be sent with e-mail to a Solaris machine, and then a Java application can restore the Frame window to the exact state which existed on the Microsoft Windows machine.
Any applet, application, or tool that uses that bean can then "reconstitute" it by deserialization.
All beans must persist. To persist, your beans must support serialization by implementing either the java.io.Serializable (in the API reference documentation) interface, or the java.io.Externalizable (in the API reference documentation) interface. These interfaces offer you the choices of automatic serialization and customized serialization. If any class in a class's inheritance hierarchy implements Serializable or Externalizable, then that class is serializable.

Classes That Are Serializable

Any class is serializable as long as that class or a parent class implements the java.io.Serializable interface. Examples of serializable classes include Component, String, Date, Vector, and Hashtable. Thus, any subclass of the Component class, including Applet, can be serialized. Notable classes not supporting serialization include Image, Thread, Socket, and InputStream. Attempting to serialize objects of these types will result in an NotSerializableException.
The Java Object Serialization API automatically serializes most fields of a Serializable object to the storage stream. This includes primitive types, arrays,and strings. The API does not serialize or deserialize fields that are marked transient or static.

Controlling Serialization

You can control the level of serialization that your beans undergo. Three ways to control serilization are:
  • Automatic serialization, implemented by the Serializable interface. The Java serialization software serializes the entire object, except transient and static fields.
  • Customized serialization. Selectively exclude fields you do not want serialized by marking with the transient (or static) modifier.
  • Customized file format, implemented by the Externalizable interface and its two methods. Beans are written in a specific file format.

Default Serialization: The Serializable Interface

The Serializable interface provides automatic serialization by using the Java Object Serialization tools. Serializable declares no methods; it acts as a marker, telling the Object Serialization tools that your bean class is serializable. Marking your class Serializable means you are telling the Java Virtual Machine (JVM) that you have made sure your class will work with default serialization. Here are some important points about working with the Serializable interface:
  • Classes that implement Serializable must have an access to a no-argument constructor of supertype. This constructor will be called when an object is "reconstituted" from a .ser file.
  • You don't need to implement Serializable in your class if it is already implemented in a superclass.
  • All fields except static and transient fields are serialized. Use the transient modifier to specify fields you do not want serialized, and to specify classes that are not serializable.

Selective Serialization Using the transient Keyword

To exclude fields from serialization in a Serializable object mark the fields with the transient modifier.
transient int status;
Default serialization will not serialize transient and static fields.

Selective Serialization: writeObject and readObject

If your serializable class contains either of the following two methods (the signatures must be exact), then the default serialization will not take place.
private void writeObject(java.io.ObjectOutputStream out)
    throws IOException;
private void readObject(java.io.ObjectInputStream in)
    throws IOException, ClassNotFoundException;
You can control how more complex objects are serialized, by writing your own implementations of the writeObject and readObject methods. Implement writeObject when you need to exercise greater control over what gets serialized when you need to serialize objects that default serialization cannot handle, or when you need to add data to the serialization stream that is not an object data member. Implement readObject to reconstruct the data stream you wrote with writeObject.

The Externalizable Interface

Use the Externalizable interface when you need complete control over your bean's serialization (for example, when writing and reading a specific file format). To use the Externalizable interface you need to implement two methods: readExternal and writeExternal. Classes that implement Externalizable must have a no-argument constructor.

Random numbers

You can use 2 alternatives:
  • the java.util.Random object;
  • or the Math.random()static method (Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.)
Usefull methods of the Random object:
  • nextInt(int n): returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive);

Loop notes

Note1:
for (String message = drop.take(); !message.equals("DONE"); message = drop.take())

Note 2: Iterate through a map key/value pairs:
HashMap<String, Integer> myMap = new HashMap<String, Integer>();
myMap.put("key1", 100);
myMap.put("key2", 200);

for(Map.Entry<String, Integer> entry : myMap.entrySet())
    System.out.println(entry.getKey()+" = "+ entry.getValue().intValue());

The ? : Operator:

Setting a single variable to one of two states based on a single condition is such a common use of if-else that a shortcut has been devised for it:
if (a > b) {
  max = a;
}
else {
  max = b;
}
            
can be replaced with:
max = (a > b) ? a : b;
            

Generics

See the Generics tutorial; Notes:
  • WildcardsExample (learn more): What is the supertype of all kinds of collections? It's written Collection<?> (pronounced "collection of unknown"), that is, a collection whose element type matches anything. We can write:
    Collection<?> c = new ArrayList<String>();
    c.add(new Object()); // Compile time error
    c.get();//ok
                        
  • Bounded Wildcard List<? extends Shape> is an example of a bounded wildcard. The ? stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard. 

Access modifiers

Access Levels
ModifierClassPackageSubclassWorld
publicYYYY
protectedYYYN
no modifierYYNN
privateYNNN
(learn more) Note: protected attributes are still accessible by subclass if the subclass access them using the "super.attribute" syntax. (this is true even if the subclass resides on the same package or not).

int VS Integer

An int is a number; an Integer is a pointer that can reference an object that contains a number. An "int" is not an object and cannot be passed to any method that requires objects. A common case is in using the provided collection classes ( List , Map , Set ); (learn more)

Collections

See the Collections tutorial; Examples:
A collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collection implementations in earlier (pre-1.2) versions of the Java platform included:
  • Vector;
  • Hashtable;
  • array;
However, those earlier versions did not contain a collections framework. The java collections framework is a unified architecture for representing and manipulating collections. All collections frameworks contain the following:
  • Interfaces: These are abstract data types that represent collections. Interfaces allow collections to be manipulated independently of the details of their representation. In object-oriented languages, interfaces generally form a hierarchy.
  • Implementations: These are the concrete implementations of the collection interfaces. In essence, they are reusable data structures.
  • Algorithms: These are the methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. The algorithms are said to be polymorphic: that is, the same method can be used on many different implementations of the appropriate collection interface. In essence, algorithms are reusable functionality.
The next image shows these collection interfaces and their hierarchy.When you understand how to use these interfaces, you will know most of what there is to know about the Java Collections Framework.
The next table shows the core collection implementations:
InterfacesHash table ImplementationsResizable array ImplementationsTree ImplementationsLinked list ImplementationsHash table + Linked list Implementations
SetHashSetTreeSetLinkedHashSet
ListArrayListLinkedList
QueueLinkedList
MapHashMapTreeMapLinkedHashMap
Some notes:
  • A good way to find wich classes implement one of this interfaces, is to visit the interface javadoc page and check the "All Known Implementing Classes". For example the Queue javadoc page shows this known implementation classes: AbstractQueue, ArrayBlockingQueue, ArrayDeque, ConcurrentLinkedDeque, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedList, LinkedTransferQueue, PriorityBlockingQueue, PriorityQueue, SynchronousQueue
  • Diference between List and Set: List<E>: An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list. Set<E>: A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction.
  • Question: You plan to write a program that uses several basic collection interfaces: Set, List, Queue, and Map. You're not sure which implementations will work best, so you decide to use general-purpose implementations until you get a better idea how your program will work in the real world. Which implementations are these? Answer: Set: HashSet List: ArrayList Queue: LinkedList Map: HashMap 
Most used core implementations by interface: (tip: if you want to find more implementations:  - visit the interface javadoc page and check the "All Known Implementing Classes" section;   - search on google for ex. "Map interface implementations" or "Set interface implementations", etc.)
  • HashSet (most used): is much faster than TreeSet (constant-time versus log-time for most operations) but offers no ordering guarantees;
  • TreeSet (implements SortedSet interface that inherits from the Set interface): used when you need to use the operations in the SortedSet interface, or if value-ordered iteration is required otherwise use HashSet;
  • LinkedHashSet: can be seen has an intermediate between HashSet and TreeSet. Provides insertion-ordered iteration. Spares its clients from the chaotic ordering provided by HashSet without incurring the increased cost associated with TreeSet.
List interface implementations:
  • ArrayList (most used):  offers constant-time positional access and is just plain fast. Think of ArrayList as Vector without the synchronization overhead;
  • LinkedList (also implements the Queue interface):  provides FIFO semantics. If you frequently add elements to the beginning of the List or iterate over the List to delete elements;
  • LinkedList (also implements the List interface): provides FIFO semantics;
  • PriorityQueue orders its elements according to their values. The order is specified at construction time, which can be the elements' natural ordering or the ordering imposed by an explicit Comparator.
Map interface implementations:
  • HashMap (most used) if you want maximum speed and don't care about iteration order;
  • TreeMap (implements SortedMap interface that inherits from the Map interface): if you care about order;
  • LinkedHashMap: near-HashMap performance and insertion-order iteration;
  • Hashtable
  • EnumMap
  • IdentityHashMap
  • Properties:  Extends  Hashtable, but each key and its corresponding value must be of type string.
  • WeakHashMap
(this article has many tips on Map implementation classes: Java's Map Interface)

NOTE: none of this implementations are synchronized (thread-safe).  All are Serializable and all support a public clone method. But any collection can be transformed into a synchronized collection, by using the Wrapper Implementations.
Example on using a Wrapper Class to synchronize a Map:
  • A default, non synchronized map:
    Map<String, String> synchronizedMap = 
     new HashMap<String, String>();
  • Making the previous map thread-safe:
    Map<String, String> synchronizedMap =
     Collections.synchronizedMap(new HashMap<String, String>());
BUT! This wrapper classes only guarantees that atomic operations are synchronized! If you have more than one thread operating on the previous map you still need to take extra measures:
  • Collections.synchronizedMap() guarantees that each atomic operation you want to run on the map will be synchronized.
  • Running two (or more) operations on the map however, must be synchronized in a block.
    More info here: Java synchronized block vs. Collections.synchronizedMap
Intead of using the Wrapper Classes, there's also Synchronized versions of this implementations on the java.util.concurrent package:
Synchronized Lists:
  • If you need synchronization, a Vector will be slightly faster than an ArrayList synchronized with Collections.synchronizedList. But Vector has loads of legacy operations, so be careful to always manipulate the Vector with the List interface or else you won't be able to replace the implementation at a later time.
Synchronized Queues:
  • LinkedBlockingQueue — an optionally bounded FIFO blocking queue backed by linked nodes
  • ArrayBlockingQueue — a bounded FIFO blocking queue backed by an array
  • PriorityBlockingQueue — an unbounded blocking priority queue backed by a heap
  • DelayQueue — a time-based scheduling queue backed by a heap
  • SynchronousQueue — a simple rendezvous mechanism that uses the BlockingQueue interface
  • TransferQueue (JDK 7) is a specialized BlockingQueue in which code that adds an element to the queue has the option of waiting (blocking) for code in another thread to retrieve the element. TransferQueue has a single implementation: LinkedTransferQueue — an unbounded TransferQueue based on linked nodes;
Synchronized Map:
  • ConcurrentMap interface, which extends Map with atomic putIfAbsent, remove, and replace methods, and the ConcurrentHashMap implementation of that interface;
     
Some collection usage notes:
  • Iterate through a maps key/value pairs:
    HashMap<String, Integer> myMap = new HashMap<String, Integer>();
    myMap.put("key1", 100);
    myMap.put("key2", 200);
    
    for(Map.Entry<String, Integer> entry : myMap.entrySet())
        System.out.println(entry.getKey()+" = "+ entry.getValue().intValue());

Strings

Official basic String trail Useful methods:
  • boolean isEmpty(): Returns true if, and only if, length() is 0.
Other string operators and objects:
  • java.lang.StringBuilder StringBuilder objects are like String objects, except that they can be modified. Internally, these objects are treated like variable-length arrays that contain a sequence of characters. At any point, the length and content of the sequence can be changed through method invocations. NOTE: Strings should always be used unless string builders offer an advantage in terms of simpler code or better performance. For example, if you need to concatenate a large number of strings, appending to a StringBuilder object is more efficient. ref.: The StringBuilder Class Learning trail
  • java.util.StringTokenizer The string tokenizer class allows an application to break a string into tokens

Class

Check the Class javadoc. What is the difference between “Class.forName()” and “Class.forName().newInstance()”? An example demonstrating how both methods are used:
package test;
public class Demo {

    public Demo() {
        System.out.println("Hi!");
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("test.Demo");
        Demo demo = (Demo) clazz.newInstance();
    }
}
And running this Demo class thus prints the following output: Hi! The big difference with the traditional new is that newInstance allows to instantiate a class that you don't know until runtime, making your code more dynamic. A typical example is the JDBC API which loads, at runtime, the exact driver required to perform the work. EJBs containers, Servlet containers are other good examples: they use dynamic runtime loading to load and create components they don't know anything before the runtime. The case of JDBC drivers is a bit special. As explained in the DriverManager chapter of Getting Started with the JDBC API: (...) A Driver class is loaded, and therefore automatically registered with the DriverManager by calling the method Class.forName. The following code loads the class acme.db.Driver: Class.forName("acme.db.Driver"); If acme.db.Driver has been written so that loading it causes an instance to be created and also calls DriverManager.registerDriver with that instance as the parameter (as it should do), then it is in the DriverManager's list of drivers and available for creating a connection. Read more here: StackOverflow - What is difference between “Class.forName()” and “Class.forName().newInstance()”?

Exceptions

Code sample 1
import static java.lang.System.out;

public class ExceptionsTest {

    private static int testMethod(String value) {
        out.println("\nGoing to process: "+value);
        try {
            return Integer.parseInt(value);
        } catch (Exception ignore) {
            out.println("Exception caught!");
        } finally {
            out.println("finally done!");
        }
        return -1;
    }

    public static void main(String[] args) {
        out.println(ExceptionsTest.testMethod("a"));
        out.println(ExceptionsTest.testMethod("2"));
    }
}

You'll get the following result:
Going to process: a
Exception caught!
finally done!
-1

Going to process: 2
finally done!
2

Things to note:
  • the finally block is always executed! Even if the return inside the try catch gets called, it will only return after invoking the finally block!

Sem comentários:

Enviar um comentário