I've been trying to understand the difference between nested, local, anonymous classes and I'm confused about a few things, but mostly why you cannot do this:
class OuterClass {
InnerClass innerClass = new InnerClass() {
//DO SOMETHING
};
}
w/o doing this...
class OuterClass {
class InnerClass {
}
InnerClass innerClass = new InnerClass() {
//DO SOMETHING
};
}
or this...
class OuterClass {
InnerClass innerClass = new InnerClass() {
//DO SOMETHING
};
}
class InnerClass {
}
How is this at all different from this really?
class OuterClass {
InnerClass innerClass = new InnerClass();
innerClass.innerClassMethod();
}
class InnerClass {
public void innerClassMethod() {
}
}
And why is it called anonymous? I dont understand that. Reading this link here I understand the logistical differences (i.e. no name, only 1 instantiation, only accessible where defined, etc. But it's really not a class so why is it called a class? It's actually, from what I can see an instantiation of a class. I see you can have other methods as well from the class it is derived from, but how are you allowed to have completely different methods than the base class w/o having to use #Override?
Everywhere you have written 'DO SOMETHING' you are actually creating a new class that inherits from whatever type is behind the 'new' Keyword...
This temporary class has no name of its own, hence anonymous.
It ends with ; because it is actually just a parameter of the outer class.
As Silvio pointed out in the comments all classes extend some class, even if it just the Object class.
You can't do this:
class OuterClass {
InnerClass innerClass = new InnerClass() {
//DO SOMETHING
};
}
Because InnerClass does not exist yet to inherit from.
Two points about that what you're doing there with InnerClass innerClass = new InnerClass() {};
First you're using the class InnerClass as a template that you extend by another anonymous class, instantiate that and save that reference to the variable innerClass.
So InnerClass has to be defined.
And because there is no available named class definition for the object named innerclass, this is why it's anonymous.
Second, your comment //DO SOMETHING in there is wrong. The only thing you can do in there is to override already existing methods. Yes, you can also add new methods, but you cannot call the from the outside directly.
InnerClass could be a normal class, an abstract class, or an interface.
Defining class InnerClass {} inside another class would be a nested class. The way you do it it is dependent on the state of the OuterClass.
This could also be static, i.e. decoupled from any instance that Outerclass and its generica parameters would have.
Your third example is a normal (additional) class definition inside a file. But because Java Language Specification defines that there can not be two top-level public classes in one file, this second class definition cannot be public. Because JLS also states that the one top-level public class inside a file has to have the same name as the file it's defined in.
And to answer your last question, in reference to what I said about 'not being able to acces other methods': In your last example you explicitly define the method innerClassMethod() in a names class, and so it can be accessed.
I create an method local Inner Class and combine with abstract class. The code work fine but I do not understand the error popup in IntelliJ about I can't set Method in inner class that extend from abstract inner class to be private.
I have to change from "Private InnerClassSubclass" to "Public InnerClassSubclass" and if I won't the error is follow:
'innerMethod()' in 'InnerClassSubclass' clashes with 'innerMethod()'
in 'InnerClass'; attempting to assign weaker access privileges
('private'); was 'public'.
I thought private is stronger privilege isn't it? only allow class within the same class to access.
I also try to change 'abstract class InnerClass' to 'private abstract class InnerClass' also got this error;
"Modifier 'private' not allowed here" at private of 'private abstract
class InnerClass'
the code is below:
public class Outerclass {
// instance method of the outer class
private void outer_Method() {
int num = 23;
// method-local inner class
abstract class InnerClass {
abstract public void innerMethod();
} // end of inner class
class InnerClassSubclass extends InnerClass {
public void innerMethod() { //if I extends, I can't use private for innerMethod here.
System.out.println("This is method inner class " + num);
}
}
// Accessing the inner class
new InnerClassSubclass().innerMethod();
}
public static void main(String args[]) {
Outerclass outer = new Outerclass();
outer.outer_Method();
}
}
Could someone clarify me why? Thank you.
You can't restrict the visibility of methods in a subclass.
Assume an Animal class has a public method "breath()". Client code receives an Animal object and invokes that method.
Now imagine you had a Dog subclass, and you pass a doggy object. How should the client code know that his specific Animal does not offer that method?!
Thus: restricting visibility of methods is conceptually wrong, and therefore the compiler gives you an error that exactly says so.
'innerMethod()' in 'InnerClassSubclass' clashes with 'innerMethod()' in 'InnerClass'; attempting to assign weaker access privileges ('private'); was 'public'.
This is correct. You will always be able to write
InnerClass ic = new InnerClassSubclass();
ic.innerMethod(); // method is public
Consider this more general case.
static void callInnerMethod(InnerClass ic) {
ic.innerMethod(); // method is public
}
You can't make this cause a compile error when you pass an InnerClassSubclass. In a more general case you only know the actual type at runtime so it's not solvable at compile time.
InnerClass ic = Class.forName(someString).asSubClass(InnerClass.class).newInstance();
ic.innerMethod(); // this will compile as the method is public.
Firstly, you cannot make the method private because as per java overriding principles, child class cannot make the access modifier of overriding method tighter than that in it's parent class. Here, because parent class have access modifier as public, it should be made public in child class as well
Secondly, inner class can only have only two access modifier : abstract and final. You cannot declare it as private
In the book 'Java OCP 8 Programmer II Study Guide', it is said that
an anonymous inner class is a local inner class
and
a local inner class is a nested class defined within a method
However, I am able to define an anonymous inner class outside a method:
public class Outer {
Foo ex = new Foo {
#Override
public void bar() {
System.out.println("This is my bar implementation");
}
}
}
void TestClass {
public static void main(String[] args) {
Outer outer = new Outer();
outer.ex.bar();
}
}
Is the book wrong in saying that an anonymous inner class is a local inner class as it doesn't have to be local (within a method) or is the example I provided not an anonymous inner class (as it is assigned to a named variable)?
Thanks
ex is not a local class. anything that a local class cannot be anonymous and vice-versa (to the best of my knowledge)
Quoting from Oracle's Java OO tutorial on 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.
Couple of lines below ..
While local classes are class declarations, anonymous classes are expressions, which means that you define the class in another expression
I've been programming for years using .NET and I'm taking the plunge into Java with some simple starter programs.
I'm having a bit of trouble though...
When I create my start-up class with public void main, the compiler won't let me instantiate any of the classes I've written?
The error I'm getting is "non-static variable _processor cannot be referenced from a static context" where _processor is the object I'm trying to instantiate from the Processor class that I wrote.
The program will compile and run just fine when I change Processor to a static class, but I don't want to have to make all of my classes static.
Any way around this?
Thanks in advance!
Here's everything I've written. It won't compile in the current state:
class Lab
{
public static void main(String[] args)
{
Processor proc = new Processor();
proc.Go();
}
private class Processor
{
private Random _rand = new Random();
public void Processor() {}
public void Go()
{
}
}
}
Is Processor an inner class of Lab by any chance? (yes, now that you published your code, my suspicion is confirmed).
In Java, nonstatic inner classes contain an implicit reference to the containing object of the outer class, so they can't be instantiated from static context (from your main method).
So
either create an instance of Lab (e.g. myLab), and then call myLab.new Processor(), or
declare Processor static (as you did), or
turn Processor into a top level class.
Is this your problem, by any chance?
public class DemoClass{
String field;
public static void main(String[] args){
field = "Hey"; //forbidden - can't access instance field from static context
DemoClass dc = new DemoClass();
dc.field = "Hey"; //this is ok
}
}
You should call a constructor from main:
public static void main(String[] args){
new MyClass();
}
And put your instantiations in the constructor.
but I don't want to have to make all of my classes static.
Most inner classes in Java are static, in my experience. If you can write an inner class in a separate file (it does not use directly the members of the containing class), it should then be defined as static. It really is only for convenience that Java lets you write inner static classes inside other classes.
Your process class is an inner class of your lab class, you can't create an instance of your process class until you instantiate an instance of you lab class, unless that inner class is static or something.
Main will run in your lab class, because it is static, but when you attempt to create an instance of the private inner class, you can't because this class is a "private inner" class of Lab, and you don't have a lab instance, so you can't reference it directly.
You can try making your processor class static, or at the very least public, or better yet you can instantiate an instance of your lab class first, and reference creation of the processor class through your instantiate lab class.
I was looking at the Java code for LinkedList and noticed that it made use of a static nested class, Entry.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
What is the reason for using a static nested class, rather than an normal inner class?
The only reason I could think of, was that Entry doesn't have access to instance variables, so from an OOP point of view it has better encapsulation.
But I thought there might be other reasons, maybe performance. What might it be?
Note. I hope I have got my terms correct, I would have called it a static inner class, but I think this is wrong: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
The Sun page you link to has some key differences between the two:
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.
...
Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
There is no need for LinkedList.Entry to be top-level class as it is only used by LinkedList (there are some other interfaces that also have static nested classes named Entry, such as Map.Entry - same concept). And since it does not need access to LinkedList's members, it makes sense for it to be static - it's a much cleaner approach.
As Jon Skeet points out, I think it is a better idea if you are using a nested class is to start off with it being static, and then decide if it really needs to be non-static based on your usage.
To my mind, the question ought to be the other way round whenever you see an inner class - does it really need to be an inner class, with the extra complexity and the implicit (rather than explicit and clearer, IMO) reference to an instance of the containing class?
Mind you, I'm biased as a C# fan - C# doesn't have the equivalent of inner classes, although it does have nested types. I can't say I've missed inner classes yet :)
There are non-obvious memory retention issues to take into account here. Since a non-static inner class maintains an implicit reference to it's 'outer' class, if an instance of the inner class is strongly referenced, then the outer instance is strongly referenced too. This can lead to some head-scratching when the outer class is not garbage collected, even though it appears that nothing references it.
Static inner class is used in the builder pattern. Static inner class can instantiate it's outer class which has only private constructor. You can not do the same with the inner class as you need to have object of the outer class created prior to accessing the inner class.
class OuterClass {
private OuterClass(int x) {
System.out.println("x: " + x);
}
static class InnerClass {
public static void test() {
OuterClass outer = new OuterClass(1);
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass.InnerClass.test();
// OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
}
}
This will output x: 1
static nested class is just like any other outer class, as it doesn't have access to outer class members.
Just for packaging convenience we can club static nested classes into one outer class for readability purpose. Other than this there is no other use case of static nested class.
Example for such kind of usage, you can find in Android R.java (resources) file.
Res folder of android contains layouts (containing screen designs), drawable folder (containing images used for project), values folder (which contains string constants), etc..
Sine all the folders are part of Res folder, android tool generates a R.java (resources) file which internally contains lot of static nested classes for each of their inner folders.
Here is the look and feel of R.java file generated in android:
Here they are using only for packaging convenience.
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.techpalle.b17_testthird;
public final class R {
public static final class drawable {
public static final int ic_launcher=0x7f020000;
}
public static final class layout {
public static final int activity_main=0x7f030000;
}
public static final class menu {
public static final int main=0x7f070000;
}
public static final class string {
public static final int action_settings=0x7f050001;
public static final int app_name=0x7f050000;
public static final int hello_world=0x7f050002;
}
}
Well, for one thing, non-static inner classes have an extra, hidden field that points to the instance of the outer class. So if the Entry class weren't static, then besides having access that it doesn't need, it would carry around four pointers instead of three.
As a rule, I would say, if you define a class that's basically there to act as a collection of data members, like a "struct" in C, consider making it static.
From http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html:
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.
Simple example :
package test;
public class UpperClass {
public static class StaticInnerClass {}
public class InnerClass {}
public static void main(String[] args) {
// works
StaticInnerClass stat = new StaticInnerClass();
// doesn't compile
InnerClass inner = new InnerClass();
}
}
If non-static the class cannot be instantiated exept in an instance of the upper class (so not in the example where main is a static function)
One of the reasons for static vs. normal have to do with classloading. You cannot instantiate an inner class in the constructor of it's parent.
PS: I've always understood 'nested' and 'inner' to be interchangeable. There may be subtle nuances in the terms but most Java developers would understand either.
Non static inner classes can result in memory leaks while static inner class will protect against them. If the outer class holds considerable data, it can lower the performance of the application.
JVM knows no nested classes. Nesting is just syntactic sugar.
Below images shows Java file:
Below images show class files representation of the java file :
Notice that 2 class files are generated, one for parent and another for nested class.
Non-static nested class' objects have access to the enclosing scope. That access to the enclosing scope is maintained by holding an implicit reference of the enclosing scope object in the nested object
Nested class is a way to represent the intent that the nested class type represents a component of the parent class.
public class Message {
private MessageType messageType; // component of parent class
public enum MessageType {
SENT, RECEIVE;
}
}
class Otherclass {
public boolean isSent(Message message) {
if (message.getMessageType() == MessageType.SENT) { // accessible at other places as well
return true;
}
return false;
}
}
private static nested class represents Point#3 & the fact the nested type can only be the subcomponent to the parent class. It can't be used separately.
public class Message {
private Content content; // Component of message class
private static class Content { // can only be a component of message class
private String body;
private int sentBy;
public String getBody() {
return body;
}
public int getSentBy() {
return sentBy;
}
}
}
class Message2 {
private Message.Content content; // Not possible
}
More details here.
I don't know about performance difference, but as you say, static nested class is not a part of an instance of the enclosing class. Seems just simpler to create a static nested class unless you really need it to be an inner class.
It's a bit like why I always make my variables final in Java - if they're not final, I know there's something funny going on with them. If you use an inner class instead of a static nested class, there should be a good reason.
Using a static nested class rather than non-static one may save spaces in some cases. For example: implementing a Comparator inside a class, say Student.
public class Student {
public static final Comparator<Student> BY_NAME = new ByName();
private final String name;
...
private static class ByName implements Comparator<Student> {
public int compare() {...}
}
}
Then the static ensures that the Student class has only one Comparator, rather than instantiate a new one every time a new student instance is created.
Adavantage of inner class--
one time use
supports and improves encapsulation
readibility
private field access
Without existing of outer class inner class will not exist.
class car{
class wheel{
}
}
There are four types of inner class.
normal inner class
Method Local Inner class
Anonymous inner class
static inner class
point ---
from static inner class ,we can only access static member of outer class.
Inside inner class we cananot declare static member .
inorder to invoke normal inner class in static area of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inorder to invoke normal inner class in instance area of outer class.
Inner i=new Inner();
inorder to invoke normal inner class in outside of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inside Inner class This pointer to inner class.
this.member-current inner class
outerclassname.this--outer class
for inner class applicable modifier is -- public,default,
final,abstract,strictfp,+private,protected,static
outer$inner is the name of inner class name.
inner class inside instance method then we can acess static and instance field of outer class.
10.inner class inside static method then we can access only static field of
outer class.
class outer{
int x=10;
static int y-20;
public void m1() {
int i=30;
final j=40;
class inner{
public void m2() {
// have accees x,y and j
}
}
}
}