Showing posts with label static. Show all posts
Showing posts with label static. Show all posts

Friday, February 25, 2011

Chapter 55: Static Inner Classes

In the chapter on Inner classes, I had promised that we will look in more detail about the different types of inner classes. Well here we are. This is the last and final type of inner classes. “Static” Inner Classes.

So, without any further delays, lets get Started!!!

Static Inner Classes

Actually static inner classes aren’t inner classes at all, by the standard definition of an inner class. While an inner class enjoys that special relationship with the outer class (or rather the instances of the two classes share a relationship), a static MyStaticExInnerClass class does not. It is simply a non-inner (also called “top-level”) class scoped within another. So with static classes it’s really more about name-space resolution than about an implicit relationship between the two classes.

A static MyStaticExInnerClass class is simply a class that’s a static member of the enclosing class:
class MyExOuter {
static class StaticInner { }
}

The class itself isn’t really “static”; there’s no such thing as a static class. The static modifier in this case says that the MyStaticExInnerClass class is a static member of the outer class. That means it can be accessed, as with other static members, without having an instance of the outer class.

Instantiating and Using Static Inner Classes

You use standard syntax to access a static MyStaticExInnerClass class from its enclosing class. The syntax for instantiating a static MyStaticExInnerClass class from a non-enclosing class is a little different from a normal inner class, and looks like this:

class MyExOuter {
static class MyStaticExInner {void do() { System.out.println("hi"); } }
}
class Test {
static class B2 {void goB2() { System.out.println("hi 2"); } }
public static void main(String[] args) {
MyExOuter.MyStaticExInner n = new MyExOuter.MyStaticExInner();
n.do();
B2 b2 = new B2();
b2.goB2();
}
}
Which produces
hi
hi 2

Exam Tip:
Just as a static method does not have access to the instance variables and nonstatic methods of the class, a static Inner class does not have access to the instance variables and nonstatic methods of the outer class. Look for static Inner classes with code that behaves like a nonstatic (regular inner) class. Be careful to spot them and you’ll be scoring points in the question without any trouble…

Previous Chapter: Chapter 54 - Anonymous Inner Classes

Next Chapter: Quick Recap - Inner classes

Wednesday, January 26, 2011

Quick Recap: Chapters 6 – 14

Chapter 6: Encapsulation

• Encapsulation hides implementation details behind an Interface or an API
• Encapsulated code has two features:
     o Instance variables are hidden (Usually with private modifier)
     o Getter and Setter methods are provided to give access to instance variables

Chapter 7: Inheritance

• Inheritance allows a class to be a subclass of a superclass and thereby inherit code and functionality of the superclass
• All classes are subclasses of Object and therefore they inherit Objects methods
• IS-A relationship is expressed with the keyword extends
• HAS-A means an instance of one class “has a” reference to an instance of another class
• Single, Multilevel, Multiple (Partial of course) and Hybrid are the types of inheritance

Chapter 8: Polymorphism

• Polymorphism means many forms
• A reference variable is always of a single, unchangeable type, but it can refer to a subtype object
• A single object can be referred to by reference variables of many different types, as long as they are the same type or a supertype of the object
• The reference variables type (not the objects type), determines which methods are called
• Polymorphic method invocations apply only to overridden instance methods

Overriding & Overloading:

• Methods can be both overridden and overloaded
• Constructors can only be overloaded
• Abstract methods must be overridden by the first concrete class (non abstract class)
• Overridden methods:
     o Must have the same argument list
     o Must have the same return type or a covariant return
     o Must not have a more restrictive access modifier
     o Must not throw new or broader checked exceptions
     o May throw fewer or narrower checked exceptions or any unchecked exception
• Final methods cannot be overridden
• Only inherited methods may be overridden (private methods are not inherited)
• You can use super.OverriddenMethodName() to call the super class’s version of the method
• Overloading means reusing a method name
• Overloaded methods
     o Must have different arguments list
     o May have different return types (But you cannot overload a method by just changing the return type)
     o May have different access modifiers
     o May throw different exceptions
     o Overloading is not Polymorphism
• Reference type determines which overloaded method will be used at compile time (In case you have overloaded a method that is available in the parent class)

Chapter 9: Reference Variable Casting

• There are two types of reference variable casting: downcasting and upcasting
• Downcasting: If you have a reference variable that refers to a subtype object, you can assign it to a reference variable of the subtype. You must make an explicit cast to do this, and the result is that you can access the subtype’s members with this new reference variable.
• Upcasting: You can assign a reference variable to a supertype reference variable explicitly or implicitly. This is an inherently safe operation because the assignment restricts the access capabilities of the new variable.


Chapter 10: Implementing an Interface

• When you implement an Interface, you are fulfilling its contract
• If you implement an interface you must provide concrete overriding for all methods defined in the interface
• If you don’t provide implementation for all methods, you must mark your class Abstract
• A single class can implement many interfaces


