I've just started working through the Java tutorials again and I decided to spend some time playing with nested classes.
The working copy I've made is a Bicycle class which could have zero or more Rider class instances within it. From within an instance of Bicycle, I'd like to be able to work with instances of Riders.
In the example below, my Bicycle has an ArrayList which holds its Riders, but I'd like to avoid having to maintain this list if possible.
My question is this. Is there another way to reference instances of Rider from Bicycle, or do I have to maintain my own list?
//Outer Class contains zero or more Inner Classes
public class Bicycle {
//ArrayList of Inner Class instances
private List<Rider> Riders = new ArrayList<Rider>();
class Rider {
private String riderName;
protected Rider(String newRiderName) {
this.riderName = newRiderName;
}
protected String GetRiderName(){
return riderName;
}
}
//When creating an Outer Class, we can instantiate zero or more Inner Classes, by name
public Bicycle(String... startingRiderName) {
//Loop through all Inner Class instance names and create an Inner Class for each
for (String newRiderName : startingRiderName) {
Riders.add(new Rider(newRiderName));
}
}
//Public method to return an array of Inner Class instance names
public String[] GetRiderNames() {
String[] riderNames = new String[Riders.size()];
// Just in case we mess up and ask the ArrayList for an out of bounds index
try {
for (int riderIndex = 0; riderIndex < Riders.size(); riderIndex++) {
riderNames[riderIndex] = Riders.get(riderIndex).GetRiderName();
}
return riderNames;
} catch (IndexOutOfBoundsException e) {
return null;
}
}
}
A list has to be maintained somewhere, otherwise those inner class instances will be garbage-collected. Whether that's in an array that is a member of Bicycle or in some external data structure is a design decision, but there's no automatic list kept by Java of inner class instances.
Yes you will need to maintain a list.
Also, a Rider doesn't seem like it should be an inner class of Bicycle. By making Rider an private inner class you are saying that it is only ever useful to Bicycle. Conceptually an inner class is more for some sub-part of Bicycle that performs an internal operation on or holds internal data that composes and is specific to that bicycle. I could imagine a FlatTyreEventHandler being an inner class, but I don't think of the Rider as part of the internal fabric or operation of a Bicycle.
Now, having a Rider and internal class of Bicycle might work in your instance, but bear in mind that anything the outside world wants to know about a rider will have to go through Bicycle, so you will have to keep adding methods such as GetRiderAge(), GetRiderRoutePreference(). These methods are specific to a rider and have nothing to do with a Bicycle. If you find yourself doing this, then Rider is not really an internal hidden class, but instead the methods on Bicycle are just passthroughs to Rider methods and having it as an internal class serves little purpose. Also, the Bicycle has lost its single purpose (of being a Bicycle) and is bloated out with a Rider interface.
So, I would probably make Rider a stand-alone class and then Bicycle has a list of Riders. Alternatively, you can have a separate class which is BicycleRiders and this class can hold a map from bicycles to riders.
Related
Below is a piece of code which provides an example of using inner class in Java.
I would like to know how the inner class instance iterator is created and linked to the arrayOfInts array.
DataStructureIterator iterator = this.new EvenIterator();
I understand that the 'ds' instance is created by the constructor of DataStructure class, but the iterator instance is of DataStructureIterator type. It seems not quite reasonable that a DataStructureIterator instance can be constructed by a constructor of another class.
Full code here:
public class DataStructure {
// Create an array
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
public DataStructure() {
// fill the array with ascending integer values
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
public void printEven() {
// Print out values of even indices of the array
DataStructureIterator iterator = this.new EvenIterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
interface DataStructureIterator extends java.util.Iterator<Integer> { }
// Inner class implements the DataStructureIterator interface,
// which extends the Iterator<Integer> interface
private class EvenIterator implements DataStructureIterator {
// Start stepping through the array from the beginning
private int nextIndex = 0;
public boolean hasNext() {
// Check if the current element is the last in the array
return (nextIndex <= SIZE - 1);
}
public Integer next() {
// Record a value of an even index of the array
Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);
// Get the next even element
nextIndex += 2;
return retValue;
}
}
public static void main(String s[]) {
// Fill the array with integer values and print out only
// values of even indices
DataStructure ds = new DataStructure();
ds.printEven();
}
}
This is a question from the Oracle's Java documents, here is the source: https://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html
From your Q:
It seems not quite reasonable that a DataStructureIterator instance can be constructed by a constructor of another class.
In your code, the instance of the DataStructureIterator is actually not created by the DataStructure constructor. It is created whenever the DataStructure instance method printEven is called:
public void printEven() {
// Print out values of even indices of the array
DataStructureIterator iterator = this.new EvenIterator();
// Omitted for brevity
}
But it could also be created in the constructor as a field or set with a default value e.g.:
public class DataStructure {
private DataStructureIterator iterator = new EvenIterator();
// Omitted for brevity
}
If your inner class (EventIterator) was public, it could also be created "outside" of DataStructure:
// In some other Java class
DataStructure ds = new DataStructure();
DataStructure.EventIterator iterator = ds.new EventIterator();
The key thing is that outer class (DataStructure) instance is created first.
As the docs note:
To instantiate an inner class, you must first instantiate the outer class
This is because the instance of an inner class is always tied to the outer/parent class.
From your Q:
I would like to know how the inner class instance iterator is created and linked to the arrayOfInts array.
The key thing is that an instance of a inner non-static class is that always has access to the parent instance's methods/fields.
As the docs also state (emphasis added):
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.
As such, the instance of the DataStructureIterator can access the DataStructure field arrayOfInts.
But note that if you created a separate DataStructure instance e.g. ds2, then the DataStructureIterator instance within ds2 will have access to ds2.arrayOfInts but it won't have access to the ds.arrayOfInts. In your code the values of arrayOfInts will be the same but the instances are actually different (try allowing arrayOfInts to be set via the DataStructure constructor).
If DataStructureIterator was defined as a nested static class, then it won't automatically have access to arrayOfInts and it would need arrayOfInts passed in as an arg to its constructor or to its method.
You can think of inner non-static classes as a logical grouping of code for the parent (DataStructure class) and the docs linked above outline good reasons when to use them. But in general don't use them unless you know what you're doing.
An inner class is instantiated the same as any other class is, just the scope of the class (and thus its instances) is different.
So yes, your inner class instance is created by a call inside the outer class method (not the constructor in the case of your example, but the printEvent method).
I don't know what you mean with the "ds instance is created by the constructor of DataStructure". If you mean that the class is initialised by the constructor, no.
A non-static inner class is best thought of as follows (because.. they really are exactly like this, at the class level):
They have a secret (invisible) final field of the outer type's type.
All constructors, even the default (empty) one have a secret additional parameter of the same type, and they all have an additional extra syntax sugar line at the top, in the vein of this.theFinalFieldIMentionedEarlier = thatParameter;.
Calling new InnerClass() will silently pass this along as that parameter.
If no this that fits is available, you must pass the parameter yourself. However, instead of writing new InnerClass(instanceOfOuter), you write instanceOfOuter.new InnerClass() instead. The effect is identical, and at the class level, there is no difference.
Generics is rather wonky; if the outer has it, oof.
As a consequence:
Do not use non-static inner classes unless you really know what you are doing and you understand and want this weird field. If you don't, or if you feel this is confusing (and it is; most java programmers do not know this is how it works), you might want to consider making your inner class static, and making that field explicit - i.e. handrolling this functionality. It's not particularly complicated (requires 1 field, 1 constructor parameter, and 1 this.outer = outer; statement in the constructor, not exactly a boatload of boilerplate), and clears up rather a lot.
So how does it work - exactly as if it had that field. Because, that's exactly what javac does. inner classes mostly don't exist at the class level, they just become top level classes with funky names (Outer$Inner), a boatload of synthetic methods to bridge private methods together. In newer JVMs, there's the nestmates system that avoids some of those bridges, but they're still individual top-level classes after javac is done with it.
In other words, this:
class Outer {
class Inner {
public Inner(int example) {}
}
void test() {
new Inner();
}
}
is virtually identical to:
class Outer {
static class Inner {
private final Outer outer;
public Inner(Outer outer, int example) {
this.outer = outer;
}
}
void test() {
new Inner(this);
}
}
I have an abstract class which lays out what each of its subclasses should implement. Most methods will have different implementations for each subclass, but some will be the same for all. I want the methods that will be the same to be to be defined in the abstract class, so that I'm not pasting the same method into several different classes. However, when I call that method on an instance of the abstract's subclass, I receive a nullpointer because, I imagine, the method implemented in the abstract class is referencing the abstract's field, not the instance's field.
Can someone point out where the flaw is?
For example:
abstract class ControlView {
String[] controls;
abstract void render();
void release() {
for (int i = 0; i <= controls.length; i++) {
//Release the controls
}
}
}
class StartingControls extends ControlView{
String[] controls;
Button uiDrawButton;
Button uiLoadButton;
StartingControls() {
this.controls = new String[2];
uiDrawButton = new Button();
this.controls[0] = uiDrawButton;
uiLoadButton = new Button();
this.controls[1] = uiLoadButton;
}
public void render() {
//Unique Render implementation
}
}
When I call
instanceOfStartingControls.release();
I obviously want to iterate over the two strings that I put into instanceOfStartingControls' controls field when it was constructed. I do not want to iterate over the non-initialized array that is apparently living in the abstract.
Is it some combination of access modifiers or static methods that is keeping this from working as it seems it should, or am I missing some crucial bit of knowledge on abstract classes? This feels like a basic question, but I'm having a hard time putting it to words, so I've not been satisfied with any results from my searches.
There are two arrays called controls. The one in the derived class is obscuring the one in the base class, thus the base instance never gets set non-null.
Delete the declaration from the derived class.
This issue is not related to the base being abstract. If you use the same field name in a derived class as is used in a base class, the base instance will be obscured.
I'am a newbie in JAVA and this came across this word called.
"A class i.e. created inside a method is called local inner class in java. If you want to invoke the methods of local inner class, you must instantiate this class inside the method".
The word in bold.
Can anyone please help me out with this one.I know it's embarrassing and i should've researched more but I just cannot understand.
Thanks.
First of all Declaring mean:
ClassName obj;
Simple meaning of instantiate is creating an object from class.
ClassName obj = new ClassName();
What is a object?
An instance of a class. From one class we can create many instances.
They are the basic runtime entities in in our program.
They may also represent user-defined data types such as lists and
vectors.
Any programming problem is analyzed in terms of objects and nature of
communication between them.
As a example:
//Define a reference(a variable) which can hold a `Person` obect.
Person p;
//Create a Person object(instantiate).
//new - use to allocate memory space for the new object
p = new Person();
What is a nested class?
A class that defined inside a class is called nested class. There 2 categories of nested classes.
inner classes
local classes
annonymous classes
Inner class:
Inner class can only be accessed by the outer class. Not by any other
class.
Inner class is a member of outer class.
Outer class can access inner class without importing.
Inner class can access any attribute or a method belong to outer
directly.
Outer class cannot access directly to a inner class.
Example for a inner class:
class Outer{
int i = 10;
void main(){
//instantiate inner class.
Inner in = new Inner();
in.show();
}
class Inner{
void show(){
System.out.print(i);
}
}
}
What is a local class?
Which are classes that are defined in a block.
Example:
public class{
int i = 10;
public main(){
class A{
void show(){
System.out.println(i);
}
}
//inside the method instantiate local class.
A obj = new obj();
obj.show();
}
//outside the main() -block(method)
//inside another method instantiate local class.
public test(){
A obj = new A();
obj.show();
}
}
To instantiate a class means to create an instance of the class. In other words, if you have a class like this:
public class Dog {
public void bark() {
System.out.println("woof");
}
}
You would instantiate it like this:
Dog myDog = new Dog();
Instantiating is when you use the new keyword to actually create an object of your class.
Instantiate == create an instance == create an object of a class.
Instantiate is creating an instance of a class. I reckon this is not helpful without knowing what an instance is.
Let's say you have a class definition like:
public class Person
{
private String name;
public Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
You make an instance of this class my calling its constructor and using the keyword new:
Person p = new Person("Hugh Laurie");
An instance of a class is a place in memory that contains the state (e.g., Person::name) of a given object which used as a template a class definition.
I want to further expand upon:
If you want to invoke the methods of local inner class you must instantiate this class
What this means is that, you need to have instantiated that class in order to use the above's example getName() method. After all, it is trying to access the state (name) of a given object in memory; without that object, there is no state.
Instantiate in Java means to call a constructor of a Class which creates an an instance or object, of the type of that Class. Instantiation allocates the initial memory for the object and returns a reference. An instance is required by non-static methods as they may operate on the non-static fields created by the constructor.
Static methods don't need an instance and should not be stateful, i.e. should not rely on changing data. They are essentially free functions that are associated with the type and not a particular instance. When you want to work with changing data, encapsulating that data as member fields that are operated on by instance methods is the way to go.
For example, a Car class might have static numbeOfWheels() that always returns 4, but an instance numberOfFlatTires() that might return 0-4 depending on the state of that particular Car.
Inner classes are no different and the only difference between a static and non-static inner class is that the non-static can use the parent instance's members. This can be used to reduce complexity. You might have a looping operation that has a common parameter for the list and an individual parameter for the items. You could use a non-static inner class to encapsulate the operations on the item while referring to the common parameter in the parent class.
Enums are special in that each value is a single instance of a single type that all extend from a common abstract base class defined in the Enum class body. The Enum value is instantiated the first time it's used, but there will only ever be one instance per value.
when you create an instance of a class or simply called as an object
for ex: Bike abc = new Bike();
as soon as you create this object using the new keyword, a new block of memory is created and object "abc" will now be pointing to that new block of memory, this is called as instantiation in java.
create an instance of the class by using "new" word
for example Car car = new Car();
I have been reading through some documentation on inner classes, and am currently reading my textbook, where I have found some good knowledge on using Inner classes. For starters I would like to consider the following example and just make sure I am understand things correctly. For reference I have read the follwing Inner Classes Documentation and have read a couple of SO questions. Hopefully someone can guide me through the following.
import java.util.ArrayList;
public class Gearbox {
private ArrayList<Gear> gears;
private int maxGears;
private int currentGear;
public Gearbox(int maxGears)
{
this.maxGears = maxGears;
this.gears = new ArrayList<Gear>();
Gear neutral = new Gear(0,0.0);
this.gears.add(neutral);
}
public class Gear
{
private int gearNumber;
private double ratio;
public Gear(int gearNumber,double ratio)
{
this.gearNumber = gearNumber;
this.ratio = ratio;
}
public double driveSpeed(int revs){
return revs * ratio;
}
}
}
In the main.java
public class Main {
public static void main(String [] args)
{
Gearbox ford = new Gearbox(6);
Gearbox.Gear first = ford.new Gear(1,20);
System.out.println(first.driveSpeed(10));
}
}
What I am kind of confused about is the notation to actually use some stuff from the nested class. For example
Gearbox ford = new Gearbox(6);
Here we make a ford object belonging to the class of Gearbox, which passes in a value of 6 to maxGears.
Next we have Gearbox.Gear first = ford.new Gear(1,20);, Here is where I am kind of confused on what is really going on. Does the .Gear let the compiler know that Gear is an inner class within Gearbox? If so, why is the next statement ford.new Gear(1,12.3)?
Wouldn't something like Gearbox.Gear first = new ford.Gear(1,12.3); make more sense?
Next we have
Gearbox.Gear first = ford.new Gear(1,20);
Here is where I am kind of confused on what is really going on. Does the .Gear let the compiler know that Gear is an inner class within Gearbox?
Yes ... sort of. Actually, it is saying "I am talking about the Gear class that is declared in Gearbox. It is not necessarily an inner class: it could be a nested class.
If so, why is the next statement ford.new Gear(1,12.3) ?
An instance of an inner class must be created in the context of an instance of its enclosing outer class. The ford.new Gear(...) is saying create the new Gear instance in the context of the Gearbox instance that ford refers to.
(If that still doesn't make sense, reread the above paying special attention to usage of the the word "instance". An instance of a class is an object .....)
As #Thilo points out, making Gear an inner class (rather than a nested class) here does not really achieve anything. It would probably be better to a redeclare Gear as
public static class Gear ...
and then you would not need to qualify the new with an instance of the Gearbox class.
Your inner class is not static, which means it belongs to a concrete instance.
Gearbox.Gear first = new ford.Gear(1,12.3);
Means that you create a Gear for instance ford.
Here you can read some more about inner class and about difference of static and non-static inner classes.
A simple question on Java class
I want to create my class with my own add method which adds an object of a different class.
For eg if my class name is Weapon, I want to create an add method like void add(Gun gun) (Gun being one of my other classes for example)
This would be just like creating your own collection maybe??? if I am not wrong? Like list.add() method, I want to implement my own add method for the Weapon class
So when I instantiate an object of my weapon class, it should be like
Weapon w = new Weapon(new Gun( ... .. constructor parameters) )
Also I would like to have variants of my add methods. Like a different add method with different parameters like void add(Weapon weapon) ( creating an method to add your own class object )
So I am not sure if this is similar to implementing a collection?? And if it is how do I achieve it? Do I have to extend another class for this?
Apologies if my question confused anyone! :)
List<Object> weapons = new ArrayList<Object>();
weapons.add(new Sword());
weapons.add(new Gun());
try this.
You don't necessarily have to do a new Gun() when you instantiate. You can just do the following:
class Weapon
{
private Gun gun;
public Weapon()
{
gun = new Gun(); //etc.
}
//add more methods here. You can use gun.function() to invoke any functions
}
As for using a Weapon object, just declare public methods in the Weapon class and then invoke them in your methods.
For example, the add() function:
class Weapon
{
...
public int val() { return 0; } // don't know, some random method.
}
Then on a different file:
int add(Weapon w)
{
return Weapon.val() + 1111; //perform something here
}
I hope this answers your questions, it was a little bit unclear :|. Comment if you need more help.
Your question is a bit unclear to me, but I'll try my best.
If you want to have a List of Weapon, then you need to use inheritance. In your example, A Gun is-a Weapon. Therefore, you can do class Gun extends Weapon. Then, let's say you're using an ArrayList, you would instantiate it like:
List<Weapon> weapons = new ArrayList<Weapon>();
You can now call add with a Gun, or any other sub-class of Weapon like so:
weapons.add(new Gun()); //or
weapons.add(new Cannon());
If you actually need to add a Gun to a Weapon (Which doesn't really make sense...), you can use composition. See Shahar's answer for a more detailed explanation of this behavior.
Just to clarify, no matter what, I'm pretty sure creating a new Collection is not what you want to do here.
These are a lot of questions :-) let's enumerate them
creating a method called add() into an object makes this object a Collection? No. To be a Collection, a class must implement the interface java.util.Collection or implement any one of the subinterfaces or extend any of the subclasses that implement this interface. A list of them is available in the Collection javadoc - http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
if I want to add an object into another, it must be via the constructor? e.g. new Weapon(new Gun())? Not necessarily. You can just create a Weapon w = new Weapon() and then add the Gun reference via a method such as w.setGun(new Gun()). Anyway, any constructor with one or more parameters must be declared explicitly in your class. Only the non-parameter constructor is available by default.
Now, let's suppose that you want to store a class Gun that is a subclass of a class Weapon. Then you first need to define the hierarchy between them, for example
class Weapon{
}
class WeaponWithBlade extends Weapon{
}
class Sword extends WeaponWithBlade{
}
class Knife extends WeaponWithBlade{
}
class Gun extends Weapon{
}
and then you want to store all these weapons in a Weapon collection.
since all of them are subclasses of the Weapon class, it's valid to do something like this
java.util.List<Weapon> weapons = new java.util.ArrayList<>();
weapons.add(new Sword());
weapons.add(new Gun());
notice that both List and ArrayList are collections (List is an interface and ArrayList is a concrete class that implements the List interface), parametrized to be collections of Weapons.
I hope this can help you.