Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
58 views

Nested Classes

1. Nested classes are classes defined within other classes. There are two types: static nested classes which cannot access non-static members of the outer class, and inner classes which can. 2. Reasons for using nested classes include logically grouping related classes, increasing encapsulation, and making code more readable. 3. Local classes are classes defined within a method block and have access to final variables and parameters of the enclosing block. They are similar to inner classes in that they cannot be static.

Uploaded by

Bogdan Cocu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
58 views

Nested Classes

1. Nested classes are classes defined within other classes. There are two types: static nested classes which cannot access non-static members of the outer class, and inner classes which can. 2. Reasons for using nested classes include logically grouping related classes, increasing encapsulation, and making code more readable. 3. Local classes are classes defined within a method block and have access to final variables and parameters of the enclosing block. They are similar to inner classes in that they cannot be static.

Uploaded by

Bogdan Cocu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

1.

Nested Classes

Class within another class: it is called a nested class

O clasa imbricata este, prin definitie, o clasa membra a unei alte clase, numita
si clasa de acoperire.

class OuterClass {
...

class NestedClass {
...
}
}

Terminology: Nested classes are divided into two categories: static and non-static.
Nested classes that are declared static are called static nested classes. Non-static
nested classes are called inner classes.

class OuterClass {
...

static class StaticNestedClass {


...
}

class InnerClass {
...
}
}

A nested class is a member of its enclosing class.

Non-static nested classes (inner classes) have access to other members of


the enclosing class, even if they are declared private.

Static nested classes do not have access to other members of the enclosing
class.

As a member of the outer class, a nested class can be declared private, public,
protected, or package private. Outer classes can only be declared public or
package private.
1.1 Why Use Nested Classes?

Reasons for using nested classes include the following:

It is a way of logically grouping classes that are only used in one place: If a
class is useful to only one other class, then it is logical to embed it in that class
and keep the two together. Nesting such "helper classes" makes their package
more streamlined.

It increases encapsulation: Consider two top-level classes, A and B, where B


needs access to members of A that would otherwise be declared private. By
hiding class B within class A, A's members can be declared private and B can
access them. In addition, B itself can be hidden from the outside world.

It can lead to more readable and maintainable code: Nesting small classes
within top-level classes places the code closer to where it is used.

1.2 Static Nested Classes

As with class methods and variables, a static nested class is associated with its outer
class. And like static class methods, a static nested class cannot refer directly to
instance variables or methods defined in its enclosing class: it can use them only
through an object reference.

Static nested classes are accessed using the enclosing class name:

OuterClass.StaticNestedClass

For example, to create an object for the static nested class, use this syntax:

OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
1.3 Inner Classes

As with instance methods and variables, an inner class is associated with an instance
of its enclosing class and has direct access to that object's methods and fields. Also,
because an inner class is associated with an instance, it cannot define any static
members itself.

Objects that are instances of an inner class exist within an instance of the outer class.

Consider the following classes:

class OuterClass {
...

class InnerClass {
...
}
}

An instance of InnerClass can exist only within an instance of OuterClass and has
direct access to the methods and fields of its enclosing instance.
To instantiate an inner class, you must first instantiate the outer class. Then, create the
inner object within the outer object with this syntax:

OuterClass.InnerClass innerObject =
outerObject.new InnerClass();

There are two special kinds of inner classes: local classes and anonymous
classes

1.3.1 Shadowing

If a declaration of a type (such as a member variable or a parameter name) in a


particular scope (such as an inner class or a method definition) has the same name as
another declaration in the enclosing scope, then the declaration shadows the
declaration of the enclosing scope. You cannot refer to a shadowed declaration by its
name alone.

public class ShadowTest {

public int x = 0;

class FirstLevel {

public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " +
ShadowTest.this.x);
}
}

public static void main(String... args) {


ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}

The output:

x = 23
this.x = 1
ShadowTest.this.x = 0

This example defines three variables named x: the member variable of the class
ShadowTest, the member variable of the inner class FirstLevel, and the parameter in
the method methodInFirstLevel. The variable x defined as a parameter of the method
methodInFirstLevel shadows the variable of the inner class FirstLevel. Consequently,
when you use the variable x in the method methodInFirstLevel, it refers to the method
parameter. To refer to the member variable of the inner class FirstLevel, use the keyword
this to represent the enclosing scope:

System.out.println("this.x = " + this.x);

