Methods and Variables within a class are collectively known as members.There are two types of modifiers that can be used for a member declaration
Every member you declare has an access control, whether you explicity type one or not. Members accessed with using the dot operator (.) must belong to the same class, the this keyword is used to reference the currently executing object.
Member Access Modifiers |
||||||||||||||||
Public Access | When the member is declared protected it means that only the following can access the member
|
|||||||||||||||
Protected Access | When the member is declared protected it means that only the following can access the member
|
|||||||||||||||
Default Access | When the member has no modifier it has default access only the following can access the member
|
|||||||||||||||
Private Access | When the member is declared protected it means that only the following can access the member. Methods that are declared private are implicity final.
|
|||||||||||||||
Member non-Access Modifers |
||||||||||||||||
Final | When used this means that the member (method or variable) cannot be overridden. A variable in a interface is implicity marked as final. | |||||||||||||||
Abstract | An abstract method is a method that has been declared but not implemented, in other words the method contains no functional code. The abstract method must be implemented in either the sub-class or any other subclass that has extend it. | |||||||||||||||
Transient | This modifier can only be applied to variables, you are telling JVM to skip this variable when you attempt to serialize the object declaring it. | |||||||||||||||
Synchronized | When used this means that the method can be accessed by only one thread at a time. It can only be applied to methods. | |||||||||||||||
Native | Indicates that a method is implemented in a platform-dependent language such as C. | |||||||||||||||
Strictfp | Indicates that strict floating-point will be adhered too. | |||||||||||||||
Static | The best way I can describe a static variable or method is that one copy of the static member is contained in memory that allows all instances to access this copy, an example of this is like having a single counter variable that all classes can update. There is a rule that states that a static method of a class can't access a nonstatic member or variable of its own class. Static methods are also declared final implicity. You can Make Static: Methods, Variables and Top-Level nested Classes There is also no this reference when using static, also all static variables and methods are loaded first in order of appearance, you may find a simple static block of code to initialize variables or execute code.
|
Quick lookup table to show the access to members permitted by each modifier
Modifier | Class |
Package |
Subclass |
World |
public | Y |
Y |
Y |
Y |
protected | Y |
Y |
Y |
N |
no modifier (default) | Y |
Y |
N |
N |
private | Y |
N |
N |
N |
Now for some examples
Method Examples |
|
Public Access | public void coolMethod() { /* any code that you want */ } |
Protected Access | protected int coolMethod() { /* any code that you want */ } |
Default Access | int coolMethod() { /* any code that you want */ } Note: no access modifier at the beginning of the statement |
Private Access | private String coolMethod() { /* any code that you want */ } |
Final | public final void superCoolMethod() { /* any code that you want */ } |
Abstract | public abstract int coolMethod(); Note: No curly braces at the end, code for this method must be in a sub-class |
Synchronized | public synchronized Record getUserInfo() { /* any code that you want */ } Note: synchronized can never be used with abstract but you can use the other access modifiers |
Static | public static void myStaticMethod() { /* any code that you want */ } Note: this method is shared by all objects within the class, there is only one copy in memory |
Local Variable Examples (contained in method or code block) |
|
No Modifier | int bonus = 1.1; Note: the default modifier is local to the block of code |
Final | final int bonus = 1.1; Note: the final non-access modifier is the only option for a local variable |
non-Local (instance) Variable Examples |
|
Public | public counter = 0; |
Protected | protected counter = 0; |
Private | private counter = 0; |
final | public final bonus = 1.5; Note: a final variable has to be initialized, it can be initialized in the constructor of a class, also a variable in an interface is implicity marked as final whether you declare it or not |
Static | public class VariableExample { public void increment() { var1.increment(); # This Java program will increase the static variable classCounter everytime a new class is created, the instanceCounter will only get affect everytime we call the increment method of that instance, the localCounter gets reset everytime we call the increment method |
A example using abstraction and using the keywords this and super
Abstraction, this and super | public class arrayTest { public static void main(String[] args) { test1 t1 = new test1(); // create the test1 object which extends the abstract class test2 t1.testMethod(); // call the abstracted method t1.testMethod2(); // calling the normal inheriated method } } class test1 extends test2{ System.out.println("local testMethod variable count = " + count); // local variable abstract class test2 extend test3{ // the abstract class int getSuperCount() { class test3 { Note: there is lots going on in this program buts its a good refresher and not a difficult program to work out. By the way there is no such thing as super.super you must get the super class to access the so called super.super class. |
You have different rules on returns types depending if you overriding or overloading
Here are some examples regarding the return types
Return a subtype of a type | Number getNumber(){ return Integer.valueOf(1); } |
Return a null of a reference type return type | Number getNumber(){ return null; } |
Return a narrower primitive data type if the return type is a primitive | long getNumber() { int myInt =2; return myInt; } |
Return a primitive data type wrapper if the return type is primitive | long getNumber(){ return Long.valueOf(1); } |
Return a wrapper of a primitive to a primitive that is the same or wider | long getNumber(){ return Integer.valueOf(1); } |
Just have the return statement but only if modifier is void | public void returnNothing() { return; } |
When passing a variable or a object to a method two outcomes happen
Passing Variable | When you pass a variable to a method, you are passing a copy of the variable which means you can do whatever you want to the variable passed but you will not affect the source of the variable. |
Passing Object | When you pass a object to a method you are passing the reference to that object not the object itself, it represents a way to get to a specific object in memory, thus any changes to the object that occur inside the method are being made to the object whose reference was passed. |
Overloaded methods lets you reuse the same method name in a class, but with different arguments (and optionally a different return type), you help out other programmers by supplying different argument types so they don't have to perform conversions before invoke your method.
The rules for overloading are as follows
Overloaded Example | // Original Method public void changeSize(int size, String name, float pattern) { ... } // Overloaded Methods public void changeSize(int size, String name) { ... } public void changeSize(float pattern, String name throws IOException) { ... } public int changeSize(int size, float pattern) { ... } |
So how does Java determine what overloaded method to use, its uses a 3 phase check of the method signature as detailed below, note that once Java finds a match the other phases are disguarded, think of it as precedence, phase one having the higher precedence
Phase One | Performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity (var args) method invocation Within Phase 1, if multiple methods meet this criteria the best method is selected by
|
Phase Two | Allows boxing and unboxing, but ignores variable arity (var args) method invocation |
Phase Three | Allows overloading to be combined with variable arity (var args), boxing and unboxing Note: var args methods will be last to match if better options exist |
Here are some examples of the above
Examples of Java 3 phase method signature testing | public class Test { public static void main(String[] args) { int i = 1; Long l = 2L; char c = 3; T1 t1 = new T1(i); // int test, will use int constructor T1 t2 = new T1(l); // Long test, will use long constructor T1 t3 = new T1(c); // char test, will use int constructor byte b = 4; long l2 = 5; short s = 6; float f = 5.6f; double d = 5.6; Character c2 = 7; T1 t4 = new T1(b); // byte test, will use int constructor T1 t5 = new T1(l2); // long test, will use long constructor T1 t6 = new T1(s); // short test, will use int constructor // T1 t7 = new T1(f); // No Constructor for float, compile error T1 t8 = new T1(d); // double test, will use Double constructor T1 t9 = new T1(c2); // Character test, will use char constructor } } class T1 { T1(int a){ System.out.println("int constructor"); } T1(long a){ System.out.println("long constructor"); } T1(char a){ System.out.println("char constructor"); } T1(Character a){ System.out.println("char constructor"); } T1(Double d) { System.out.println("Double constructor"); } } |
Overridden Methods
Methods can be overridden and overloaded, constructors can only be overloaded. Overload methods and constructors let you use the same name but different argument lists, overriding lets you redefine a method in a sub-class when you need new sub-class behavior unless the method is mark final. In the case of a abstract method you have no choice you must override it.
The rules for overriding are as follows
The key benefit of overriding a method is to define behavior that is specific to the class
Overriding example | public class Animal { // This will be the super class class Horse extends Animal { // Horse is a sub-class of Animal public void printAnimal { class Lion extends Animal { // Lion is a sub-class of Animal Note: to call methods from the superclass use the super keyword. |
Difference between Overloaded and Overriding
Overloaded |
Overridden |
|
Argument list |
Must change | Must not change |
Return type |
Can Change | Must not change |
Exceptions |
Can Change | Can reduce or eliminate Must not throw new or broader checked exception |
Access |
Can Change | Must not make more restrictive (can be less restrictive) |
Invocation |
Reference type determines which overloaded version (based on declared argument types) is selected. Happens at compile time. The actual method that's invoked is still a virtual method invocation that happens at runtime, but the compiler will always know the signature of the method that is to be invoked. So at runtime, the argument match will have already been nailed down, just not the actual class in which the method lives | Object type (in other words, the type of the actual instance on the heap) determines which method is selected Happens at runtime. |