What is the advantage of local classes in Java or in any other language that makes use of this feature?
Here's an example of how an anonymous inner class, a local inner class, and a regular inner class might be present in a program. The example is looking at a myMethod method and a InnerClass class present in MyClass class. For the sake of discussion, those classes will all be implementing the Runnable interface:
public class MyClass
{
public void myMethod()
{
// Anonymous inner class
Runnable r = new Runnable() {
public void run() {}
};
// Local inner class
class LocalClass implements Runnable
{
public void run() {}
}
}
// ... //
// Inner class
class InnerClass implements Runnable
{
public void run() {}
}
}
The anonymous inner class can be used to simply to make an class that implements Runnable without actually having to write out the class and naming it, and as krosenvold mentioned in his post, it is used as a "poor man's closure" in Java.
For example, a very very simple way to start a Thread using an anonymous inner class would be:
new Thread(new Runnable() {
public void run()
{
// do stuff
}
}).start();
An local inner class can be used to make a class that is within the local scope -- it won't be able to be accessed from other methods outside of myMethod.
If there was another method and we tried to make an instance of the LocalClass that is located inside the myMethod method, we won't be able to do so:
public void anotherMethod()
{
// LocalClass is out of scope, so it won't be found,
// therefore can't instantiate.
new Thread(new LocalClass()).start();
}
An inner class is part of the class that the inner class is located in. So, for example, the inner class InnerClass can be accessed from other classes by MyClass.InnerClass. Of course, it also means that another method in MyClass can instantiate an inner class as well.
public void anotherMethod()
{
// InnerClass is part of this MyClass. Perfectly instantiable.
new Thread(new InnerClass()).start();
}
Another thing about the anonymous inner class and local inner class is that it will be able to access final variables which are declared in the myMethod:
public void myMethod()
{
// Variable to access from anonymous and local inner classes.
final int myNumber = 42;
// Anonymous inner class
Runnable r = new Runnable() {
public void run()
{
System.out.println(myNumber); // Works
}
};
// Local inner class
class LocalClass implements Runnable
{
public void run()
{
System.out.println(myNumber); // Works
}
}
// ... //
So, what are the advantages? Using anonymous inner classes and local inner classes instead of having a separate full-blown inner class or class will allow the former to have access to final variables in the method in which they are declared, and at the same time, the classes are local to the method itself, so it can't be accessed from outside classes and other methods within the same class.
There are a number of things that you can do with local classes that you don't get with anonymous inner classes.
because the type has a name, you can more usefully add members not in the supertype
a given name can make stack traces easier to follow (particularly for lock objects)
subtype more than one base type
construct in more than one place, and multiple constructors
On the other hand they make some hideously verbose syntax even messier.
They allow you to take logic out of the parent class and objectify it. This removes functionality from where it doesn't belong and puts it into its own class. But what if this new object is only needed for a short time, only for the duration of a single block of code? Well, that's where a local class fits in.
Related
I am starting java programming and I came across abstract classes. I know that you cannot instantiate them without creating concrete classes which extend them to become the subclass. However, I got really confused when I tried this code and it runs ok.
abstract class Communication{
public void FirstMethod()
{
System.out.println("I am first method()\n");
}
}
public class Main{
public static void main(String[] args){
Communication communication = new Communication() {
#Override
public void FirstMethod(){
super.FirstMethod();
}
};
communication.FisrtMethod();
}
}
Output is: I am first method().
If I modify it to:
Communication communication = new Communication() {
#Override
public void FirstMethod(){
System.out.println("I've been called from Main");
}
};
The output is: I've been called from Main.
Could somebody please explain if this is a kind of instantiation or what concept is this?
This is termed as
Anonymous Class
Definition:
An inner class declared without a class name is known as an anonymous inner class.
In case of anonymous inner classes, we declare and instantiate them at the same time. Generally, they are used whenever you need to override the method of a class or an interface.
This is called anonymous inner class. This way you can implement an interface or abstract class without having to find a name for it and instantiate it at the same time. This concept is useful when you use a certain implementation just once.
The construct looks always like that:
new SomeClass() {
//implementation of methods
};
This is known as anonymous class. The anonymous class definition allows you to provide a class definition within code and it has no formal name. The anonymous class expression has the class definition and instance creation expression.This is not limited to abstract classes but also for interfaces and concrete classes.
For example
abstract class A { }
// so the anonymous class expression is
A a = new A() {// class definition };
// This will actually create an instance of a
// class that extends the abstract class A
// that java will create at run time
You can even use anonymous class expression in the method arguments.Example of this is a Comparator in Collections.sort() method;
Collections.sort(listOfValues,new Comparator<Value>(){
public int compare(Value v1, Value v2){
// method implemetation.
}
})
I have studied some books for OCPJP 7 certification and in the inner classes chapter there were some strange/incomplete informations. I've tried to create an interface inside a method, but it seems you can't do that, you can only create classes inside a method. Is there any reason why you can't do that or it's just a missing feature?
Sample code:
public class Outer {
public void method() {
class C {} // allowed
interface I {} // interface not allowed here
}
}
If you read carefully the Java Tutorials, you will see that:
You cannot declare an interface inside a block, because interfaces are inherently static.
This means that if you have an interface, like this one:
public class MyClass {
interface MyInterface {
public void test();
}
}
You will be able to do
MyClass.MyInterface something = new MyClass.MyInterface() {
public void test () { .. }
};
because MyInterface will be explicitly static. It doesn't make sense to be tied to an instance of the enclosing class, because it just provides some abstraction which doesn't have to be bound to a specific instance or a state of the enclosing class.
Same thing goes to the case, in which the interface is nested in a method. Nothing inside the method could be (explicitly) static (because non-static methods are tied to a specific instance of the enlosing class) and thus you can't have a local interface.
I'm struggling on the concept of static vs. non-static. I'm studying this Thread example program(modified, from here originally), and when I use inner classes I will get the error:
Error: non-static variable this cannot be referenced from a static context
Here is the error-causing code:
public class Main2 {
public static void main(String[] args) {
Thread simple = new Thread(new SimpleTask());
simple.start();
}
class SimpleTask implements Runnable {
public void run() {
}
;
}
class DaemonTask implements Runnable {
public void run() {
int i = 0;
}
}
}
However, when I break it out so that it's 3 classes, there's no error.. ie if I make it:
public class Main2 {
/* contents */
}
class SimpleTask implements Runnable {
/* contents */
}
class DaemonTask implements Runnable {
/* contents */
}
Then it compiles just fine. Why does it matter that we split it out into another class?
you need an outer class instance(Main2) to access inner class instance(SimpleTask).
Try this:
Thread simple = new Thread(new Main2().new SimpleTask());
Check Inner class on Oracle trails
Because your classes are non-static inner classes; they implicitly need a corresponding instance of the outer class.
Declare your inner classes as static, and your issue should go away.
Try and make class SimpleTask implements Runnable static.
When you declare a class like that, you are declaring somewhat of a per-instance class definition. To be more precise, you are tying the class definition of SimpleTask to an instance of Main2.
In order to instantiate an object of that class you would do:
Main2 obj = new Main2();
SimpleTask t = obj.new SimpleTask();
Notice the use of obj.new. When you call that from inside your outer class, you are really calling this.new. Static methods have no knowledge of this, so you get an error.
SimpleTask and DemonTask class should be static
Instance members(in your case SimpleTask and DemonTask) are associated with the particular object of class.And so you can't use instance members directly within static method(becuase static members don't have any information about the instances of class unless you pass the instance itself as parameter)
You have to either create an object of Main2 and access SimpleTask and DemonTask through it new Main2().new SimpleTask()
OR
make those two classes static
The issue is in the line "Thread simple = new Thread(new SimpleTask());" As the class SimpleTask is defined as a nested class, you need an object of the outer class to create one (the constructor essentially requires an implicit reference to the containing class, similar to how normal methods get an implicit reference to the current class instance as 'this').
What you are essentially asking for here is "Thread simple = new Thread(null.new SimpleTask());" and it's this 'null' which is causing the exception.
If I have class with a nested class, why wouldn't you want it to be static? Is there even a way for two instances of the same class to have different nested classes?
For example:
class MyClass {
public static class myInnerClass {
}
}
why wouldn't you want it to be static
Because I want it to access instance data of a parent object.
Is there even a way for two instances of the same class to have different nested classes?
What do you mean by have? Declared? A class has only one declaration where you list all nested classes. So, in this case the answer is no.
Take for example a Comparator or Runnable (multi-threading) implementations. This is a classic example when you need an extra class that has access to the current instance's fields and methods but is of no use outside of that class. However, static classes could be useful outside the enclosing type, too.
public class EnclosingType
{
private static final class StaticRunnableImplementation implements Runnable
{
private final EnclosingType instance;
public StaticRunnableImplementation(EnclosingType instance)
{
this.instance = instance;
}
#Override
public void run()
{
instance.getSomething();
//getSomething() leads to compile error
}
}
public class NonStaticRunnableImplementation implements Runnable
{
#Override
public void run()
{
doStuff();
}
}
public int getSomething()
{
return 42;
}
public synchronized void doStuff()
{
;
}
public void doSomething()
{
Thread t1 = new Thread(new StaticRunnableImplementation(this));
Thread t2 = new Thread(new NonStaticRunnableImplementation());
t1.start();
t2.start();
}
}
The access to the non-static methods and fields of current instance of the enclosing type, wouldn't be possible if the nested classes would be declared static.
I don't know if I understand your question correctly, but the difference between a static inner class to a non-static is that the second needs a reference from the parent class to be created.
It's preferable to create static class, because of "hidden ciclic references" that can be created. For example, it's normal in GUI developing you do something like
public class View {
private Table table;
...
private void addListeners() {
this.table.addListener(new TableSelectionListener());
}
privte class TableSelectionListener implements Table.SelectionListener {
#Overrides
public void selected(SelectionEvent evt) { /* do stuff.*/ }
}
}
Lots of programmers don't realize, but you now have a circular reference between View and Table, because SelectionListener, being non static, saves a reference to its parent. So
View -> Table -> TableSelectionListener --> View
If you declare TableSelectionListener static it will only need the "namespace" from view to be created, but besides that, it will not save a reference to any View unless you save it on a field. But then, you will return to the first problem :P
Hope that helps :)
A non-static nested class is associated and has access to the members of an enclosing class instance:
Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.
If you implement a Listener of some kind, for example, you usually want to call a method on the outer class when you receive the event. In that case, an inner class is simpler than a nested class with an explicit reference to the outer class instance.
That's often used in GUI components. For example (using an API which doesn't actually exist):
public class CircleView extends View {
private final Circle circle = new Circle();
private final Button button = new Button();
public CircleView() {
circle.setColor(Color.RED);
button.addClickListener(new MyClickListener());
}
private toggleColor() {
circle.setColor(circle.getColor() == Color.RED ? Color.BLUE : Color.RED);
}
private class MyClickListener implements ClickListener() {
#Override
public void onClick() {
// Only possible because of the implicit reference:
toggleColor();
}
}
}
A non-static nested class allows the following in an implicit/magical way:
class MyClass {
public static class MyInnerClass {
final MyClass myClass_this;
public MyInnerClass(MyClass parent) {
// Nested class instance has/keeps access to "parent" object.
// In a nested non-static class the "parent" is -guaranteed- to be
// non-null as the nested class can only be created with
// an instance of the containing class.
myClass_this = parent;
}
public Foo bar() {
// Use myClass_this
// Would be available as MyClass.this or implicit resolution in a
// a nested non-static class.
}
}
}
The rules for scope access are also a bit different but the above should show when it might be useful/desirable. In both cases there is only one type for the inner class (MyClass$MyInnerClass), although there can be many instances.
Wether or not this is a "good" thing to have such non-static nested type behavior is debatable, but it is provided in Java.
However, one case where this "non-static" behavior is extremely useful in Java is with anonymous classes (e.g. event handlers or callbacks) which behave as non-static nested classes; while a "different" construct the same mechanism allows accessing methods defined in the enclosing type. Moving the anonymous classes to non-static nested classes can thus merely be viewed as an extension of this common idiom that also allows exposing the nominative type.
(C# has no notion of a "non-static" nested class, but it is easy to emulate it as per above - although I would argue it's usually better to pass a more-refined interface. In addition, other constructs such as closures minimize the need/use even more.)
How do I pass a object to an implement and pass the local object to object that is outside? I think the SwingUtilities.invokeLater is nessasary for a Swing object , right?
Sensors sens = new Sensors();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI application = new GUI(sens);
application.getJFrame().setVisible(true);
}
});
SMS sms = new SMS(application);
this is me try to solve the problem , but i get a No enclosing instance of type GUI is accessible. Must qualify the allocation with an enclosing instance of type GUI (e.g. x.new A() where x is an instance of GUI). problem.
// in main
Sensors sens = new Sensors();
GUI application = null;
SwingUtilities.invokeLater(new GUIthread(sens , application));
SMS sms = new SMS(application);
//a class inside GUI.java , but not inside GUI class
class GUIthread implements Runnable{
Sensors s;
GUI g;
public GUIthread(Sensors s , GUI g){
this.s = s;
this.g = g;
}
#Override
public void run() {
// TODO Auto-generated method stub
g = new GUI(s);
g.getJFrame().setVisible(true);
}
}
the sourcecode
This problem arises when you try to create an instance of a non-static inner class in a context that does not specify (or imply) an instance of the enclosing class.
From this, I deduce that you have declared one of your classes as a non-static inner class; e.g. something like this:
public class Outer {
...
public class Inner {
public Inner() {
...
}
...
}
...
}
If you now try to create an instance of Inner in some other code using new Inner(), you will get a compilation error like the one you are seeing.
You can do one of two things to "fix" the problem:
If you change public class Inner { to public static class Inner {, you can use new Inner() as you are currently doing. But this will mean that the code of Inner cannot access the (final) instance variables of the enclosing class; i.e. Outer.
If you don't want to change Inner to a static class, you will need to instantiate it as follows:
Outer outer = ...
...
Inner inner = outer.new Inner(); // qualified creation
FOLLOWUP
any down side using static class to call swing?
Only the one that I identified above.
SO , all the instantiate happen inside Outer constructor? right?
No. The code in the "qualified creation" example above can appear anywhere that the Inner class is accessible. And since we declared it as public ...
If you instantiate Inner inside a constructor (or instance method) for Outer, you can just use new Inner(). The enclosing Outer instance is the same as this.
Try
final Sensors sens = new Sensors();
instead.
Easy, declare the reference final and it will be seen by the anon class code.
I agree with Zach and suspect that GUIthread is an inner class. If so, you may do well to make it a stand-alone class or a static inner class, but it's difficult to know if this is the true solution without more information and without the actual error message.