Refer to member variables that enclose larger scopes by the class name to which they
belong. For example, the following statement accesses the member variable of the class
ShadowTest from the method methodInFirstLevel:

System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);

1.3.2 Local and Anonymous Classes

There are two additional types of inner classes. You can declare an inner class within
the body of a method. These classes are known as local classes. You can also
declare an inner class within the body of a method without naming the class.
These classes are known as anonymous classes.
1.3.3 Modifiers

You can use the same modifiers for inner classes that you use for other members of
the outer class. For example, you can use the access specifiers private, public, and
protected to restrict access to inner classes, just as you use them to restrict access do
to other class members.

1.4 Local Classes

Local classes are classes that are defined in a block, which is a group of zero or
more statements between balanced braces. You typically find local classes defined
in the body of a method.

Topics:

- Declaring Local Classes


- Accessing Members of an Enclosing Class
- Shadowing and Local Classes
- Local Classes Are Similar To Inner Classes

1.4.1 Declaring Local Classes

You can define a local class inside any block. For example, you can define a
local class in a method body, a for loop, or an if clause.

The following example, LocalClassExample, validates two phone numbers. It


defines the local class PhoneNumber in the method validatePhoneNumber:

public class LocalClassExample {

static type memberOfEnclosingClass = ...;

public static void method1(...) {

final type localVariable =...;

class LocalClass {

...

LocalClass(...){ //constructor

...
}
public ... oneMethodOfLocalClass(...) {
...//return something (or not)
}

...

LocalClass myObject1 = new LocalClass (...);


LocalClass myObject2 = new LocalClass (...);

...
//call oneMethodOfLocalClass
myObject1.oneMethodOfLocalClass (...) ...
...

public static void main(String... args) {


method1(...);
}
}

1.4.2 Accessing Members of an Enclosing Class

A local class has access to the members of its enclosing class. In the previous
example, LocalClass (…) constructor accesses the member
LocalClassExample.memberOfEnclosingClass.
In addition, a local class has access to local variables. However, a local class
can only access local variables that are declared final. When a local class
accesses a local variable or parameter of the enclosing block, it captures that
variable or parameter. For example, the LocalClass (…) constructor can access
the local variable localVariable because it is declared final; localVariable is a
captured variable.
However, starting in Java SE 8, a local class can access local variables and
parameters of the enclosing block that are final or effectively final. A variable
or parameter whose value is never changed after it is initialized is effectively
final.

Starting in Java SE 8, if you declare the local class in a method, it can access
the method's parameters.
1.4.2.1 Shadowing and Local Classes

Declarations of a type (such as a variable) in a local class, shadow declarations


in the enclosing scope that have the same name.

1.4.3 Local Classes Are Similar To Inner Classes

Local classes are similar to inner classes because they cannot define or declare
any static members. Local classes in static methods, such as the class
LocalClass, which is defined in the static method method1, can only refer to
static members of the enclosing class. For example, if you do not define the
member variable memberOfEnclosingClass as static, then the Java compiler
generates an error similar to "non-static variable memberOfEnclosingClass
cannot be referenced from a static context."
Local classes are non-static because they have access to instance members of
the enclosing block. Consequently, they cannot contain most kinds of static
declarations.

1.5 Anonymous Classes

Anonymous classes enable you to make your code more concise. They enable you to
declare and instantiate a class at the same time. They are like local classes except
that they do not have a name. Use them if you need to use a local class only once.

Topics:

- Declaring Anonymous Classes


- Syntax of Anonymous Classes
- Accessing Local Variables of the Enclosing Scope, and Declaring and
Accessing Members of the Anonymous Class

1.5.1 Declaring Anonymous Classes

While local classes are class declarations, anonymous classes are expressions,
meaning that you define the class in another expression.
The following example, HelloWorldAnonymousClasses, uses anonymous classes in
the initialization statements of the local variables frenchGreeting and
spanishGreeting, but uses a local class for the initialization of the variable
englishGreeting:

public class HelloWorldAnonymousClasses {

interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}

public void sayHello() {

class EnglishGreeting implements HelloWorld {


String name = "world";
public void greet() {
greetSomeone("world");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hello " + name);
}
}

HelloWorld englishGreeting = new EnglishGreeting();

HelloWorld frenchGreeting = new HelloWorld() {


String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
}

HelloWorld spanishGreeting = new HelloWorld() {


String name = "mundo";
public void greet() {
greetSomeone("mundo");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hola, " + name);
}
}
englishGreeting.greet();
frenchGreeting.greetSomeone("Fred");
spanishGreeting.greet();
}

public static void main(String... args) {


HelloWorldAnonymousClasses myApp =
new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}

1.5.2 Syntax of Anonymous Classes

An anonymous class is an expression. The syntax of an anonymous class


expression is like the invocation of a constructor, except that there is a class definition
contained in a block of code.

Consider the instantiation of the frenchGreeting object:

HelloWorld frenchGreeting = new HelloWorld() {


String name = "tout le monde";

public void greet() {


greetSomeone("tout le monde");
}

public void greetSomeone(String someone) {


name = someone;
System.out.println("Salut " + name);
}
};

The anonymous class expression consists of the following:

- The new operator

- The name of an interface to implement or a class to extend. In this


example, the anonymous class is implementing the interface HelloWorld.

- Parentheses that contain the arguments to a constructor, just like a normal


class instance creation expression. Note: When you implement an interface,
there is no constructor, so you use an empty pair of parentheses, as in this
example.
A body, which is a class declaration body. More specifically, in the body,
method declarations are allowed but statements are not.

Because an anonymous class definition is an expression, it must be part of a


statement. In this example, the anonymous class expression is part of the statement
that instantiates the frenchGreeting object. (This explains why there is a semicolon
after the closing brace.)

1.5.3 Accessing Local Variables of the Enclosing Scope, and


Declaring and Accessing Members of the Anonymous Class

Like local classes, anonymous classes can capture variables; they have the same
access to local variables of the enclosing scope:

- An anonymous class has access to the members of its enclosing class.


- An anonymous class cannot access local variables in its enclosing scope
that are not declared as final or effectively final.
- Like a nested class, a declaration of a type (such as a variable) in an
anonymous class shadows any other declarations in the enclosing scope that
have the same name.

Anonymous classes also have the same restrictions as local classes with respect to
their members:

- You cannot declare static initializers or member interfaces in an


anonymous class.
- An anonymous class can have static members provided that they are
constant variables.

Note that you can declare the following in anonymous classes:

- Fields
- Extra methods (even if they do not implement any methods of the supertype)
- Instance initializers
- Local classes

However, you cannot declare constructors in an anonymous class.


1.6 Lambda Expressions

One issue with anonymous classes is that if the implementation of your anonymous
class is very simple, such as an interface that contains only one method, then the
syntax of anonymous classes may seem unwieldy and unclear. In these cases, you're
usually trying to pass functionality as an argument to another method, such as what
action should be taken when someone clicks a button. Lambda expressions enable
you to do this, to treat functionality as method argument, or code as data.

Although this is often more concise than a named class, for classes with only one
method, even an anonymous class seems a bit excessive and cumbersome. Lambda
expressions let you express instances of single-method classes more compactly.

1.7 When to Use Nested Classes, Local Classes, Anonymous Classes,


and Lambda Expressions

Nested classes enable you to logically group classes that are only used in one place,
increase the use of encapsulation, and create more readable and maintainable code.
Local classes, anonymous classes, and lambda expressions also impart these
advantages; however, they are intended to be used for more specific situations:
- Local class: Use it if you need to create more than one instance of a class,
access its constructor, or introduce a new, named type (because, for example,
you need to invoke additional methods later).
- Anonymous class: Use it if you need to declare fields or additional methods.
- Lambda expression:
- Use it if you are encapsulating a single unit of behavior that you want to
pass to other code.
- Use it if you need a simple instance of a functional interface and none of
the preceding criteria apply (for example, you do not need a constructor, a
named type, fields, or additional methods).
- Nested class: Use it if your requirements are similar to those of a local class,
you want to make the type more widely available, and you don't require access
to local variables or method parameters.
- Use a non-static nested class (or inner class) if you require access to an
enclosing instance's non-public fields and methods. Use a static nested
class if you don't require this access.
2. Enum Types

Incepand cu versiunea 1.5 a limbajului Java, exista posibilitatea de a defini


tipuri de date enumerare prin folosirea cuvantului cheie enum. Acesta
solutie simplifica manevrarea grupurilor de constante, dupa cum reiese din
urmatorul exemplu:

public class CuloriSemafor {


public static final int ROSU = -1;
public static final int GALBEN = 0;
public static final int VERDE = 1;
}
...
// Exemplu de utilizare
if (semafor.culoare = CuloriSemafor.ROSU)
semafor.culoare = CuloriSemafor.GALBEN);
...

Clasa de mai sus poate fi rescrisa astfel:

public enum CuloriSemafor { ROSU, GALBEN, VERDE };


...
// Utilizarea structurii se face la fel
...
if (semafor.culoare = CuloriSemafor.ROSU)
semafor.culoare = CuloriSemafor.GALBEN);
...

