There are four types or flavors of nested classes in Java:
- Static nested class
- Inner class
- Local inner class
- Anonymous inner class
Static Nested Classes (or Interfaces)
You can define a class (or interface) as a static member inside another class (or interface). Since the outer type can be a class or an interface and the inner ones can also be a class or interface, there are four combinations.
class Outer {
// an outer class has a static nested class
static class Inner {}
}
interface Outer {
// an outer interface has a static nested class
static class Inner {}
}
class Outer {
// an outer class has a static nested interface
static interface Inner {}
}
interface Outer {
// an outer interface has a static nested interface
static interface Inner {}
}
You don’t have to explicitly use the static keyword with a nested interface, since it is implicitly static.
Example 1 - In constants
public enum ErrorCode {
NONE("", null, false),
ERRORCODE1("ERRORCODE1", FS.Strategy1, false),
ERRORCODE2("ERRORCODE2", null, false);
private final String strategy;
private final String errorcode;
ErrorCode(String errorcode, String strategy) {
this.code = code;
this.strategy = strategy;
}
public final String getCode() {
return code;
}
public final FulfillmentStrategy getStrategy() {
if(strategy == null) {
return FS.NoLicenseStrategy;
}
return (FulfillmentStrategy)ContextSingleton.getFactory().getBean(strategy);
}
private static class FS {
private static final FulfillmentStrategy NoLicenseStrategy = new NoLicenseFulfillmentStrategy();
private static final String Strategy_1 = "Strategy1";
private static final String Strategy_2 = "Strategy2";
private static final String Strategy_3 = "Strategy3";
}
}
Example 2 - In DTO and Builder Pattern
public class CustomerData {
private String name;
private String adddress;
private Long customerId;
private CustomerData( Builder builder){
setName(builder.name);
setAdddress(builder.adddress);
setCustomerId(builder.customerId);
}
public String getName() {
return name;
}
public String getAdddress() {
return adddress;
}
public Long setCustomerId() {
return customerId;
}
public static class Builder {
private String name;
private String adddress;
private Long customerId;
public Builder name(String name){
this.name = name;
return this;
}
public Builder adddress(String adddress){
this.adddress = adddress;
return this;
}
public Builder customerId(Long customerId){
this.customerId = customerId;
return this;
}
public CustomerData build(){
return new CustomerData(this);
}
}
}
// using the builder
private CustomerData createCustomerData(final ResultSet rs) throws SQLException {
CustomerData.Builder builder = new CustomerData.Builder();
builder.name(rs.getString(1)).
address(rs.getString(2)).
custmerId(rs.getLong(3));
return builder.build();
}
Inner Classes
You can define a class (or an interface) as a non-static member inside another class.
class Outer { // an outer class has an inner class
class Inner {}
}
class Outer { // an outer class has an inner interface
interface Inner {}
}
Let’s create a Point class to implement the center of a Circle. Since you want to associate each Circle with a center Point, it is a good idea to make Point an inner class of Circle
public class Circle {
// define Point as an inner class within Circle class
class Point {
private int xPos;
private int yPos;
// you can provide constructor for an inner class like this
public Point(int x, int y) {
xPos = x;
yPos = y;
}
// the inner class is like any other class - you can override methods here
public String toString() {
return "(" + xPos + "," + yPos + ")";
}
}
// make use of the inner class for declaring a field
private Point center;
private int radius;
public Circle(int x, int y, int r) {
// note how to make use of the inner class to instantiate it
center = this.new Point(x, y);
radius = r;
}
public String toString() {
return "mid point = " + center + " and radius = " + radius;
}
public static void main(String []s) {
System.out.println(new Circle(10, 10, 20));
}
// other methods such as area are elided
}
you have defined Point as a private member of Circle here
center = this.new Point(x, y);
You need to prefix the object reference of the outer class to create an instance of the inner class. In this case, it is a this reference, so you are prefixing it with this before the new operator
You can access members of an outer class within an inner class without creating an instance; but this is not the case with an outer class. You need to create an instance of inner class in order to access the members.
Local Inner Classes
A local inner class is defined in a code block (say, in a method, constructor, or initialization block).
local inner classes are not members of an outer class; they are just local to the method or code in which they are defined.
Here is an example of the general syntax of a local class:
class SomeClass {
void someFunction() {
class Local { }
}
}
Local is a class defined within someFunction. It is not available outside of someFunction, not even to the members of the SomeClass. Since you cannot declare a local variable static, you also cannot declare a local class static.
class StatusReporter {
// important to note that the argument "color" is declared final
// otherwise, the local inner class DescriptiveColor will not be able to use it!!
static Shape.Color getDesciptiveColor(final Shape.Color color) {
// local class DescriptiveColor that extends Shape.Color class
class DescriptiveColor extends Shape.Color {
public String toString() {
return "You selected a color with RGB values " + color;
}
}
return new DescriptiveColor();
}
public static void main(String []args) {
Shape.Color descriptiveColor =
StatusReporter.getDesciptiveColor(new Shape.Color(0, 0, 0));
System.out.println(descriptiveColor);
}
}
You can pass only final variables to a local inner class.
Anonymous Inner Classes
anonymous inner class does not have a name. The declaration of the class automatically derives from the instance-creation expression. They are also referred to simply as anonymous classes.
Here is an example just to address the syntax of a local class:
class SomeClass {
void someFunction() {
new Object() { };
}
}
You can simplify the code by converting the local class into an anonymous class
class StatusReporter {
static Shape.Color getDesciptiveColor(final Shape.Color color) {
// note the use of anonymous inner classes here -- specifically, there is no name
// for the class and we construct and use the class "on the fly" in the return
// statement!
return new Shape.Color() {
public String toString() {
return "You selected a color with RGB values " + color;
}
};
}
public static void main(String []args) {
Shape.Color descriptiveColor =
StatusReporter.getDesciptiveColor(new Shape.Color(0, 0, 0));
System.out.println(descriptiveColor);
}
}
• Anonymous classes are defined in the new expression itself, so you cannot create multiple objects of an anonymous class.
• You cannot explicitly extend a class or explicitly implement interfaces when defining an anonymous class.
• You cannot explicitly extend a class or explicitly implement interfaces when defining an anonymous class.
No comments:
Post a Comment