Chapter 11: Return Types

• Overloaded methods can change return types
• Overridden methods cannot change return types (Except in case of covariant returns)
• Object reference return types can accept null as a return value
• An array is a perfectly legal return type, both to declare and to return as a value
• For methods with primitive return types, any value that can be implicitly converted to the return type can be returned
• Nothing can be returned from a method that has the void modifier
• You can use the return keyword to get out of a method early but you cannot return anything from a void method and you cannot use an empty return in a non-void method
• Methods with an object reference return type, can return a subtype
• Methods with an interface return type, can return any implementer

Chapter 12: Constructors and Instantiation

• A Constructor is always invoked when a new object of a class is created
• Each superclass in an objects inheritance tree will have a constructor called
• Every class (Even an abstract class) has atleast one constructor
• Even if you don’t write a constructor explicitly, the compiler will add a default no-arg constructor to your class
• If you write a constructor that takes arguments, the compiler will not place a no-arg constructor in your class
• Constructors must have the same name as the class (Case Sensitive)
• Constructors don’t have a return type (If you see a return type, then it’s a method and not a constructor)
• Constructors can use any access modifier including private
• The default constructor is always the no-arg constructor
• The first statement of every constructor must be a call to either this() or super()
• You cannot have both this() and super() in the same constructor
• Constructors are never inherited, so they cannot be overridden
• A constructor can be directly invoked only by another constructor
• You cannot call a constructor explicitly

Chapter 13: Statics

• Use static methods to implement behavior that will not be affected by the state of any instances
• Use static variables to hold data that is class specific. There will be only one copy of a static variable irrespective of how many instances you make of a class
• All static members of a class belong to the class and not any instance
• A static method cannot access instance variables
• Static methods cannot be overridden

Chapter 14: Coupling and Cohesion

• Coupling refers to the degree to which one class knows about another class
• Loose coupling is a desirable state of having classes that are well encapsulated, minimize references to one another
• Tight coupling is undesirable
• Cohesion refers to the degree in which a class has a single, well defined role or responsibility
• High cohesion is a desirable state and low cohesion is undesirable


Previous Chapter: Chapter 14: Coupling and Cohesion

Next Chapter: Self Test Chapters 6 to 14

Tuesday, January 25, 2011

Chapter 13: Statics

Static is one of the most important and powerful keywords in the java programming language. It can alter the behavior of variables and methods. The purpose of this chapter is to take a detailed look at this feature.

Static Variables and Methods

The static modifier has such a profound impact on the behavior of a method or variable that we’re treating it as a concept entirely separate from the other modifiers. To understand the way a static member works, we’ll look first at a reason for using one. Imagine you’ve got a utility class with a method that always runs the same way; its sole function is to return, say, a random number. It wouldn’t matter which instance of the class performed the method—it would always behave exactly the same way. In other words, the method’s behavior has no dependency on the state (instance variable values) of an object. So why, then, do you need an object when the method will never be instance-specific? Why not just ask the class itself to run the method?

Let’s imagine another scenario: Suppose you want to keep a running count of all instances instantiated from a particular class. Where do you actually keep that variable? It won’t work to keep it as an instance variable within the class whose instances you’re tracking, because the count will just be initialized back to a default value with each new instance. The answer to both the utility-method-always-runs-the-same scenario and the keep-a-running-total-of-instances scenario is to use the static modifier. Variables and methods marked static belong to the class, rather than to any particular instance. In fact, you can use a static method or variable without having any instances of that class at all. You need only have the class available to be able to invoke a static method or access a static variable. static variables, too, can be accessed without having an instance of a class. But if there are instances, a static variable of a class will be shared by all instances of that class; there is only one copy.

The following code declares and uses a static counter variable:

class Car {
static int CarCount = 0; // Declare and initialize
// static variable
public Car() {
CarCount += 1; // Modify the value in the constructor
}
public static void main (String [] args) {
new Car();
new Car();
new Car();
System.out.println("Car count is now " + CarCount);
}
}

In the preceding code, the static CarCount variable is set to zero when the Car class is first loaded by the JVM, before any Car instances are created! (By the way, you don’t actually need to initialize a static variable to zero; static variables get the same default values instance variables get.) Whenever a Car instance is created, the Car constructor runs and increments the static CarCount variable. When this code executes, three Car instances are created in main(), and the result is

Car count is now 3

Now imagine what would happen if CarCount were an instance variable (in other words, nonstatic):
class Car {
int CarCount = 0; // Declare and initialize
// instance variable
public Car() {
CarCount += 1; // Modify the value in the constructor
}
public static void main (String [] args) {
new Car();
new Car();
new Car();
System.out.println("Car count is now " + CarCount);
}
}

When this code executes, it should still create three Car instances in main(), but the result is...a compiler error! We can’t get this code to compile, let alone run.
Car.java:11: nonstatic variable CarCount cannot be referenced

