/* * Your professor was trying to show you "order of operations" in a sense, but it is poorly structured. * Below is the code that your original code compiles into. I will explain why things are moved. */ public class M { // ==================================== // THE CONSTRUCTOR // ==================================== // | A constructor is called in any line // | that looks like "new MyType(...)" // | The "..." means there can be any // | number of arguments. In this case // | there are none. // | // | In the original source file you saw: // | // | . . . . . . . . . . . . . . . . . // | { // | System.out.println("Scope1"); // | } // | // | M() { // | System.out.println("Constructor"); // | } // | // | { // | System.out.println("Scope2"); // | } // | . . . . . . . . . . . . . . . . . // | // | In the code above (from the original) // | there were these 'random' blocks with // | no name. When you compile these, they // | are placed in the BEGINNING of // | the constructor in the order of they // | appear in the source. M() { System.out.println("Scope1"); System.out.println("Scope2"); System.out.println("Constructor"); } // ==================================== // THE INSTANCE METHOD // ==================================== // | This method belongs to "M". // | I think the professor was trying // | to show you that you can declare // | extensions of classes in-line // | through various ways. public void test() { // Here we make a new "K" but we // override "print". This new // implementation of "K" is stored // in the variable "k". K k = new K(){ @Override public void print() { System.out.println("Anonymous K print"); } }; // We now call "print" for "k". k.print(); // Here we do the same thing as above // but instead of storing the new // implementation in a variable, // we call the "print" method in-line. new K(){ @Override public void print() { System.out.println("Anonymous K"); } }.print(); // Same as above with in-line, but we // add a new method "smth". You can // call this method in-line too even // though it does belong to the original // "K" class defined at the bottom of this // file. // The truth is, all of these in-line classes // generate new files when they are compiled. // They are called "Anonymous" classes. // Since they behave as independant classes // you can define new methods in them and // even call them like in this example. // However if you were to store this in a variable // of type "K" with the name "test" you would // be unable to do "test.smth()" because // "smth" does not belong to K, it belongs // to the anonymous class. new K(){ public void smth() { System.out.println("Anonymous K2"); } @Override public void print() { System.out.println("Anonymous K2 print"); } }.smth(); } // ==================================== // THE MAIN (Entry-point) METHOD // ==================================== // | This is where your java program // | typically begins & ends. As you can // | see there are two "println" calls. // | One in the beginning. // | One in the end. // | In between a new instance of "M" is // | created. That will call the constructor. // | Then it calls the instance method of "M" // | called "test". // | // | After test is run the ending print is // | called and the program will terminate. // | // | There is a "gotcha" in this class though. // | You have a 'static` block below. // | Before ANYTHING happens with a class // | java will check if it has a "static block" // | and will run the code inside there first. // | Yes, it runs before constructors. // | Yes, it runs before the main method. public static void main(String[] arrstring) { System.out.println("Main1"); // First line executed M m = new M(); m.test(); System.out.println("Main2"); // Last line executed } // ==================================== // THE STATIC BLOCK // ==================================== // | This is a special method sort of // | like a constructor, but it is even // | more unique. // | The static block is only called ONCE. // | This occurs when the class is loaded // | by the java virtual machine. // | // | Since this is also the class with // | the "main" method, it is loaded instantly. // | This method precedes all others. // | // | If we had another class "O" in a file // | "O.java" we could do the following: // | // | new O(); // | // | Java will check if it's loaded, and if // | it is not, it will load the class, then // | check if it needs to run the static block. // | If one exists it runs it. Lastly it does // | what we told it to do, call the constructor. static { System.out.println("Static"); } // ==================================== // THE INNER CLASS // ==================================== // | This is just a class within a class. // | In our case it has: // | * Constructor with no args // | * abstract "print" method. // | // | The class is abstract so the following // | code is invalid: // | // | K variable = new K(); // | // | However the following code IS valid: // | // | K variable = new K(){ // | @Override // | public void print() { // | System.out.print("hi"); // | } // | }; // | // | Why is that? // | Because of the 'abstract' modifier. // | Abstract means a class cannot be constructed // | as-is. It will need to be extended first. // | Remember above where we talked about // | "Anonymous" classes? The generated // | anonymous classes do exactly this. They // | extend the abstract class which lets us // | use them like seen in the "test" method above. public abstract class K { public K() { System.out.println("ScopeK"); System.out.println("K"); } // ==================================== // THE ABSTRACT METHOD // ==================================== // | Much like an abstract class, these // | require extensions. Refer above to // | the "test" method. You can see that // | we "@Override" the methods, which // | makes it clear that they are extensions // | of this method, overriding their behaviour. public abstract void print(); } }