Java - Why static is important in this case - java

I've two questions that relates to the following code (Linked Bag):
public class LinkedBag<Item> implements Iterable<Item> {
private Node first; // beginning of bag
private int N; // number of elements in bag
private class Node {
private Item item;
private Node next;
}
and this one
public class Bag<Item> implements Iterable<Item> {
private Node<Item> first; // beginning of bag
private int N; // number of elements in bag
// helper linked list class
private static class Node<Item> {
private Item item;
private Node<Item> next;
}
What's the difference between Node<Item> and Node here? both implementations are generic, so how Node and Node<Item>differ here ?
What's the meaning of static in the second version, why is it crucial ? ( doesn't compile without static).
Thanks !

If your nested class is not static, then it's an inner class, and the enclosing class's type parameter Item is in scope. However, if your nested class is static, then the enclosing class's type parameter is not in scope, because that type parameter has to do with an instance of the enclosing class, which is not relevant for a static nested class.
Here, the static class Node declares its own Item type parameter. It could have declared any other name and it would have been equivalent. You should not receive a compiler error using Node<Item> in your second case (with the static class); that is legal.

What's the difference between Node<Item> and Node here?
Adding a generic parameter is necessary because Java prohibits static inner classes of generic types from referencing type parameters of their outer types.
What's the meaning of static in the second version?
static means that Node instances do not get a reference to their parent class, and can be created outside of its context if it is necessary. It is not exactly "crucial", but shrinks your node by a third (two references vs. three references), which is an advantage.

If a nested class is not static (called an inner class), it means that every instance belongs to an instance of the enclosing class. Therefore in the first example, a Node instance belongs to a LinkedBag<Item>, so it already has a generic type Item (from LinkedBag<Item>).
An instance of a static nested class does not belong to an instance of the enclosing type, so it does not get the generic type parameter from an enclosing instance - you need to give it its own generic parameter.
Looking at the source code for the various Collection and Map implementations in the standard Java collections framework, you can see that both approaches to Node classes (static and non-static) are commonly used.

Related

Inner Class in Java creates reference to self as attribute

I have a simple class in my Java program that models a BST of generic types. In this class there is an inner class that models the nodes of the BST.
public class Tree<T extends Comparable<T>> {
private class TreeElement {
private T element;
private TreeElement left = null;
private TreeElement right = null;
public TreeElement(T element){
this.element=element;
}
}
public TreeElement root=null;
public void insert(T element) {
if (root==null){
root=new TreeElement(element);
return;
}
//More Code here that is not relevant
}
}
Tree tree = new Tree();
tree.insert(5);
After inserting an Integer-Element into my Tree, I get the following Tree object (from debugger):
tree = {Tree#1147}
root = {Tree$TreeElement#1157}
element = {Integer#1155} 5
left = null
right = null
this$0 = {Tree#1147}
root = {Tree$TreeElement#1157}
element = {Integer#1155} 5
left = null
right = null
this$0 = {Tree#1147}
This would go on for as long as I keep clicking, so its an recursive reference to itself.
My questions are:
Where does the this$0-reference to itself come from?
How do I avoid it?
From my understanding, my Tree Object should only have a root Object that has 3 Attributes (element, left, right).
Where does the this$0-reference to itself come from?
It comes from the class being non-static.
How do I avoid it?
This reference is what enables your code to reference tree.this. You cannot get rid of it, unless you are willing to supply tree.this to the method that uses it through some alternative way (e.g. by passing it as a parameter all the time).
Once you figure out how to not reference tree.this from your code, making TreeElement class static would get rid of the hidden reference to Tree.
It's not a 'recursive reference to self'. It's a non-recursive reference to the instance of the outer class via which the inner-class object was created. You can get rid of it by changing the inner class to static, but this will cause other code problems if you access members of the outer class from within it. Such as tree.this.
This is not a problem, so you don't need to solve it.

Why do I need to declare a private class static to avoid the "Generic Array Creation" error?

The following code snippet throws the error: " Generic array creation" despite not having any generic instances within the Node class. However, if i declare the private class Node as static , the error goes away. Why is the static keyword important here?
public class SeperateChainingST<Key, Value>{
private int M =97;
private Node[] st = new Node[M];
private class Node{
Object key;
Object val;
Node next;
}
}
Node is a non-static nested class. That means it is an inner class, and it is within the scope of the type parameters Key and Value of its outer class.
When you simply write the type Node without any explicitly qualification inside SeperateChainingST, it is implicitly qualified as SeperateChainingST<Key, Value>.Node. This is a parameterized type (it has the type parameters Key and Value), even though you do not "see" them when writing Node.
As you know, you cannot use array creation expression with a component type that is a parameterized type:
new HashMap<Key, Value>[5]
So you cannot do
new Node[5] // which is equivalent to
new SeperateChainingST<Key, Value>.Node[5]
But, as you may also know, array creation expression can be used with a component type that is a raw type, or a type that is parameterized with all wildcards:
new HashMap[5]
new HashMap<?,?>[5]
We can do it similarly here, except how do you get the raw type of the inner class Node? It is not just Node, as we have found. Instead, you must explicitly qualify it with the raw type of the outer class:
new SeperateChainingST.Node[5]
or with the all-wildcards way:
new SeperateChainingST<?,?>.Node[5]

Bloch Effective Java - favor static classes over nonstatic - how many instances?

I want to know how many instances of a static member class can be created by the enclosing class. I assume one only, but then the following extract from Bloch doesn't make sense to me.
Quoting Joshua Bloch's Effective Java - Item 22*: Favor static member classes over nonstatic.
A common use of private static member classes is to represent components of the object represented by their enclosing class. For example, consider a Map instance, which associates keys with values. Many Map implementations have an internal Entry object for each key-value pair in the map. While each entry is associated with a map, the methods on an entry (getKey, getValue and setValue) do not need access to the map. Therefore, it would be wasteful to use a nonstatic member class to represent entries: a private static member class is best. If you accidentally omit the static modifier in the entry declaration, the map will still work, but each entry will contain a superfluous reference to the map, which wastes space and time.
He states that the map creates an Entry object for each key-value pair in the map, i.e. multiple instances of the static member class.
So my assumption is wrong! That means my understanding of static member classes is wrong. Everyone knows how a static member variable behaves, the classic static final string for instance - there is only one instance of the object.
Does this mean then that a static member class is not actually instantiated when the enclosing object is instantiated?
Well in that case, what's the point of Map using a static member class for Entry? Why not just use an interface on the API? Every other Collections class could then just provide it's own implementation.
[*] Just realised that it's item 18 in the PDF version of the book I have
This is a common misinterpretation of the static keyword.
When you use static with a variable it means there will be only one of these for all objects of this class or something like that.
static Object thereWillBeOnlyOne = new Object();
However, in the context of inner classes it means something completely different. A static inner class has no connection with an object of the enclosing class while a non-static inner class does.
A static inner class:
public class TrieMap<K extends CharSequence, V> extends AbstractMap<K, V> implements Map<K, V> {
private static class Entry<K extends CharSequence, V> implements Map.Entry<K, V> {
The Map.Entry class used by my TrieMap class does not need to refer to the object that created it so it can be made static to save the unnecessary reference.
A non-static inner class:
public final class StringWalker implements Iterable<Character> {
// The iteree
private final String s;
// Where to get the first character from.
private final int start;
// What to add to i (usually +/- 1).
private final int step;
// What should i be when we stop.
private final int stop;
// The Character iterator.
private final class CharacterIterator implements Iterator<Character> {
// Where I am.
private int i;
// The next character.
private Character next = null;
CharacterIterator() {
// Start at the start.
i = start;
}
public boolean hasNext() {
if (next == null) {
if (step > 0 ? i < stop : i > stop) {
next = s.charAt(i);
i += step;
}
}
return next != null;
}
The CharacterIterator inside a StringWalker object refers to the string to be iterated as s which only exists once in the StringWalker object. I can therefore create many iterators of a StringWalker and they all walk the same string.
Why this weirdness?
This seemingly illogical duality derives from the use of the static keyword in C.
In C you can (or at least used to be able to) do:
void doSomething () {
static int x = 1;
if ( x < 3 ) {
} else {
}
x += 1;
}
and each time you called the function, x would be as you left it last time around - incremented in this case.
The concept was that the static keyword indicated that the variable was scopefully enclosed by its enclosing block but semantically enclosed by its parent block. I.e. the above code was roughly equivalent to:
int x = 1;
void doSomething () {
if ( x < 3 ) {
} else {
}
x += 1;
}
but x was only allowed to be referenced inside the function.
Take that concept forward into Java and things now make a little more sense. A static inner class behaves exactly like it was declared outside the class while a non-static inner bonds much more tightly to its enclosing instance - in fact it can refer to the instance directly.
Also:
class Thing {
static Object thereWillBeOnlyOne = new Object();
behaves much like
Object thereWillBeOnlyOne = new Object();
class Thing {
if it were legal.
Here endeth the lesson.
I think the Java team messed up the naming on this one. A static inner class (strictly speaking their correct name is "static nested class") is in no way different from an ordinary class except it has a fancy name (Something.MyClass instead of MyClass) and can be made private (i.e. not instantiable from other classes).
In case of Map, it was solely chosen because the name Map.Entry makes it clear that Entry relates to Map. As you suggest, it would have been perfectly reasonable to just use an ordinary class for this. The only difference is you don't get to write Map.Entry.
I think what they should have done is to use the syntax for "non-static" inner classes (i.e. just class in an enclosing class) for static nested classes, and instead invent a new keyword to create "non-static" inner classes, because it's these that behave different from normal classes. Maybe something like attached class. AFAIK the keyword static was chosen in order to avoid having too many reserved keywords, but I think it just encouraged confusion.
Yes, you can have many instances of the nested class, no matter that the nested class is static.
When the nested class is static you can create instances of it without having an instance of the enclosing class, this is one of the benefits, and basically the main difference between static and non-static nested classes.
Does this mean then that a static member class is not actually instantiated when the enclosing object is instantiated?
It's instantiated when it's constructor is called. Not any different from non-static classes. The nested class itself is loaded by the JVM, when the code first accesses it. Again this is not any different when compared to other classes, I think (not 100% sure of this though, but you can test it yourself). So I think you're kind of mixing the terms "loading the class by the JVM" and "instantiating the class".
Well in that case, what's the point of Map using a static member class for Entry? Why not just use an interface on the API?
As said, it's easier to create instances of static nested classes. You don't need an enclosing instance which is sometimes (maybe most of the times) exactly what you want.
See also:
(1) Nested Classes
(2) How can the JVM decide if a class is nested into another class?
(3) Loading of a nested class by the JVM
You can search for other references along these lines.
The reference (2) seems advanced and kind of peripheral to your question.
what's the point of Map using a static member class for Entry?
That's because, it makes the package structure logically correct.
Why not just use an interface on the API?
Now, this is a design discussion nobody would like to be dragged into.

Memory usage of a node class of a LinkedList in java (enclosing instance reference)

In page 201 of Sedgewick's algorithms4 book, the memory taken up by a Node is given as 40 bytes:
class Node{
Item item;
Node next;
}
The breakdown given is:
object overhead = 16 bytes
item reference = 8 bytes (=memory address)
next reference = 8 bytes
extra overhead = 8 bytes
The explanation for extra overhead is:
A nested non static (inner)class as our Node class (page 142) require an extra 8 bytes (for reference to the enclosing instance)
What is this enclosing instance he mentions? The Node class only contains item and next variables.
Can someone clarify this?
Well it says that the Node is a non-static inner class. If the class was static inner class it could exist without the enclosing class. Since it's not static it depends on (is a part of) the instance of the outer class in which it is defined.
So if I have a class Bar and a static inner class Foo:
public class Bar {
private class Foo {
}
}
in order to use the Foo, I would have to have an enclosing Bar, e.g.
Foo foo= new Bar().new Foo();
If the Foo was static, I could do
Foo foo= new Bar.Foo(); //i.e. new Bar.Foo()
Therefore, you need these extra 8 bytes for the enclosing instance of Bar.
What is this enclosing instance he mentions?
It is the instance of the LinkedList class that the Node object belongs to.
In fact, if you use javap to examine the ArrayList$Node.class file, you should see a mysterious synthetic attribute that contains the reference to the enclosing ArrayList instance.

B-Tree Implementation - shall I make the Node class a static member class or not?

I need to implement a B-Tree for University:
I have an "outer" class B-Tree with attributes root and _degree. The class to represent the nodes is implemented as a static-member class:
public class BTree<E> {
private Node<E> root;
// the minimal degree
private int degree;
public BTree(int degree) {
if (degree < 2) {
throw new IllegalArgumentException();
}
this.degree = degree;
}
// other stuff
private static class Node<T> {
T[] elements = (T[])new Object[degree * 2 - 1];
Node<T>[] children = (Node<T>[])new Object[degree * 2];
int size = 0;
}
}
So, now my problem is: As I implemented the Node class as a static member class, I can't access the degree attribute of the outer class.
Now I have to choices:
Make the Node class an inner class (non-static member class) OR
Create a constructor for the Node class and pass the degree in every time I need to construct a Node.
What would be the best choice? Making it an inner class would mean the Nodes would all have a reference to the Btree (outer class), but making it a static member class would mean I would have to pass the degree in every time.
I would keep it static and pass degree in. That way you ensure that Node cannot know any details about BTree.
If it were me, I'd have the Node class public so I could reuse it in other containing data structures, but that's just me. In that case, I'd have to pass the degree through the constructor, and that's OK with me too. I don't like the idea of inner classes manipulating the members of enclosing classes. I feel it makes the classes too tightly bound to each other. I know sometimes it's appropriate, but I avoid when I can and this seems an easily avoidable case.
There are arguments to make it static, because it decouples the classes.
But I think a BTree.Node is a node from a particular BTree. It doesn't make sense to go and create a bunch of Nodes (with random degrees). You can't have a Node, but no Tree. Thus, I say non-static.

Categories