Compilatorul este responsabil cu transformarea unei astfel de structuri


intr-o clasa corespunzatoare.

An enum type is a special data type that enables for a variable to be a set of
predefined constants. The variable must be equal to one of the values that have been
predefined for it. Common examples include compass directions (values of NORTH,
SOUTH, EAST, and WEST) and the days of the week.

Because they are constants, the names of an enum type's fields are in uppercase
letters.

In the Java programming language, you define an enum type by using the enum
keyword. For example, you would specify a days-of-the-week enum type as:

public enum Day {


SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
You should use enum types any time you need to represent a fixed set of constants.
That includes natural enum types such as the planets in our solar system and data sets
where you know all possible values at compile time—for example, the choices on a
menu, command line flags, and so on.

Here is some code that shows you how to use the Day enum defined above:

public class EnumTest {


Day day;

public EnumTest(Day day) {


this.day = day;
}

public void tellItLikeItIs() {


switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;

case FRIDAY:
System.out.println("Fridays are better.");
break;

case SATURDAY: case SUNDAY:


System.out.println("Weekends are best.");
break;

default:
System.out.println("Midweek days are
so-so.");
break;
}
}

public static void main(String[] args) {


EnumTest firstDay = new EnumTest(Day.MONDAY);
firstDay.tellItLikeItIs();
EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
thirdDay.tellItLikeItIs();
EnumTest fifthDay = new EnumTest(Day.FRIDAY);
fifthDay.tellItLikeItIs();
EnumTest sixthDay = new EnumTest(Day.SATURDAY);
sixthDay.tellItLikeItIs();
EnumTest seventhDay = new EnumTest(Day.SUNDAY);
seventhDay.tellItLikeItIs();
}
}

The output is:

Mondays are bad.


Midweek days are so-so.
Fridays are better.
Weekends are best.
Weekends are best.

Java programming language enum types are much more powerful than their
counterparts in other languages. The enum declaration defines a class (called an
enum type). The enum class body can include methods and other fields. The
compiler automatically adds some special methods when it creates an enum. For
example, they have a static values method that returns an array containing all of
the values of the enum in the order they are declared. This method is commonly
used in combination with the for-each construct to iterate over the values of an
enum type. For example, this code from the Planet class example below iterates over
all the planets in the solar system.

for (Planet p : Planet.values()) {


System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}

All enums implicitly extend java.lang.Enum

In the following example, Planet is an enum type that represents the planets in the
solar system. They are defined with constant mass and radius properties.
Each enum constant is declared with values for the mass and radius parameters.
These values are passed to the constructor when the constant is created. Java
requires that the constants be defined first, prior to any fields or methods. Also, when
there are fields and methods, the list of enum constants must end with a semicolon.

Note: The constructor for an enum type must be package-private or private access.
It automatically creates the constants that are defined at the beginning of the enum
body. You cannot invoke an enum constructor yourself.

In addition to its properties and constructor, Planet has methods that allow you to
retrieve the surface gravity and weight of an object on each planet. Here is a sample
program that takes your weight on earth (in any unit) and calculates and prints your
weight on all of the planets (in the same unit):
public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6),
JUPITER (1.9e+27, 7.1492e7),
SATURN (5.688e+26, 6.0268e7),
URANUS (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7);

private final double mass; // in kilograms


private final double radius; // in meters

Planet(double mass, double radius) {


this.mass = mass;
this.radius = radius;
}

private double mass() { return mass; }


private double radius() { return radius; }

// universal gravitational constant (m3 kg-1 s-2)


public static final double G = 6.67300E-11;

double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java Planet
<earth_weight>");
System.exit(-1);
}

double earthWeight = Double.parseDouble(args[0]);


double mass = earthWeight/EARTH.surfaceGravity();

for (Planet p : Planet.values())


System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
}
If you run Planet.class from the command line with an argument of 175, you get this
output:

$ java Planet 175


Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
Your weight on EARTH is 175.000000
Your weight on MARS is 66.279007
Your weight on JUPITER is 442.847567
Your weight on SATURN is 186.552719
Your weight on URANUS is 158.397260
Your weight on NEPTUNE is 199.207413

You might also like