From : http://java.boot.by/scjp-tiger/

Develop code that declares both static and non-static methods, and - if appropriate - use method names that adhere to the JavaBeans naming standards. Also develop code that declares and uses a variable-length argument list.

To set or get an instance variable, use methods with the names setVariable(...) and getVariable() for variables named variable:

private Object variable;

public void setVariable(Object var) {...}
public Object getVariable() {...}
					

For boolean instance variables you may provide a getter method named is... or has... that returns a boolean, that can be used conveniently in boolean expressions:

private boolean enabled;

public void setEnabled(boolean aBoolean) {...}
public boolean isEnabled() {...}
					

Varargs

In past releases, 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. Furthermore, it is upward compatible with preexisting APIs. So, for example, a method now has this declaration:

method (type a, type b, type ... arguments);
					

The three periods after the final parameter's type indicate that the final argument may be passed as an array or as a sequence of arguments. Varargs can be used only in the final argument position.

See the following program for example:

public class VarArgs {

	public static void main(String... args) {
		printUs("ONE", "TWO", "THREE");
		printUs("FOUR", "FIVE");
		printUs(new String[]{"SIX", "SEVEN"});
		printUs(); // empty array is allowed too
	}

	private static void printUs(String... args) {
		System.out.println("Var args method");
		for (String s : args) {
			System.out.println(s);
		}
	}

	private static void printUs(String arg1, String arg2) {
		System.out.println("Specific two argument method");
		System.out.println(arg1);
		System.out.println(arg2);
	}
}
					
It produces the following output:
Var args method
ONE
TWO
THREE
Specific two argument method
FOUR
FIVE
Var args method
SIX
SEVEN
Var args method
					

Purpose: add methods that can be called with variable-length argument list.

Heavily employed in formatting text output, aiding internationalization.

Syntax and semantics:

// Method declaration
public static void publish(String str, Object ... data) // Object[]
					
// Method calls
publish("one");             // ("one", new Object[] {})
publish("one", "two");      // ("one", new Object[] {"two"})
publish("one", "two", 3);   // ("one", new Object[] {"two", new Integer(3)})
					

Some more varargs examples:

					
import static java.lang.System.out;

public class VarargsDemo {

    public static void main(String ... args) {
        int day = 1;
        String month = "February";
        int year = 2005;

        flexiPrint(); 			// new Object[] {}
        flexiPrint(day); 		// new Object[] {new Integer(day)}
        flexiPrint(day, month);	// new Object[] {new Integer(day), month}
        flexiPrint(day, month, year); // new Object[] {new Integer(day), month, new Integer(year)}
    }

    public static void flexiPrint(Object ... data) { // Object[]
        out.println("No. of elements: " + data.length);
        for (int i = 0; i < data.length; i++) {
            out.print(data[i] + " ");
        }    
        out.println();
    }
}					

					
The output:
No. of elements: 0

No. of elements: 1
1
No. of elements: 2
1 February
No. of elements: 3
1 February 2005
					

Overloading resolution

Resolution of overloaded methods selects the most specific method for execution.

One method is more specific than another method if all actual parameters that can be accepted by the one can be accepted by the other. A method call can lead to an ambiguity between two or more overloaded methods, and is flagged by the compiler. Example:

...
// The method 'flipFlop(String, int, Integer)' is ambiguous for the type VarargsDemo
flipFlop("(String, Integer, int)", new Integer(4), 2004); // COMPILER ERROR!
...

private static void flipFlop(String str, int i, Integer iRef) {
	out.println(str + " ==> (String, int, Integer)");
}

private static void flipFlop(String str, int i, int j) {
	out.println(str + " ==> (String, int, int)");
}
					

This is a legal example:

...					
flipFlop("(String, Integer, int)", new Integer(4), 2004); // OK
...

private static void flipFlop(String str, Integer iRef,  int i) {
	out.println(str + " ==> (String, Integer, int)");
}
	
private static void flipFlop(String str, int i, int j) {
	out.println(str + " ==> (String, int, int)");
}					
					
The output will be:
(String, Integer, int) ==> (String, Integer, int)
					

Varargs and overloading

The example illustrates how the most specific overloaded method is chosen for a method call:

public class VarargsOverloading {

	public void operation(String str) {
		String signature = "(String)";
		out.println(str + " => " + signature);
	}

	public void operation(String str, int m) {
		String signature = "(String, int)";
		out.println(str + " => " + signature);
	}

	public void operation(String str, int m, int n) {
		String signature = "(String, int, int)";
		out.println(str + " => " + signature);
	}

