Declares a method, (possibly with a body), so that it can be referenced via a method reference, called, and overridden.
A method is a named group of statements that can be referred to and executed via a method invocation statement. A method declaration introduces a method to the program. The group of statements that are executed are called the method's implementation. A method declaration includes the method's name (and formally, it's signature), which can be used to refer to the method elsewhere, though it is not always necessary for a declaration to include the implementation.
A method declaration consists of:
| 1 | modifier-list return-type name (parameter-list)array-dimsthrowsthrow-list
			body | 
| 2 | modifier-list <type-parameter-list>annotation-list return-type name(parameter-list)array-dimsthrowsthrow-list
			body | 
where...
| modifier-list | is a possibly empty set of keywords and annotations that can
			contain: 
 | 
| return-type | is a type denoting what type of value, if any,
			the method returns. The type may have its own annotations. If voidis specified as the method's return type,
				the method returns no value. | 
| name | is an identifier that names the method. | 
| parameter-list | is a comma-separated list of parameters, the first of which may be a receiver parameter and the last of which may be a variable-arity (var-args) parameter. | 
| parameter | is made up of three components, in order: 
 | 
| array-dims | is any number of consecutive pairs of []strings,
			optionally separated (e.g.[][] [])
			and/or split (e.g.[][][ ]) by
			whitespace. Each[]pair may be annotated with an
			annotation that targets type use. (Such annotations target the
			respective dimension of the array that the[]represents.) | 
| throw-list | A list of exception types denoting what the method is permitted to throw. | 
| body | is either a semicolon ;or a block statement. | 
| type-parameter-list | is a comma-separated list of type parameters. Each type parameter
			is an identifier. The identifier may be followed by the keyword extendsand then a set of types to establish an upper bound. The set of types
			upper-bounding the parameter must be delimitted by the&token, and all but the first must beinterfacetypes. | 
such that...
@
		character, present in any annotation, may have any amount of
		whitespace before or after it.  If not separated by
			whitespace, two consecutive keywords or identifiers will be parsed as
			a single identifier token. For example, finalstatic is
			parsed as a single identifier. Annotations, however, never need
			whitespace immediately before them, even if a keyword precedes them,
			since the @ symbol indicates to Java the end of the
			previous token and the beginning of an annotation: public@SuppressWarnings("all")void test() {	}
				A whitespace is not needed, but is allowed, before or after the @.
				Since @SuppressWarnings also ends in a closing
				parenthesis, whitespace is not required after it either.
			
				For annotations that end in an identifier, e.g. @Override,
				whitespace must come after them if an identifier or keyword
				follows, to separate the annotation's name from the succeeding
				token:
			
public @Overridevoid test() {	} // Does not compile: Unknown annotation "Overridevoid" and method has no return type.abstract or native keywords,
				or
			default
				keyword,
			; for its body. Otherwise, the method must have a
		block statement as its body.
	1 A normal method declaration.
2 A generic method declaration, with type parameters.
A method can be declared directly within a class or interface, or within an enum's body declaration (after the constant list). Method declarations can override methods inherited from a parent type.
Annotations can be placed in two distinct places in a method declaration, either in the modifier-list, intermixed with keyword modifiers, or, if type parameters are included, after the type-parameter-list and immediately before the return type.
Annotations included in the method declaration's modifier list will apply to:
If the annotation targets both type-uses and methods, the annotation applies to both the return type and the method. If the annotation does not target either, a compile error occurs.
If the method declares type parameters and the annotation is placed after the type-parameter-list, the annotation must target type-uses and the annotation applies only to the return type.
	Keyword modifiers are any of public, protected,
	private, static, final, synchronized,
	strictfp, default, abstract, and
	native.
Access modifiers affect the accessibility of a method, which determines from where the method may be invoked (via a method invocation statement), referenced (via a method reference), and overridden. Without any access modifier keywords, a method's accessibility is package-protected, meaning that it can be accessed by code within the same package as where it is declared. If the method has the access modifier:
public, it can be accessed from anywhere,protected, it can be accessed from within the
		top-level class it is declared in and within all of the subclasses of
		the immediate, surrounding class it is declared in,private, it can be accessed from within the top-level
		class it is declared in only.A method can have at most one access modifier keyword, otherwise a compile error occurs.
| final | The finalmodifier, when used on a method, disables
			the ability for any subclasses to override the method. Despite having
			no effect, it may be used onprivatemethods. It cannot
			be used on declarations directly in aninterface, nor on
			any method declaredabstractornative. | 
| static | The staticmodifier causes a method to be a class
				method rather than an instance method. Resultingly, the
			method may not refer tothis,super, or any
			other instance methods or instance fields without qualifying such
			references with an explicit instance. This is in contrast to instance
			methods, which, in their bodies, may access instance-specific members
			without explicit qualification. Instance methods additionally may
			refer tothisandsuper. | 
| strictfp | The strictfpmodifier causes all floating point
			computations written in the body of a so modified method to
			consistently operate on the normal float/double value set (depending
			on expression type) across implementations. See strictfp for details. | 
| synchronized | A synchronizedmethod synchronizes on:
 before it begins executing. The lock is released after the method completes. | 
| abstract | Abstract method declarations cannot provide a block statement
			body. abstractmethods cannot bestatic,final,native,private,synchronized,
			norstrictfp. Any type containing anabstractmethod must also, itself, beabstract(interfaces
			are always inherentlyabstract).abstracttypes cannot be instantiated directly; only concrete sub-types can be
			instantiated directly.
				Any non- | 
| native | The native modifier is used to declare a method whose
			implementation is provided through some other language, typically C
			or C++. Such methods' implementations are connected to the program
			through the Java Native Interface. 
				The  | 
| default | The default modifier allows a method declared in an interfaceto include an implementation.defaultmethods are not
			abstract. A method declaration containingdefaultmust
			include a block as its body. | 
	A method's return type determines the type of the method invocation
	that invokes it. Specifically, any method invocation (e.g. doSomething())
	will be an expression whose type is the same as the return type of the
	method it invokes. For example, the following method's return type is int:
int getRandomNumber() {	return (int) (Math.random() * 10);	}// Method declaration
	so the expression that invokes it (getRandomNumber()) is
	an int expression, that can be assigned to an int
	variable:
int result = getRandomNumber();
	If a method has a return type other than void, it is
	required to execute at least 1 return
	statement at the end of every possible path of normal
	execution that does not throw a value.
finally block, a method may execute
	multiple return statements. In such a case, the last abrupt
		exit from execution of the method takes precedence, i.e., the
	final return or throw that is executed is
	what the method completes with: int test() {
	try {
		return 5;
	} finally {
		return 10;
	}
}test() returns 10,
	even though the return 5 does in fact get executed.
 If a path of execution does not end, (e.g., if you have an
	infinite while or for loop), then that path
	is not required to return a value: int neverEndingMethod() {
	while(true);
	
	// No return statement required.
	// In fact, writing a return statement here is a compile time error, since the return statement would be unreachable.
}A method's parameters are a list of inputs that must be provided upon a call to the method. The variables declared in the parameter list are accessible throughout the body of the method and are given values when the method is called.
A method may be overloaded if there are two or more method declarations with its same name, but different signatures. A method's signature includes the ordered list of types of its parameters, and methods with different ordered lists of parameter types are considered different when resolving overloads to execute a method invocation statement. The presence of a receiver parameter has no effect on overload resolution, since method invocation statements cannot provide an argument for that parameter explicitly.
Overload resolution happens statically, so the type of the expression used as an argument in the method invocation is what determines the method to be called.
	The receiver parameter is a parameter whose type is that of the class
	the instance method belongs to and whose parameter name is the keyword
	this. It may be annotated as any other parameter, but it
	otherwise has no effect on the code; it does not change the method's
	signature or affect overloading or invoking. The this
	keyword is innately accessible in instance methods without needing to
	be declared.
	The final parameter in a parameter list can optionally be a variable-arity
	parameter, by succeeding its type with the ... token. Such
	a parameter allows any number of arguments, of the parameter's type, to
	be provided in a method invocation statement as the final arguments in
	the statement's argument list. An array is automatically created from
	the arguments provided, and in the body of the method, the varargs
	parameter is useable in the exact same way as an array.
Generic type parameters declared in the type-parameter-list can be referenced throughout the remainder of the method, including in the method's parameter-list, body, and even the method's throw-list. Any type parameters declared in the type-parameter-list may also be referenced anywhere else within the type-parameter-list. This allows for recursive type parameters.
When used as a type in the parameter-list, a type parameter's upper bound is used for overload resolution.
   <T> void test(T input) {	}
// void test(Object input) {	} // Compiler error, generic method test(T) conflicts with this method.This conflict can be avoided in cases where it is possible to upper-bound the parameter:
   <T extends Dog> void test(T input) {	}
   void test(Object input) {	} // Does not conflict; test(T) cannot be called with ANY object.However, the upper bound, if provided explicitly, can still conflict with other methods:
   <T extends Dog> void test(T input) {	}
// void test(Dog input) {	} // Conflicts with test(T), since T's upper bound is Dog.
	Type parameters may also be used in the throw-list
	to declare a method that throws a generic exception. This is only
	possible if the type parameter being used is bounded so that it is
	guaranteeably a type that can be thrown (Throwable or a
	subclass thereof).
Type parameters can be used as any other type within the body of the method they are declared in.
	The array-dims is a legacy
	syntactical element that allows the pairs of brackets ([]),
	used to declare a dimension of an array type for the return type of the
	method, to be placed after the parameter list of a method declaration.
	It can consist of any number of pairs of brackets. The array dims
	specified in this location are applied to the return type as if
	appended to the return type.
throws Clause
	The throws clause declares what exceptions a method can
	throw. Any checked exceptions that are thrown in the method body under
	any path of execution must be assignable to at least one of the types
	listed in the throws clause, otherwise, the code will not
	compile. The same exception may be listed in the throw-list more than once. Additionally, RuntimeExceptions
	and Errors, (both of which are the root unchecked types),
	and their subtypes, do not need to be listed, but may be.
	The rules governing required types in the throw-list
	apply only to checked exceptions that the method may abruptly terminate
	due to the throwing of. Because of this, if a checked exception is
	thrown and caught within the method's body, the exception does not need
	to be listed in the throws clause.
static Method Restrictions
	
		Example of inability to reference instance properties from a static
		method body:
	
class Dog {
	static Dog someDogInstance = new Dog();
	int age; // Instance field
	static void grow() {
		// age++; // Not allowed; no Dog instance to increment the age of.
		
		Dog x = new Dog(); // Make a Dog instance.
		x.age++;
		
		someDogInstance.age++;
	}
	
	void growThisDog() {
		age++; // Instance methods are called with an instance, and that instance is used implicitly here in the method body.
		this.age++; // Equivalent to age++
		
		someDogInstance.age++; // Instance methods can still access static data directly, but not vice versa.
	}
}abstract Methods
	An expression whose type is an abstract type can still be used to invoke abstract methods in that abstract type, though the implementation that gets executed depends on the concrete type of the value the expression evaluates to:
abstract class Animal {
	abstract void makeSound();
}
class Dog extends Animal {
	void makeSound() {
		System.out.println("Woof");
	}
}
class Cat extends Animal {
	void makeSound() {
		System.out.println("Meow");
	}
}
class Test {
	void test() {
		Animal a = Math.random() < .5 ? new Dog() : new Cat();
		a.makeSound(); // May print "Meow" or "Woof"
	}
}
		abstract methods must be implemented by any concrete
		subclasses that inherit them:
	
abstract class A {
	abstract void test();
}
class Sub extends A {
	// Sub must implement test since Sub is not an abstract class, test is abstract, and test was inherited by Sub from A.
	@Override void test() {
		System.out.println("Sub");
	}
}
class Test {
	static A getNewA() {
		return new Sub();
	}
	void test() {
		A obj = getNewA();
		obj.test();
	}
}Example of how return type affects method invocation statements:
public class Test {
	static int x() {
		System.out.println("x");
		return 5;
	}
	
	static void y() {
		System.out.println("y");
	}
	
	public static void main(String[] args) {
		int a = x();
		// int b = y(); // Not allowed; y does not return anything.
		// String c = x(); // Not allowed; x does not return a String.
		
		System.out.println(a); // Prints 5.
	}
}Example of return type imposing return requirements on method body:
int test() {
	if (Math.rand() > 0.5) {
		return 4;
	}
	// Function may reach this point without returning a value; this is not allowed.
}Method parameters determine which method gets invoked by a method call:
void test(int x) {
	System.out.println("Test was called with the number: " + x);
}
void test(String x) {
	System.out.println("Test was called with: " + x);
}
void runTest() {
	test("abc");
}
		The output of invoking runTest() is:
	
Test was called with: abcChanging the type, but not the value, of an expression used as an argument for a method, can cause a different overload to be invoked:
void test(String x) {
	System.out.println("STRING VERSION CALLED");
}
void test(Object x) {
	System.out.println("OBJECT VERSION CALLED");
}
void runTest() {
	test((Object) "abc"); // Provide a String, but casted to type "Object."
}
		In the above example, test(Object) will be invoked with a
		String as its argument, leading to the following output:
	
OBJECT VERSION CALLEDAny number of arguments can be provided in place of a varargs parameter:
void test(String... args) {
	System.out.println("TEST was called with: " + args.length + " argument(s).");
}
void runTest() {
	test(); // Provide no arguments.
	test("a", "b", "c"); // Provide three arguments.
	test("a"); // Provide one argument.
}
		A call to runTest() prints:
	
TEST was called with: 0 argument(s).
TEST was called with: 3 argument(s).
TEST was called with: 1 argument(s).A var-args parameter can also be unambiguously provided an array argument:
test(new String[] {"a", "b", "c"});Such method call prints:
TEST was called with: 3 argument(s).throws Clause
	
		Use of a type parameter in a throws clause:
	
<T extends Exception> void doSomethingThenThrow(T exception) throws T {
	if (Math.random() < 0.5)
		throw exception;
}This can allow callers to have to handle checked exceptions only when calling the method with checked exceptions:
doSomethingThenThrow(new RuntimeException()); // This invocation effectively declares "throws RuntimeException", so no need to wrap in try-catch.
try {
	doSomethingThenThrow(new Exception()); // This invocation effectively declares "throws Exception"
} catch (Exception e) {
}Methods declared with array-dims
// Two total array dims, both after parameter list.
int x()[][] {
	return new int[1][1];
}
// Three total array dims: two in return type, one after parameter-list.
int[][] x()[] {
	return new int[1][1][1];
}throwing Without throws Clause
	
		A throws clause is only necessary if the method may
		terminate with a checked exception:
	
void riskyMethod() throws Exception {
	if (Math.random() < .1)
		throw new Exception("Throwing an exception!");
}
void test() {
	try {
		riskyMethod();
	} catch (Exception e) {
		// Ignore the exception!
	}
}
		The above example compiles since the body of the method test()
		does not have any code deemed to potentially complete abruptly due to
		a checked exception. If the try-catch were
		not used to wrap the call to riskyMethod(), Exception
		or its supertype, Throwable, would need to be listed in
		the throw-list.
	
final modifier never has an effect on private
		methods, since such instance methods are not dynamically bound, and
		since such static methods cannot be overridden anyway.
	
			Type parameters can be used to throw a checked exception in an
			unchecked fashion by allowing the type of the expression provided to
			a throw statement to be an unchecked exception while the
			value itself remains a checked exception. This can be done by casting
			a checked exception to a generic type parameter, and then throwing
			the result:
		
public static @SuppressWarnings("unchecked") <E extends Throwable> void throwUnchecked(Throwable t) throws E {
	throw (E) t;
}
			Any call to the method that does not explicitly provide type
			arguments will infer E to be RuntimeException,
			however, the exception provided to the method will still be thrown,
			even if it is a Throwable instance.
		
			The cast to E does not fail, since E is
			upper-bounded by Throwable and the argument to the
			method is any Throwable instance.
		
The compiler prefers method overloads that are closer to the type of the expression being used to invoke a method. A call can be ambiguous if two or more overloads can plausibly be called by a single method invocation statement. There are many cases where this can happen, most often with a var-args overload or a null argument, but sometimes with overloads whose problematic parameters are sibling types in a type hierarchy:
void varargs(int... x) {	}
void varargs(Integer... x) {	}
			Calling varargs(1) will fail. The caller is required to
			provide an array explicitly to pick which method is desired, such as
			through: varargs(new int[] {1}).
		
Another example, involving a class hierarchy:
// Wrapper class
public class AmbiguityTest {
	interface X {	}
	interface Y {	}
	class Z implements X, Y {	}
	
	static void m(X x) {	}
	static void m(Y y) {	}
	
	public static void main(String[] args) {
		// m(new Z()); // Ambiguous method call; expression of type Z is equidistant from both X and Y. (X & Y are the types of the parameters of the two method overloads of m.)
	}
}
			Such can be resolved using a cast, e.g. m((X) new Z())
			will invoke m(X). If a method overload is introduced to
			explicitly accept a Z parameter, such overload will be
			used instead, since the method invocation has an argument of type Z.
		
			The null literal can often lead to ambiguity, because it
			can directly exist as an expression of any reference type:
		
// Wrapper class
public class AmbiguityTest {
	interface X {	}
	interface Y {	}
	class Z implements X, Y {	}
	
	static void m(X x) {	}
	static void m(Y y) {	}
	
	public static void main(String[] args) {
		// m(null); // Ambiguous method call with null literal.
	}
}
			A cast can clarify the type of the expression null in
			the method call and resolve the ambiguity in this case as well.
			Adding a more specific overload in the class hierarchy will cause the
			method invocation to prefer that as well:
		
// Wrapper class
public class AmbiguityTest {
	interface X {	}
	interface Y {	}
	class Z implements X, Y {	}
	
	static void m(X x) {	}
	static void m(Y y) {	}
	static void m(Z z) {	}
	
	public static void main(String[] args) {
		m(null); // Calls m(Z)
	}
}However, if there is no overload that is a subtype of other overloads, the ambiguity will persist:
// Wrapper class
public class AmbiguityTest {
	static void m(String x) {	}
	static void m(Number y) {	}
	
	public static void main(String[] args) {
		// m(null); // Ambiguous
	}
}