Thursday, August 16, 2012

Generics - Part 2


One of the hardest sections is Generics that was introduced by Sun in Java 5.0, this section will try to summarize the most relevant topics as well as real examples to help you memorize when/where and why use a specific collection for a given scenario.

Let's start with the key interfaces and classes.

Intefaces



Classes



Noticed that almost all the interfaces and classes directly or not extend java.util.Collection, only Map and interfaces and classes under it don't extend java.util.Collection. Take a look at the structure of Collection below:



Watch out - Collections is a utility class which provides static methods and Collection is an interface.

Overview of each member of collections.

¦ Lists - Lists of things (classes that implement List).
¦ Sets  - Unique things (classes that implement Set).
¦ Maps  - Things with a unique ID (classes that implement Map).
¦Queues - Things arranged by the order in which they are to be processed.

Sorted,Unsorted,Ordered and Unordered that's a tricky part of collections

Ordered --> When a collection is ordered, it means you can iterate through the
collection in a specific (not-random) order, find below some examples of ordered and unordered collection
package br.com.ocjp.generics;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.Map;
public class AppOrdered {
public static void main(String[] args) {
String s = "apple";
String s2 = "mango";
String s3 = "orange";
String s4 = "strawberry";
LinkedHashSet<String> link = new LinkedHashSet<String>();
link.add(s2);
link.add(s);
link.add(s4);
link.add(s3);
System.out.println("======== LinkedHashSet =============");
for (String string : link) {
System.out.println(string);
}
ArrayList<String> array = new ArrayList<String>();
array.add(s2);
array.add(s);
array.add(s4);
array.add(s3);
System.out.println("======== ArrayList =============");
for (String string : array) {
System.out.println(string);
}
Hashtable<Integer, String> hash = new Hashtable<Integer, String>();
hash.put(1,s);
hash.put(2,s2);
hash.put(3,s4);
hash.put(4,s3);
System.out.println("======== Hashtable =============");
for ( Map.Entry<Integer, String> entry : hash.entrySet()) {
System.out.println(entry.getValue());
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub


As you can see the class LinkedHashSet keeps the order based on insertion where the last inserted is the last element in a collection, ArrayList keeps the order by using index position and finally Hashtable does not keep the order of its elements.

Sorted --> A sorted collection means that the order in the collection is determined
according to some rule or rules, to determine this rule we need to implement Comparator or Comparable, more about it is comming up.

Let's see an overview of the interfaces and those concrete implementations.

List Interface:
A List cares about the index, it's a ordered collection.

ArrayList:
It's a ordered collection by index but not sorted, it's a good idea choose this collection when you need fast iteration, however is not suitable if your intention is insertion and deletion.

Vector: 
Basically the same as an ArrayList, but its methods are synchronized.

LinkedList: 
It's a ordered collection by index, also it has methods that allow insertion and deletion from the beginning or end.
You'll be in a good shape using this collection to massive insertion and deletion but be careful when you need iteration.
Finally since Java 5.0 it implements java.util.Queue so it has the basic methods peek(), poll(), and offer().

Set Interface:
A Set cares about uniqueness, it doesn't allow duplicates, to do this the method equals() ensures it.

HashSet:
A HashSet is an unsorted, unordered Set, ensure that you did a good implementation for hashCode() method because it's determines a performance of this collection, use it when you don't want duplicates and you don't care about order when you iterate through it.

LinkedHashSet: 
Different from HashSet this collection is ordered, so use it when you care about order when you iterate through it, an order is determined by insertion of elements.

TreeSet:
It's a sorted collection, the elements will be in ascending order based on natural order also you can construct a TreeSet using a Comparator/Comparable.

Map Interface:
A Map cares about unique identifiers. It's structure is based on key/value(Objects of course).
Equals() method determines if the keys are the same or different.

HashMap:
A HashMap is an unsorted, unordered Set, ensure that you did a good implementation for hashCode() method because it's determines a performance of this collection
HashMap allows one null key and multiple null values in a collection.

HashTable:
It's like a Vector where its methods are synchronized, different from HashMap it does not allow null values as well as null key.

LinkedHashMap:
Similar to LinkedHashSet this collection is ordered, so use it when you care about order when you iterate through it, an order is determined by insertion of elements, you can get faster interation but don't expect good performance for insertion and deletion.

TreeMap:
It's a sorted collection, the elements will be in ascending order based on natural order also you can construct a TreeMap using a Comparator/Comparable.

Queue Interface:
Basically used as a FIFO(first in - first out), it supports all the methods related to collections, in addition there are methods for adding, removing and review the queue.

PriorityQueue:
A PriorityQueue's elements are ordered either by natural ordering

See below the table with useful information.


Tuesday, August 14, 2012

Generics - Part 1


Before diving into Generics we have to get a better understanding of some Object's methods like hashCode() and equals().

Overriding equals()

The main purpose of this method is compare if the objects are meaningfully equivalent, if you don't override this method you cannot use the object as a key in a hashtable, it's because when you don't override a equals() method it uses the operator == to do a comparison.

Let's override a equals() method.

package br.com.ocjp.generics;
public class Employee {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean equals(Object o) {
if ( (o instanceof Employee) && ( ((Employee)o).getName().equals(this.getName()) &&
((Employee)o).getAge() == this.getAge() ) ) {
return true;
} else {
return false;
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub
package br.com.ocjp.generics;
public class AppEquals {
public static void main(String[] args) {
Employee e = new Employee();
e.setName("David");
e.setAge(34);
Employee e1 = new Employee();
e1.setName("Anthony");
e1.setAge(34);
Employee e2 = new Employee();
e2.setName("David");
e2.setAge(34);
System.out.println(e.equals(e1));
System.out.println(e.equals(e2));
}
}
view raw gistfile1.java hosted with ❤ by GitHub
Overriding hashCode()

Hascode is used by some Collections, it provides a way to store the objects in a collection as well as it helps to locale the objets within the collections.  If two objects are equal, their hashcodes must be equal as well.

Implementing hashCode()
package br.com.ocjp.generics;
public class Employee {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
Let's review equals and hashCode methods



After this brief introduction needed to work with Collections you're able to dive into Collections which will be covered in the next section.

Monday, July 30, 2012

Parsing, Tokenizing and Formatting


Parsing

This section is intended to review all the approches to find, token and format stuff.
Let's see the first example:

package br.com.ocjp.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexFirst {
public static void main(String[] args) {
Pattern p = Pattern.compile("aba");
Matcher m = p.matcher("abababa"); // index starts from 0
while ( m.find() ) {
System.out.print(m.start() + " "); // Prints 0 4
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

As you can see the mehtod matcher from the class Matcher gets a source and the class Pattern uses the method compile to handle a pattern that you want to search.

!Important:

  a b a b a b a
  0 1 2 3 4 5 6

Why the little program showed above didn't print 0 2 4?
The reason is the regex engine does not consider the index 2 because it was consumed, and cannot be reused, but there are expections for this rule and will be shown sooner.

  a b a
  0 1 2

Using Metacharacters

\d A digit
\s A whitespace character
\w A word character (letters, digits, or "_" (underscore))
 . Any character
package br.com.ocjp.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMeta {
public static void main(String[] args) {
Pattern[] p = new Pattern[7];
p[0] = Pattern.compile("\\d");
p[1] = Pattern.compile("\\s");
p[2] = Pattern.compile("\\w");
p[3] = Pattern.compile(".");
p[4] = Pattern.compile("[abc]");
p[5] = Pattern.compile("[a-f]");
p[6] = Pattern.compile("[a-fA-F]");
Matcher[] matchers = new Matcher[7];
for ( int i = 0; i < matchers.length ; i++ ) {
matchers[i] = p[i].matcher("abcfd5 9erARqf C1#");
// abcfd5 9erARqf C1#
// 012345678901234567
System.out.println("Matcher ==> " + i);
while ( matchers[i].find() ) {
System.out.print(matchers[i].start() + " ");
}
System.out.println("");
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Output
Matcher ==> 0
5 7 16
Matcher ==> 1
6 14
Matcher ==> 2
0 1 2 3 4 5 7 8 9 10 11 12 13 15 16
Matcher ==> 3
0 1 2
Matcher ==> 4
0 1 2 3 4 8 13
Matcher ==> 5
0 1 2 3 4 8 10 13 15

Using Quantifiers

+ One or more occurrences
* Zero or more occurrences
? Zero or one occurrence
package br.com.ocjp.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexQuantifiers {
public static void main(String[] args) {
Pattern[] p = new Pattern[3];
p[0] = Pattern.compile("0[xX]([0-9a-fA-F])+");
p[1] = Pattern.compile("proj1([^,])*");
p[2] = Pattern.compile("\\d\\d\\d([-\\s])?\\d\\d\\d\\d"); // ? which means Zero or one occurrence
Matcher[] matchers = new Matcher[3];
for ( int i = 0; i < matchers.length ; i++ ) {
if ( i == 0 ) {
matchers[i] = p[i].matcher("12 0x 0x12 0Xf 0xg");
} else if ( i == 1) {
matchers[i] = p[i].matcher("proj3.txt,proj1sched.pdf,proj1,proj2,proj1.java");
} else {
matchers[i] = p[i].matcher("1234567,123-4567,123 4567");
}
System.out.println("Matcher ==> " + i);
while ( matchers[i].find() ) {
System.out.println(matchers[i].start() + " " + matchers[i].group());
}
System.out.println("");
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub


Greedy Quantifiers

package br.com.ocjp.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexGreedy {
public static void main(String[] args) {
Pattern p = Pattern.compile(".*xx"); // Greedy *
Matcher m = p.matcher("yyxxxyxx");
while ( m.find() ) {
System.out.println( m.start() + " " + m.group());
}
System.out.println("#########################");
Pattern p1 = Pattern.compile(".*?xx"); // Reluctant quantifier
Matcher m1 = p1.matcher("yyxxxyxx");
while ( m1.find() ) {
System.out.println( m1.start() + " " + m1.group());
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub


Tokenizing

Tokenizing is the process of taking big pieces of source data, breaking them into
little pieces, and storing the little pieces in variables

Tokenizing with Scanner
package br.com.ocjp.regex;
import java.util.Scanner;
public class AppScanner {
public static void main(String [] args) {
boolean b2, b;
int i;
String s, hits = " ";
Scanner s1 = new Scanner(args[0]);
Scanner s2 = new Scanner(args[0]);
while(b = s1.hasNext()) {
s = s1.next(); hits += "s";
}
while(b = s2.hasNext()) {
if (s2.hasNextInt()) {
i = s2.nextInt(); hits += "i";
} else if (s2.hasNextBoolean()) {
b2 = s2.nextBoolean(); hits += "b";
} else {
s2.next(); hits += "s2";
}
}
System.out.println("hits " + hits);
}
}
view raw gistfile1.java hosted with ❤ by GitHub


Formatting with printf() and format()

Both methods have exactly the same behaviour which means anything we say about one of these methods is applicable to both.

Let's see how formatting works:

%[arg_index$][flags][width][.precision]conversion char

The values within [ ] are optional.

1. arg_index - An integer followed directly by a $, this indicates which argument should be printed in this position.

2. flags - While many flags are available, for the exam you'll need to know:
¦ "-" Left justify this argument
¦ "+" Include a sign (+ or -) with this argument
¦ "0" Pad this argument with zeroes
¦ "," Use locale-specific grouping separators (i.e., the comma in 123,456)
¦ "(" Enclose negative numbers in parentheses


3. width -  This value indicates the minimum number of characters to print. (If you
want nice even columns, you'll use this value extensively.)

4. precision - For the exam you'll only need this when formatting a floating-point
number, and in the case of floating point numbers, precision indicates the number of
digits to print after the decimal point.

5. conversion - The type of argument you'll be formatting. You'll need to know:
¦ b boolean
¦ c char
¦ d integer
¦ f floating point
¦ s string


package br.com.ocjp.regex;
public class AppPrintf {
public static void main(String[] args) {
boolean b = true;
double num = 565.99;
long num1 = 6565415;
System.out.printf("%1$010d \n",num1);
System.out.printf("%1$,.5f \n",num);
System.out.printf("%1$010d , %2$,.5f \n ",num1,num);
System.out.printf("---> %1$b",b);
}
}
view raw gistfile1.java hosted with ❤ by GitHub



Wednesday, July 18, 2012

Working with Dates/Numbers and Currencies


In this section you'll learn the most common methods to format Dates, Numbers and Currencies as well as the relationship between the main classes responsible to do that.

Let's start with the classes that you have to learn.

java.util.Date;
java.util.Calendar;
java.text.DateFormat;
java.text.NumberFormat;
java.util.Locale;

package br.com.ocjp.formatting;
import java.util.Date;
public class AppDate {
public static void main(String[] args) {
Date d = new Date();
System.out.println(d.toString());
Date d2 = new Date(1000000L);
System.out.println(d2.toString());
Date d3 = new Date();
System.out.println(d3.getTime());
Date d4 = new Date(d3.getTime());
System.out.println(d4.toString());
Date d5 = new Date();
d5.setTime(10000054700104L);
System.out.println(d5.toString());
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Console:

Wed Jul 18 10:18:42 AMT 2012
Wed Dec 31 19:16:40 AMT 1969
1342621122734
Wed Jul 18 10:18:42 AMT 2012
Sun Nov 21 04:58:20 AMT 2286

The class java.util.Date is hard to work with,if you look at the preceding example to set a specific date we have to use a number representation(long), this class is normally used to create a date that represents "now" as well as working with java.util.Calendar.

package br.com.ocjp.formatting;
import java.util.Calendar;
import java.util.Date;
public class AppCalendarDate {
public static void main(String[] args) {
Date d1 = new Date("09/15/2012");
System.out.println(d1.toString());
Date d = new Date();
System.out.println("Today is " + d.toString());
Calendar cal = Calendar.getInstance();
cal.setTime(d);
System.out.println("Day of the week " + cal.get(Calendar.DAY_OF_WEEK));
System.out.println("Day of the year " + cal.get(Calendar.DAY_OF_YEAR));
Calendar c1 = Calendar.getInstance();
c1.setTime(d1);
System.out.println("Last day of the year " + c1.get(Calendar.DAY_OF_YEAR));
long current = cal.get(Calendar.DAY_OF_YEAR);
long last = c1.get(Calendar.DAY_OF_YEAR);
long remaining = last - current;
System.out.println("Remaining Days ==> " + remaining );
cal.add(Calendar.YEAR, 2);
d = cal.getTime();
System.out.println(d.toString());
cal.roll(Calendar.MONTH, 10);
d = cal.getTime();
System.out.println(d.toString());
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Console:

Sat Sep 15 00:00:00 AMT 2012
Today is Wed Jul 18 10:37:26 AMT 2012
Day of the week 4
Day of the year 200
Last day of the year 259
Remaining Days ==> 59
Fri Jul 18 10:37:26 AMT 2014
Sun May 18 10:37:26 AMT 2014


Watch out, the class Calendar is abstract you cannot create an instance of it(look at line 16), also it provides friendly methods to manipulate dates, where you can add hours, days, weeks, and so on.
Notice the class java.util.Calendar work together java.util.Date, instead of setting a date using number(long) you can use a Date object.
Finally the method roll is similar to add, the difference is it does not change into next month(if you're adding days), years(if you're adding months) and so on.

package br.com.ocjp.formatting;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class AppDateLocale {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(2012, 07, 17);
Date d = c.getTime();
Locale us = new Locale("en");
Locale pt = new Locale("pt","br");
Locale fr = new Locale("fr");
Locale sp = new Locale("es");
Locale ja = new Locale("ja");
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, us);
DateFormat df1 = DateFormat.getDateInstance(DateFormat.FULL, pt);
DateFormat df2 = DateFormat.getDateInstance(DateFormat.FULL, fr);
DateFormat df3 = DateFormat.getDateInstance(DateFormat.FULL, sp);
DateFormat df4 = DateFormat.getDateInstance(DateFormat.FULL, ja);
System.out.println(df.format(d));
System.out.println(df1.format(d));
System.out.println(df2.format(d));
System.out.println(df3.format(d));
System.out.println(df4.format(d));
try {
String date = df.format(d);
Date parseDate = df.parse(date);
System.out.println("Parse ==> " + parseDate);
} catch ( ParseException e){}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Console:

Friday, August 17, 2012
Sexta-feira, 17 de Agosto de 2012
vendredi 17 août 2012
viernes 17 de agosto de 2012
2012?8?17?
Parse ==> Fri Aug 17 00:00:00 AMT 2012


The class java.text.DateFormat is an abstract class that provides us formatted dates using or not pré-defined styles as well as Locales.
You can get a DateFormat class by invoking the methods getInstance() and getDateInstance().
Finally we can parse a String to Date by using the method parse() which must be enclosed in a try-catch block.

package br.com.ocjp.formatting;
import java.util.Locale;
public class AppLocale {
public static void main(String[] args) {
Locale[] loc = new Locale[4];
loc[0] = new Locale("pt");
loc[1] = new Locale("pt","br");
loc[2] = new Locale("fr");
loc[3] = new Locale("en","us");
for ( Locale l : loc) {
System.out.print(l.getLanguage() + " -> ");
System.out.println(l.getDisplayCountry(l));
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Console:

pt ->
pt -> Brasil
fr ->
en -> United States


Let's take a briefly look at java.util.Locale.

The first argument is related to the language and the second is a country.
The most important methods are getLanguage() and getDisplayCountry().
There are not setters to define language and country at java.util.Locale.

package br.com.ocjp.formatting;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class AppNumberFormat {
public static void main(String[] args) {
float f = 1100.56845f;
Locale pt = new Locale("pt");
Locale us = new Locale("en","us");
NumberFormat nf[] = new NumberFormat[6];
nf[0] = NumberFormat.getNumberInstance();
nf[0].setMaximumFractionDigits(5);
nf[1] = NumberFormat.getNumberInstance(pt);
nf[2] = NumberFormat.getNumberInstance(us);
nf[3] = NumberFormat.getCurrencyInstance();
nf[4] = NumberFormat.getCurrencyInstance(pt);
nf[5] = NumberFormat.getCurrencyInstance(us);
for ( NumberFormat nfs : nf ) {
System.out.println(nfs.format(f));
}
System.out.println(nf[0].getMaximumFractionDigits());
try {
NumberFormat nf1 = NumberFormat.getInstance();
System.out.println(nf1.parse("1234.567"));
nf1.setParseIntegerOnly(true);
System.out.println(nf1.parse("1234.567"));
} catch (ParseException pe) {
System.out.println("parse exc");
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Console:

1.100,56848
1.100,568
1,100.568
R$ 1.100,57
¤ 1.100,57
$1,100.57
5
1234567
1234567


Similar to java.text.DateFormat the class java.text.NumberFormat works with numbers(currency, percent, and so on), where there are many ways to get a concrete class since NumberFormat is abstract.

getInstance(),
getNumberInstance(),
getCurrencyInstance(),
.. and so on

The method parse() is present as well where you can get a Number object.

Wednesday, July 11, 2012

I/O - Getting better understanding of API


Let's start with the class File

package br.com.ocjp.io;
import java.io.File;
import java.io.IOException;
public class ClassFile {
public static void main(String[] args) {
File f = new File("C:\\temp\\file.txt"); // There is no file yet.
System.out.println("Does the file exist? " + f.exists());
try {
boolean flag = f.createNewFile(); // May Create a real file
System.out.println("File has been created " + flag);
System.out.println("Does the file exist? " + f.exists());
} catch (IOException e) {}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Notice that the file has not been created until the line 13 be reached, to memorize it think of when you create a File(line 10) it doesn't throw any exception but the method createNewFile does.

Serialization

Serialization is the mechanism that allows you save the state of objects.
Find below the keys to make a class serializable.

package br.com.ocjp.serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
class Request implements Serializable {
public int number;
public Date create;
public String description;
}
public class Serialization {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Request request = new Request();
request.number = 100;
request.create = new Date();
request.description = "@@ version 1.3 @@";
FileOutputStream output = new FileOutputStream("C:\\temp\\request.ser");
ObjectOutputStream os = new ObjectOutputStream(output);
os.writeObject(request);
os.close();
FileInputStream file = new FileInputStream("C:\\Temp\\request.ser");
ObjectInputStream io = new ObjectInputStream(file);
Request r = (Request) io.readObject();
System.out.println(r.number);
System.out.println(r.create);
System.out.println(r.description);
}
}
view raw gistfile1.java hosted with ❤ by GitHub

First of all we have to implement the interface serializable( look at line 11), also to save the state of object we need the classes FileOutputStream and ObjectOutputStream, the writeObject(object) method is responsible for it and to retrieve the serializable object from the file we need FileInputStream and ObjectInputStream the readObject() is responsible for reading it.

!Import

- If you don't want to save a member of object you must mark it as transient
- Whether a super class implements Serializable its subclasses are indirectly Serializable
- Whether a subclass implements Serializable and a superclass doesn't the constructor will be invoked as well as the instance variable will get their default values

Let's see an example:
package br.com.ocjp.serializable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Something {
Something() {
System.out.println("Something constructor");
}
}
class Animal extends Something {
Animal() {
System.out.println("Animal constructor");
}
String name = "something";
int age;
}
class Dog extends Animal implements Serializable {
Dog() {
System.out.println("Dog constructor");
}
String kind;
String owner;
}
public class SerializableExamples {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream out = new FileOutputStream("C:\\temp\\animal.ser");
ObjectOutputStream st = new ObjectOutputStream(out);
Dog a1 = new Dog();
a1.age = 5;
a1.name = "Dog";
a1.kind = "Pet";
a1.owner = "Somebody";
st.writeObject(a1);
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Let's see what's been saved.
package br.com.ocjp.serializable;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Input {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream f = new FileInputStream("C:\\temp\\animal.ser");
ObjectInputStream in = new ObjectInputStream(f);
Dog a2 = (Dog)in.readObject();
System.out.println("Age ==> " + a2.age);
System.out.println("Name ==> " + a2.name);
System.out.println("Kind ==> " + a2.kind);
System.out.println("Owner ==> " + a2.owner);
}
}
view raw gistfile1.java hosted with ❤ by GitHub



- if you wanna save a state of object that has a reference to another object which does not implement Serializable you have to write the methods writeObject() and readObject().

package br.com.ocjp.serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Monitor {
String model;
}
class PC implements Serializable {
String system;
int version;
public transient Monitor monitor;
private void writeObject(ObjectOutputStream o) {
try {
o.defaultWriteObject();
o.writeObject(monitor.model);
} catch (IOException e) {
e.printStackTrace();
}
}
private void readObject(ObjectInputStream in) {
try {
in.defaultReadObject();
Monitor m = new Monitor();
m.model = (String)in.readObject();
this.monitor = m;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch( IOException e) {}
}
}
public class WriteReadObject {
public static void main(String[] args) {
PC m = new PC();
m.system = "iOS";
m.version = 1;
Monitor d = new Monitor();
d.model = "SX465";
m.monitor = d;
try {
FileOutputStream f = new FileOutputStream("C:\\temp\\pc.ser");
ObjectOutputStream out = new ObjectOutputStream(f);
out.writeObject(m);
FileInputStream f1 = new FileInputStream("C:\\temp\\pc.ser");
ObjectInputStream in = new ObjectInputStream(f1);
PC pc = (PC)in.readObject();
System.out.println("PC Monitor ==> " + pc.monitor.model);
} catch (IOException e) {
System.out.println("Cannot save it");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

- Finally we can use serialization with static variables but as you've seen serialization is useful for objects

Print this post

Working with Strings and StringBuffer/StringBuilder

In this section we'll discuss about String as well as its creation, polemic things like "Strings are immutable" and see wthat's going on behind the scenes also StringBuffer and StringBuilder will be on focus.

Let's take a look at how the string objects are created and understand the immutability.

package br.com.ocjp.string;
public class StringImmutable {
public static void main(String[] args) {
String st = new String("OCJP");
String st2 = st;
st = st.concat(" - Java");
System.out.println("st variable ==> " + st);
System.out.println("st2 variable ==> " + st2);
}
}
view raw gistfile1.java hosted with ❤ by GitHub


package br.com.ocjp.string;
public class StringImmutable {
public static void main(String[] args) {
String book = new String("Book");
book.concat(" - Java");
book.upperCase();
System.out.println("book variable ==> " + book); // it prints "Book"
}
}
view raw gistfile1.java hosted with ❤ by GitHub

As you can see it prints "Book" because we don't refer the new String created to "Java - Book", so the object is in the heap however nobody refers to it.

Commom methods
Let's see common methods in action.

package br.com.ocjp.string;
public class StringCommon {
public static void main(String[] args) {
String example = "Java Example ";
System.out.println("charAt() ==> " + example.charAt(0)); // it prints J
System.out.println("concat() ==> " + example.concat(" -1")); // it prints Java Example - 1
System.out.println("equalsIgnoreCase() ==> " + example.equalsIgnoreCase("java example ")); // it prints true
System.out.println("length() ==> " + example.length()); // it prints 14
System.out.println("replace() ==> " + example.replace("a","@")); // it prints J@v@ Ex@mple
System.out.println("substring() ==> " + example.substring(0)); // it prints Java Example
System.out.println("substring() ==> " + example.substring(0,4)); // it prints Java
System.out.println("toLowerCase() ==> " + example.toLowerCase()); // it prints java example
System.out.println("toString() ==> " + example.toString()); // it prints Java Example
System.out.println("toUpperCase() ==> " + example.toUpperCase()); // it prints JAVA EXAMPLE
System.out.println("trim() ==> " + example.trim()); // no space at the end... it prints Java Example
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Pool of String
package br.com.ocjp.string;
public class StringPool {
public static void main(String[] args) {
String t = "java"; // Creates an object in a heap and puts it in a pool of String
String t1 = new String("java"); //Creates a new object in a heap and puts it in a pool of String
System.out.println(t == t1); // prints false
String s = "ocjp";
String s1 = "ocjp"; // Retrieve the string ocjp from the pool
System.out.println(s == s1); // prints true
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Also you can use the method intern() (String class) this way we can get the string from the pool if the string pass using the method equals().


StringBuffer and StringBuilder friends of memory

Both classes are intented to help you handle Strings without wasting memory, as we mentioned Strings are immutable and if we have to handle lots and lots of them StringBuffer and StringBuilder will help you.
The unique difference between StringBuffer and StringBuilder is StringBuilder is not thread-safe which means its methods aren't synchronized, as you can imagine StringBuilder is faster than StringBuffer.

package br.com.ocjp.string;
public class StringBufferBuilder {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append("Java Test - ");
sb.append("OCJP");
System.out.println(sb); // Prints Java Test - OCJP
StringBuffer sd = new StringBuffer("0123456789");
sd.delete(4, 6);
System.out.println(sd); //Prints 01236789
StringBuffer si = new StringBuffer("0123456789");
si.insert(4, "----");
System.out.println(si); //Prints 0123----46789
StringBuffer sr = new StringBuffer("0123456789");
sr.reverse();
System.out.println(sr); //Prints 987654321
StringBuilder builder = new StringBuilder("abcdef");
builder.append("ghij").reverse().delete(5,20);
System.out.println(builder); // Prints jihgf
}
}
view raw gistfile1.java hosted with ❤ by GitHub

The most import thing here is StringBuffer and StringBuilder are not immutable like String and the StringBuffer contains the synchronized methods;

Monday, July 2, 2012

Unusual things in Exceptions


I called this post "Unusual things in Exceptions" because you're going to see something that isn't usually used in a real word as well as staffs that you have to memorize for the OCJP certification.

Let's start with the class hierarchy:


package br.com.ocjp.exception;
import java.io.IOException;
public class ExceptionOrder {
public static void doSomething() {
try {
String s = "Exception example";
} catch (IOException e) { // does not compile
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

The code above does not compile you cannot handle an exception if the block try does not "throw" one.

!Import
The block finally always is called, even if there is a return statement in the try/catch block, the finally block will be executed before the return stamement.

package br.com.ocjp.exception;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExceptionOrder {
public static void doSomething() {
try {
new FileOutputStream( new File("C:\\file.txt"));
} catch (IOException e) {
} catch (FileNotFoundException e) { // does not compile
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

In this case the block try "throws" an exception throught the creation of FileOutputStream, but we still getting a compiler error, because the catch that handles FileNotFoundException will never be reached.
package br.com.ocjp.exception;
import java.io.IOException;
public class ExceptionCatchDeclare {
public void doSomething()/* throws IOException*/ {
throw new IOException(); // does not compile you have to declare(throws)
}
public void doAnything() {
doSomething(); // here you have to handle(try/catch) or declare(throws)
}
}
view raw gistfile1.java hosted with ❤ by GitHub

That's the rule for checked exceptions if you throw an exception you must declare(throws) from the calling method or catch(try/catch).


Different from checked exception, every exception under RuntimeException/Error are not obligated to catch or declare, but if you did you would be able to catch it by using try/catch block.
package br.com.ocjp.exception;
public class ExceptionRunTime {
public void doIt() throws ArithmeticException {
throw new ArithmeticException();
}
public void doThat() {
doIt();
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Common Exception

Let's take a look at the common exception, watch out where they come from





Autoboxing Overloading - Part 3


I've created a new topic for overloading because it involves Autoboxing and as you'll see there are some tricks that need to seen closely.
As you know to overload a method you have to change its arguments and the compiler will decide which method to invoke.
Let's see a simple example of overloaded method:

public class Overloaded {
public static void doSomething(byte b) {
System.out.println("byte " + b);
}
public static void doSomething(double f) {
System.out.println("double " + f);
}
public static void doSomething(int i) {
System.out.println("int " + i);
}
public static void main(String[] args) {
short s = 9;
int i = 45;
float f = 12.55f;
doSomething(s) ; // Prints int 9
doSomething(i) ; // Prints int 45
doSomething(f) ; // Prints double 12.55
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Widening
Ok that's a easy one, the important thing here is the statement at line 19, it invokes the method doSomething(int i), despite we're passing a short value you know that int supports short because int is bigger than short, that's why the method doSomething(int i) was called instead of doSomething(byte b). Also if the method doSomething(int i) did not exist the method doSomething(double f) would be invoked.

Now take a look at the following image:


The image tells us that Widening beats Boxing and Var-args and Boxing beats Var-args, so to get a better understanding of it keep in your mind this rule.
Let's see it in action

package br.com.ocjp.autoboxing;
public class AutoBoxingBeats {
public static void doIt(long value) {
System.out.println("Primitive long");
}
public static void doIt(Integer value) {
System.out.println("Integer");
}
public static void doIt(int... value) {
System.out.println("var-args");
}
public static void doThat(Integer value) {
System.out.println("Integer");
}
public static void doThat(int... value) {
System.out.println("var-args");
}
public static void doSomething(Object s) {
System.out.println("Object");
}
public static void doSomething(Number s) {
System.out.println("Number");
}
public static void main(String[] args) {
int n = 100;
doIt(n); // Prints Primitive long - Widening
doThat(n); // Prints Integer - Boxing
doSomething(n); // Prints Number - Variable Reference Widening
}
}
view raw gistfile1.java hosted with ❤ by GitHub

!Important

You cannot widen an Integer wrapper to a Long, so keep it in your mind it's not able to widen Wrapper to Wrapper.
Looking closely to the doSomething() method what happens first is a boxing int - Integer and then Integer is a Number.

Finally sometimes the compiler cannot tell apart which overloaded method is eligible to be invoke which results in a compiler error, for more details about this look it out. click here

Monday, June 25, 2012

Assignments


Stack and Heap

Stack handles Local variables.
Heap handles Instance variables and objects.


package br.com.ocjp.assignments;
class MotherBoard { }
class Computer {
MotherBoard motherboard;
String brand;
void setBrand(String brandName) { // <===== local variable
brand = brandName;
}
void build(Computer pc) { // <===== local variable
motherboard = new MotherBoard();
pc.setBrand("MacBook");
}
}
public class StackHeap {
public static void main(String[] args) {
Computer c; // <===== local variable
c = new Computer();
c.build(c);
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Stack
setBrand() brandName
build() pc
main() c

Heap
Computer
MotherBoard
String

Integer Literals

Decimal, Octal and Hexadecimal are by default int, unless we type L as a suffix

long so = 0xFFFFl;  // Note the lowercase 'l'

Octal Literals => Octal integers use only the digits 0 to 7.
The preceding 0 identifies an Octal integer.

class Octal {
public static void main(String [] args) {
int six = 06; // Equal to decimal 6
int seven = 07; // Equal to decimal 7
int eight = 010; // Equal to decimal 8
int nine = 011; // Equal to decimal 9
System.out.println("Octal 010 = " + eight);
}
}
view raw gistfile1.java hosted with ❤ by GitHub
We can have up to 21 digits in an octal number, not including the leading zero.

Hexadecimal Literals => Are constructed using 16 distinct symbols not including the prefix 0x or the optional suffix extension L

0 1 2 3 4 5 6 7 8 9 a b c d e f

class HexTest {
public static void main (String [] args) {
int x = 0X0001;
int y = 0x7fffffff;
int z = 0xDeadCafe;
System.out.println("x = " + x + " y = " + y + " z = " + z);
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Floating-Point Literals

package br.com.ocjp.assignments;
public class FloatingPoint {
public static void main(String[] args) {
float m = 100.88; // does not compile
float n = 100.88f;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
By default floating-point literals are defined as a double(64 bits), that's why the first statement does not compile, the second statement is using a suffix "f"(could be "F") which says to compiler we're talking the risk(loss of precision), Finally we cannot use a semicon instead of a dot.

Boolean Literals

!Important
Java does not allow a number like 0 or 1, only true and false are valid

Character Literals

You can assign a number literal, assuming it will fit into the unsigned 16-bit
range (65535 or less).

Not legal assignments.

char e = -29;   // Possible loss of precision; needs a cast
char f = 70000  // Possible loss of precision; needs a cast

Primitive Assignments

Image of all primitives

As you know literal integer is always int, futhermore the result of a expression involving an int results in an int value.

byte a = 3;     // No problem, 3 fits in a byte
byte b = 8;     // No problem, 8 fits in a byte
byte c = b + c; // Does not compile because the result is an int.

Primitive Casting

Casts can be implicit or explicit, where implicit cast we don't have to type anything, implicit casts happen when we try to assign a smaller thing(like short) to a bigger container(like long).

int num = 100;
long num1 = num; // Implicit cast, an int value always fits in a long

An explicit casts looks like this:
float ft = 100.001f;
int num = (int)ft; // Explicit cast, the float could lose info

Let's review

public class PrimitiveAssignments {
public static void main(String[] args) {
short sh = 300; // by default integer literals are int
short sh1 = 127 * 5; // By default a result of an expression is an int
//short sh2 = 127 * 1000; Does not compile because the int returned does not fit in a range of short
short sh3 = 5;
short sh4 = 127;
//short sh5 = sh3 * sh4; //Does not compile because the value of a variable can change at runtime, needs a cast
short sh5 = (short)(sh3 * sh4); // Works fine using casting.
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Floating Assignments

public class FloatingAssignments {
public static void main(String[] args) {
//float f = 32.5; Does not compile because a floating literals are always double
float f = (float) 32.3; // Works fine, using casting
float g = 32.3f; // Works fine, suffix f
float h = 32.3F; // Works fine, suffix F
}
}
view raw gistfile1.java hosted with ❤ by GitHub

! Important
 +=, -=, *=, and /= will all put in an implicit cast.

 byte b = 127;
 b+= 7;




Autoboxing - Part 2


The most import thing to know about Autoboxing is that wrapper classes are not immutable and since Java 5 we can work with them like primitives, for instance:

public class Autoboxing {
public static void main(String[] args) {
Short s = Short.valueOf("10");
Short s1 = s;
System.out.println(s == s1); // Prints true once that s and s1 refer to the same object
s--; // We can use s as a primitive type
System.out.println(s); // Prints 9
System.out.println(s == s1); // Prints false, again wrapper classes are not immutable like Strings.
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Comparasion of Boxing

Let's do something really weird

package br.com.ocjp.autoboxing;
public class AutoBoxing1 {
public static void main(String[] args) {
Long x = Long.valueOf(10);
Long y = Long.valueOf(10);
System.out.print("x and y are == "); // What????
System.out.println(x == y);
System.out.println("x and y are equals " + x.equals(y)); // it's not a surprise
System.out.println("Another example....");
Long x1 = Long.valueOf(130);
Long y1 = Long.valueOf(130);
System.out.print("x1 and y1 are == "); // normal behaviour
System.out.println(x1 == y1);
System.out.println("x1 and y1 are equals " + x1.equals(y1)); //normal behaviour
}
}
view raw gistfile1.java hosted with ❤ by GitHub

What happened at line 10? Why it prints true?  The operator == compares if the instance variable points to the same object in the heap,in this case we have 2 objects, so it should print false, however in this case the comparison is primitive to primitive, it happeans because the wrapper objects are unwrapped, but watch out, it is not applicable for all wrapper classes and values, find below what classes are allowed:

- Boolean
- Byte
- Short,Integer and Long ( range -128 to 127)
- Character ( from \u0000 to \u007f (7f is 127 in decimal))

Finally make sure that a variable instance is not pointing to a null otherwise we'll get an exception (NullPointerException)

Foundation of Autoboxing - Part 1


The main purpose of AutoBoxing(unBoxing) is provide a way to work with primitives as Objects, in order we can use Generics and so on.

Find below the Wrapper classes:



Creating Wrapper Objects

Most of Wrappers provide a constructor that gets as an argument a primitive value and a String object. Only the Wrapper class Character gets one argument which is a char primitive.
Let's see some examples:

public class WrapperJava {
public static void main(String[] args) {
Integer n1 = Integer("10");
Integer n2 = Integer(10);
Float f1 = new Float("5.3");
Float f2 = new Float("5.3f");
Float f3 = new Float("5.3d");
Float f4 = new Float(5.3);
Float f5 = new Float(5.3f);
Character c1 = new Character('d');
//... so on
}
}
view raw gistfile1.java hosted with ❤ by GitHub

All the wrapper classes mentioned so far contain a method called valueOf(), this method is a static method and can get different arguments depending on the wrapper, for instance:

Byte/Short/Integer/Long

[Wrapper] static valueOf(primitive)
[Wrapper] static valueOf(String)
[Wrapper] static valueOf(primitive, int radix) // radix defines the base like decimal, octal or hexadecimal.

Float/Double/Boolean

[Wrapper] static valueOf(primitive)
[Wrapper] static valueOf(String)

Character
[Wrapper] static valueOf(primitive)

Conversion 

Also we can make a conversion using the wrapper classes by calling the methods xxxValue(), all these methods don't have arguments, for instance:

Wrapper classes
The following classes extend Number -> Byte/Double/Float/Integer/Long/Short



Slightly different from the valueOf() method, the static method parseXXX() has two "flavours" similar to valueOf(), furthermore these methods are applicable only for the 6(six) integer classes and not to mention that the return of these is a primitive type instead of a wrapper class.

[Wrapper] static valueOf(String)
[Wrapper] static valueOf(primitive, int radix) // radix defines the base like decimal, octal or hexadecimal.

Example of valueOf, xxxValue and parseXxx

package br.com.ocjp.autoboxing;
public class Examples {
public static void main(String[] args) {
// valueOf
Byte b1 = Byte.valueOf((byte)100);
Byte b2 = Byte.valueOf("101");
System.out.println(b1); // Prints 100
System.out.println(b2); // Prints 101
// parseXXX
byte b3 = Byte.parseByte("100");
byte b4 = Byte.parseByte("010", 8);
byte b5 = Byte.parseByte("F", 16);
System.out.println(b3); // Prints 100
System.out.println(b4); // Prints 8
System.out.println(b5); // Prints 15
// xxxValue
Integer i = Integer.valueOf("F",16);
byte b6 = i.byteValue();
System.out.println(b6); //Prints 15
// toString /toString(xxx) and toString(xxx,radix)
System.out.println(i.toString()); //Prints 15
System.out.println(Float.toString(10.59f));//Prints 10.59
// Watch out, only Long and Integer have a toString(xxx,radix) method.
System.out.println(Long.toString(15, 16)); //Prints f
// Again only for Long and Integer
// toXxxString()
String s1 = Integer.toBinaryString(1);
String s2 = Integer.toHexString(8);
String s3 = Integer.toHexString(15);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Finally the last thing that you have to pay attention is, valueOf and parseXxx throw a NumberFormatException if the format of a string is not valid.

Tuesday, June 19, 2012

Reference Variable Casting


This section takes care of Casting(DownCasting and UpperCasting) Downcast: Casting down the inheritance tree to a more specific class
class Animal {
void makeNoise() {
System.out.println("Generic noise");
}
}
class Dog extends Animal {
void makeNoise() {
System.out.println("Bark");
}
void playDead() {
System.out.println("Playing");
}
}
public class AnimalTest {
public static void main(String ...x) {
Animal a = new Dog();
Dog d = (Dog)a; // downcast
a.playDead();
}
}
view raw gistfile1.java hosted with ❤ by GitHub
The compiler trusts in us even if you're trying to cast object that does not refer a dog.
public class AnimalTest {
public static void main(String ...x) {
Animal a = new Animal();
Dog d = (Dog)a; // downcasting
a.playDead();
}
}
view raw gistfile1.java hosted with ❤ by GitHub
The code above compiles well but you'll get an exception(java.lang.ClassCastException) at runtime, it occurrs because the compiler only verifies an inheritance tree, in this case Dog is a subtype of Animal. !Important Watch out, the code above compiles the exception is throwns at runtime. Upcasting: Unlike downcasting you don't have to type anything like the previous example Dog d = (Dog)a, the upcasting is implicitly, in other words you're restricting the number of methods that you can invoke.
class Computer {
void turnOn() {
System.out.println("Turning on Computer");
}
}
class MacBook extends Computer {
void turnOn() {
System.out.println("Turning on MacBook");
}
void openMacX() {
System.out.println("Openning a MacX");
}
}
public class ComputerTest {
public static void main(String x[]) {
MacBook m = new MacBook();
Computer c = m; // upcasting - implicitly
Computer c = (Computer)m; //upcasting - explicitly
}
}
view raw gistfile1.java hosted with ❤ by GitHub
Finally the casting can be at one line.
public class AnimalTest {
public static void main(String ...x) {
Animal a = new Dog();
Dog d = (Dog)a; // downcasting
a.playDead();
((Dog)a).playDead(); // at one line
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Monday, June 18, 2012

Overridden Methods


When we think about inheritance one of the important things to learn is overridden methods, in this post I will provide you an overview of this feature of oriented-object, also this post is intented to help you to get all the rules involved to get an OCJP certification.

Let's start with an example

e.g.

public class Computer {
public void turnOn() {
System.out.println("The Computer is turned on");
}
}
class MacBook extends Computer {
public void turnOn() {
System.out.println("The MacBook is turned on");
}
public void openMacOS() {
System.out.println("The MacOS is opened");
}
}
class ComputerTest {
public static void main(String[] args) {
Computer c = new MacBook();
c.turnOn();
c.openMacOS(); // we cannot invoke this method
Computer c = new Computer();
c.turnOn();
}
}
view raw gistfile1.java hosted with ❤ by GitHub

If you run this code above you will get:

The MacBook is turned on
The Computer is turned on

The reference variable determines at runtime which method will run depending on instanced object.
Notice that the method openMacOS() cannot be invoked using the reference variable Computer, this variable doesn't know anything about specific methods defined by MacBook class.
Also the overridding method cannot have a more restrictive access modifier, in this case the method turnOn() cannot be private, protected or default.

Let's review the rules.

1. The argument list must be exactly the same as the method that you're overrinding otherwide you're overloading a method.
2. The return type must be the same as, or a subtype of an overridden method declared in a superclass.
3. The access level can't be more restrictive than the overridden method's, but can be less restrictive.
4.

5.
import java.io.FileNotFoundException;
import java.io.IOException;
class Computer {
public void turnON() throws IOException {
System.out.println("Turned on computer");
}
}
class MacBook extends Computer {
public void turnON() throws RuntimeException, FileNotFoundException {
System.out.println("Turned on macBook");
}
}
view raw gistfile1.java hosted with ❤ by GitHub

-The overriding method CAN throw any unchecked (runtime) exception
-If the method declared in a superclass throws a checked exception the overriding method must throw a checked exceptions that match in a test IS-A.
6. Look at the modifiers: method marked as final or static cannot be overriden.
7. Methods that cannot be inherited cannot be overriden, so watch out the access modifiers.

Invoking a Superclass Version

We can invoke the superclass method by using super.methodName().

import java.io.FileNotFoundException;
import java.io.IOException;
class Computer {
public Object turnON() throws IOException {
System.out.println("Turned on computer");
return null;
}
}
class MacBook extends Computer {
public String turnON() throws RuntimeException, FileNotFoundException {
System.out.println("Turned on macBook");
try {
super.turnON();
} catch (IOException e) { // we have to handle this exception
e.printStackTrace();
}
return null;
}
}
view raw gistfile1.java hosted with ❤ by GitHub

Talking about Enums declarations

First off all we have to get a better understanding of enums declaration, it seems to be easier however there are some tricks involved. 
Let's start from the easiest part how to declare a enum or better where enums are allowed to be declared: 

1. Enums can be declared within a class like a member: 

e.g. 
class Employee {
Gender gender;
}
public class Something {
enum Gender { MALE , FEMALE };
public static void main(String[] args) {
Employee e = new Employee();
e.gender = Something.Gender.FEMALE;
}
}
view raw gistfile1.java hosted with ❤ by GitHub



Ok, that's a easy one, but be aware that the semicolon at the end of the statement is not required when there is no more statements below the enum. 
Notice that the class name is preceding the enum, it's required to access enums that are declared within a class. 

2. Enuns can be declared outside a class 

e.g. 
enum Gender {
MALE,
FEMALE
}
class Employee {
Gender gender;
}
public class TestEnum {
public static void main(String[] args) {
Employee e = new Employee();
e.gender = Gender.MALE;
}
}
view raw gistfile1.java hosted with ❤ by GitHub

    
 The most important thing here is when you declare a enum outside a class it cannot be marked as private or protected like a non-inner class 
 Different from enums declared within a class here we can access the enum by using only its name. 
  
 ! Important 
 Let's see what is allowed for enums declarations. 
  
 1. We cannot declare a enum within a method. 
 2. An enum declared outside a class cannot be marked as private or protected. 
 3. None of these modifiers are allowed for enums declared outside a class: final, static and abstract. 
 4. We can mark methods that are declared in a enum outside a class as final, static and syncronized but not abstract. 
 5. All access modifiers and static modifier are allowed for enums declared as a member(inside a class). 
  
 Declaring constructors, instance variables and methods in an enum.
  
 We can declare constructors, instance variables and methods inside an enum like you do for classes, each element of enum is a instance of enum that could contain its state and behavior. 

 e.g.
enum Gender {
MALE("M","Male"),
FEMALE("F","Female");
private String shortCode;
private String description;
Gender(String shortCode, String description) {
this.shortCode = shortCode;
this.description = description;
}
public String getShortCode() {
return shortCode;
}
public String getDescription() {
return description;
}
}
view raw gistfile1.java hosted with ❤ by GitHub
 

The import things here are: 

1. We cannot invoke directly the constructor, as you can see the arguments of constructors are declared with the element, in this case MALE and FEMALE. 
2. We can declare more than one argument for the constructor as well as overload it. 

The last feature that enums provide us is: 

 e.g.
enum Gender {
MALE("M","Male"),
FEMALE("F","Female") {
public String printSomething() {
return "Enum Gender for Female";
}
};
private String shortCode;
private String description;
Gender(String shortCode, String description) {
this.shortCode = shortCode;
this.description = description;
}
public String getShortCode() {
return shortCode;
}
public String getDescription() {
return description;
}
public String printSomething() {
return "Enum Gender";
}
}
view raw gistfile1.java hosted with ❤ by GitHub
 



It's like a default method for the element FEMALE, all the elements when invoke printSomething() get a message "Enum Gender", unlike when FEMALE invokes that method it will get "Enum Gender for Female".