	public void operation(String str, Integer... data) {
		String signature = "(String, Integer[])";
		out.println(str + " => " + signature);
	}

	public void operation(String str, Number... data) {
		String signature = "(String, Number[])";
		out.println(str + " => " + signature);
	}

	public void operation(String str, Object... data) {
		String signature = "(String, Object[])";
		out.println(str + " => " + signature);
	}

	public static void main(String[] args) {
		VarargsOverloading ref = new VarargsOverloading();
		ref.operation("1. (String)");
		ref.operation("2. (String, int)", 10);
		ref.operation("3. (String, Integer)", new Integer(10));
		ref.operation("4. (String, int, byte)", 10, (byte) 20);
		ref.operation("5. (String, int, int)", 10, 20);
		ref.operation("6. (String, int, long)", 10, 20L);
		ref.operation("7. (String, int, int, int)", 10, 20, 30);
		ref.operation("8. (String, int, double)", 10, 20.0);
		ref.operation("9. (String, int, String)", 10, "what?");
		ref.operation("10.(String, boolean)", false);
	}
}					
					
The output:
1. (String) => (String)
2. (String, int) => (String, int)
3. (String, Integer) => (String, int)
4. (String, int, byte) => (String, int, int)
5. (String, int, int) => (String, int, int)
6. (String, int, long) => (String, Number[])
7. (String, int, int, int) => (String, Integer[])
8. (String, int, double) => (String, Number[])
9. (String, int, String) => (String, Object[])
10.(String, boolean) => (String, Object[])					
					

Varargs and overriding

Overriding of varargs methods does not present any surprises as along as criteria for overriding is satisfied.

public class OneSuperclass {
	public int doIt(String str, Integer... data) throws java.io.EOFException,
			java.io.FileNotFoundException { // (1)
		String signature = "(String, Integer[])";
		out.println(str + " => " + signature);
		return 1;
	}

	public void doIt(String str, Number... data) { // (2)
		String signature = "(String, Number[])";
		out.println(str + " => " + signature);
	}
}					
					
import static java.lang.System.out;

public class OneSubclass extends OneSuperclass {

	// public int doIt(String str, Integer[] data) 	//  Overridden (a)
	public int doIt(String str, Integer... data) // Overridden (b)
			throws java.io.FileNotFoundException {
		String signature = "(String, Integer[])";
		out.println("Overridden: " + str + " => " + signature);
		return 0;
	}

	public void doIt(String str, Object... data) { // Overloading
		String signature = "(String, Object[])";
		out.println(str + " => " + signature);
	}

	public static void main(String[] args) throws Exception {
		OneSubclass ref = new OneSubclass();
		ref.doIt("1. (String)");
		ref.doIt("2. (String, int)", 10);
		ref.doIt("3. (String, Integer)", new Integer(10));
		ref.doIt("4. (String, int, byte)", 10, (byte) 20);
		ref.doIt("5. (String, int, int)", 10, 20);
		ref.doIt("6. (String, int, long)", 10, 20L);
		ref.doIt("7. (String, int, int, int)", 10, 20, 30);
		ref.doIt("8. (String, int, double)", 10, 20.0);
		ref.doIt("9. (String, int, String)", 10, "what?");
		ref.doIt("10.(String, boolean)", false);
	}
}					
					
The output:
Overridden: 1. (String) => (String, Integer[])
Overridden: 2. (String, int) => (String, Integer[])
Overridden: 3. (String, Integer) => (String, Integer[])
4. (String, int, byte) => (String, Number[])
Overridden: 5. (String, int, int) => (String, Integer[])
6. (String, int, long) => (String, Number[])
Overridden: 7. (String, int, int, int) => (String, Integer[])
8. (String, int, double) => (String, Number[])
9. (String, int, String) => (String, Object[])
10.(String, boolean) => (String, Object[])					
					

Another method signature:

...
public int doIt(String str, Integer[] data) 	//  Overridden (a)
// public int doIt(String str, Integer... data) // Overridden (b)
...
					
However, the method will be invoked from superclass:
1. (String) => (String, Number[])
2. (String, int) => (String, Number[])
3. (String, Integer) => (String, Number[])
4. (String, int, byte) => (String, Number[])
5. (String, int, int) => (String, Number[])
6. (String, int, long) => (String, Number[])
7. (String, int, int, int) => (String, Number[])
8. (String, int, double) => (String, Number[])
9. (String, int, String) => (String, Object[])
10.(String, boolean) => (String, Object[])