from a static context
System.out.println("Car count is " + CarCount);
^
1 error

The JVM doesn’t know which Car object’s CarCount you’re trying to access. The problem is that main() is itself a static method, and thus isn’t running against any particular instance of the class, rather just on the class itself. A static method can’t access a nonstatic (instance) variable, because there is no instance! That’s not to say there aren’t instances of the class alive on the heap, but rather that even if there are, the static method doesn’t know anything about them. The same applies to instance methods; a static method can’t directly invoke a nonstatic method. Think static = class, nonstatic = instance. Making the method called by the JVM (main()) a static method means the JVM doesn’t have to create an instance of your class just to start running code.

Exam Tip:
One of the mistakes most often made by new Java programmers is attempting to access an instance variable (which means nonstatic variable) from the static main() method (which doesn’t know anything about any instances, so it can’t access the variable). The following code is an example of illegal access of a nonstatic variable from a static method:
class Bad {
int x = 3;
public static void main (String [] args) {
System.out.println("x is " + x);
}
}
Understand that this code will never compile, because you can’t access a nonstatic (instance) variable from a static method. Just think of the compiler saying, “Hey, I have no idea which Bad object’s x variable you’re trying to print!” Remember, it’s the class running the main() method, not an instance of the class.

Of course, the tricky part for the exam is that the question won’t look as obvious as the preceding code. The problem you’re being tested for—accessing a nonstatic variable from a static method—will be buried in code that might appear to be testing something else. For example, the preceding code would be more likely to appear as
class Bad {
int x = 3;
float y = 4.3f;
public static void main (String [] args) {
for (int z = x; z < ++x; z--, y = y + z) // complicated looping and branching code } } So while you’re trying to follow the logic, the real issue is that x and y can’t be used within main(), because x and y are instance, not static, variables! The same applies for accessing nonstatic methods from a static method. The rule is, a static method of a class can’t access a nonstatic (instance) method or variable of its own class.





Accessing Static Methods and Variables

Since you don’t need to have an instance in order to invoke a static method or access a static variable, then how do you invoke or use a static member? What’s the syntax? We know that with a regular old instance method, you use the dot operator on a reference to an instance:

class Car {
int CarSize = 0;
public int getCarSize() {
return CarSize;
}
public Car(int s) {
CarSize = s;
}
public static void main (String [] args) {
Car f = new Car(25);
System.out.println(f.getCarSize()); // Access instance
// method using f
}
}

In the preceding code, we instantiate a Car, assign it to the reference variable f, and then use that f reference to invoke a method on the Car instance we just created. In other words, the getCarSize() method is being invoked on a specific Car object on the heap.

But this approach (using a reference to an object) isn’t appropriate for accessing a static method, because there might not be any instances of the class at all! So, the way we access a static method (or static variable) is to use the dot operator on the class name, as opposed to using it on a reference to an instance, as follows:

class Car {
static int CarCount = 0; // Declare and initialize
// static variable
public Car() {
CarCount += 1; // Modify the value in the constructor
}
}

class TestCar {
public static void main (String [] args) {
new Car();
new Car();
new Car();
System.out.print("CarCount:"+Car.CarCount); //Access
// static variable
}
}

But just to make it really confusing, the Java language also allows you to use an object reference variable to access a static member:
Car f = new Car();
int Cars = f.CarCount; // Access static variable
// CarCount using f

In the preceding code, we instantiate a Car, assign the new Car object to the reference variable f, and then use the f reference to invoke a static method! But even though we are using a specific Car instance to access the static method, the rules haven’t changed. This is merely a syntax trick to let you use an object reference variable (but not the object it refers to) to get to a static method or variable, but the static member is still unaware of the particular instance used to invoke the static member. In the Car example, the compiler knows that the reference variable f is of type Car, and so the Car class static method is run with no awareness or concern for the Car instance at the other end of the f reference. In other words, the compiler cares only that reference variable f is declared as type Car.

Finally, remember that static methods can’t be overridden! This doesn’t mean they can’t be redefined in a subclass, but redefining and overriding isn’t the same thing. Let’s take a look at an example of a redefined (remember, not overridden), static method:

class Car {
static void drive() {
System.out.print("a ");
}
}
class Ferrari extends Car {
static void drive() { // it's a redefinition & not an override
System.out.print("d ");
}
public static void main(String [] args) {
Car [] a = {new Car(), new Ferrari(), new Car()};
for(int x = 0; x < a.length; x++) a[x].drive(); // invoke the static method } } Running this code produces the output: a a a Remember, the syntax a[x].drive() is just a shortcut (the syntax trick)...the compiler is going to substitute something like Car.drive() instead. This happens because the Array is of type Car and so the static method inside the Car class is used even though there is an instance of Ferrari in the list. Previous Chapter: Chapter 12 - Constructors and Instantiation

Next Chapter: Chapter 13 - Coupling & Cohesion
© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers