Creating Nested Classes Flashcards
Nested class can come in one of four flavors.
* Inner class: A non-static type defined at the member level of a class
* Static nested class: A static type defined at the member level of a class
* Local class: A class defined within a method body
* Anonymous class: A special case of a local class that does not have a name
Declaring an Inner Class
An inner class, also called a member inner class, is a non-static type defined at the member
level of a class (the same level as the methods, instance variables, and constructors). Because
they are not top-level types, they can use any of the four access levels, not just public and
package access.
Inner classes have the following properties:
Inner classes have the following properties:
* Can be declared public, protected, package, or private
* Can extend a class and implement interfaces
* Can be marked abstract or final
* Can access members of the outer class, including private members
Nested Classes Can Now Have static Members
Nested Classes Can Now Have static Members
Instantiating an Instance of an Inner Class
20: public static void main(String[] args) { 21: var home = new Home(); 22: Room room = home.new Room(); // Create the inner class instance 23: room.enter(); 24: }
lines 21 and 22. We need an instance of Home to create a Room. We can’t just call new Room() inside the static main() method, because Java won’t know which instance of Home it is associated with. Java solves this by calling new as if it were a method on the room variable.
We can shorten lines 21–23 to a single line:21: new Home().new Room().enter(); // Sorry, it looks ugly to us too!
Referencing Members of an Inner Class
Here is how to nest multiple classes and access a variable with the same name in each:
1: public class A { 2: private int x = 10; 3: class B { 4: private int x = 20; 5: class C { 6: private int x = 30; 7: public void allTheX() { 8: System.out.println(x); // 30 9: System.out.println(this.x); // 30 10: System.out.println(B.this.x); // 20 11: System.out.println(A.this.x); // 10 12: } } } 13: public static void main(String[] args) { 14: A a = new A(); 15: A.B b = a.new B(); 16: A.B.C c = b.new C(); 17: c.allTheX(); 18: }}
Inner Classes Require an Instance
can figure out why two of the three constructor calls do not compile:
public class Fox { private class Den {} public void goHome() { new Den(); } public static void visitFriend() { new Den(); // DOES NOT COMPILE } } public class Squirrel { public void visitFox() { new Den(); // DOES NOT COMPILE } }
- The first constructor call compiles because goHome() is an instance method, and therefore the call is associated with the this instance.
- The second call does not compile because it is called inside a static method. You can still call the constructor, but you have to explicitly give it a reference to a Fox instance.
- The last constructor call does not compile for two reasons. Even though it is an instance method, it is not an instance method inside the Fox class. Adding a Fox reference would not fix the problem entirely, though. Den is private and not accessible in the Squirrel class.
Creating a static Nested Class
A static nested class is a static type defined at the member level. Unlike an inner class, a static nested class can be instantiated without an instance of the enclosing class. The trade-off, though, is that it can’t access instance variables or methods declared in the outer class. In other words, it is like a top-level class except for the following:
* The nesting creates a namespace because the enclosing class name must be used to refer to it.
* It can additionally be marked private or protected.
* The enclosing class can refer to the fields and methods of the static nested class.
static Nested Class example:
1: public class Park { 2: static class Ride { 3: private int price = 6; 4: } 5: public static void main(String[] args) { 6: var ride = new Ride(); 7: System.out.println(ride.price); 8: } }
Line 6 instantiates the nested class. Since the class is static, you do not need an instance of
Park to use it. You are allowed to access private instance variables, as shown on line 7.
Writing a Local Class
A local class is a nested class defined within a method. Like local variables, a local class declaration does not exist until the method is invoked, and it goes out of scope when the method returns. This means you can create instances only from within the method. Those instances can still be returned from the method. This is just how local variables work.
Local classes have the following properties:
Local classes have the following properties:
- They do not have an access modifier.
- They can be declared final or abstract.
- They have access to all fields and methods of the enclosing class (when defined in an instance method).
- They can access final and effectively final local variables.
Example :
public void processData() { final int length = 5; int width = 10; int height = 2; class VolumeCalculator { public int multiply() { return length * width * height; // DOES NOT COMPILE } } width = 2; }
The length and height variables are final and effectively final, respectively, so neither causes a compilation issue. On the other hand, the width variable is reassigned during the method, so it cannot be effectively final. For this reason, the local class declaration does not compile.
Defining an Anonymous Class
An anonymous class is a specialized form of a local class that does not have a name. It is
declared and instantiated all in one statement using the new keyword, a type name with
parentheses, and a set of braces {}. Anonymous classes must extend an existing class or
implement an existing interface. They are useful when you have a short implementation that will
not be used anywhere else. Here’s an example:
1: public class ZooGiftShop {
2: abstract class SaleTodayOnly {
3: abstract int dollarsOff();
4: }
5: public int admission(int basePrice) {
6: SaleTodayOnly sale = new SaleTodayOnly() {
7: int dollarsOff() { return 3; }
8: }; // Don’t forget the semicolon!
9: return basePrice - sale.dollarsOff();
10: } }
But what if we want to both implement an interface and extend a class? You can’t do so with
an anonymous class unless the class to extend is java.lang.Object. The Object class
doesn’t count in the rule. Remember that an anonymous class is just an unnamed local class.
TABLE 7.4 Modifiers in nested classes
TABLE 7.5 Nested class access rules