public SampleBehaviour otherway(final String st) {
return new SampleBehaviour() {
private String str = st;
#Override
public void print() {
System.out.println("val:"+val);
}
};
}
SampleBehaviour is an interface.
Classes that implements an interface must define the methods behavior, whats the use of some variables in interface?
Why does the method parameter need to be final? I don't get some real time application for this type of usage? What's the real thing behind this?
If it's useful, why doesn't C++ have something like this?
From The Java Language Specification, Section 8.1.3:
Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.
Wikipedia says that it's so the inner class needs to keep its own copy of the variable since it can live on after the outer class goes out of scope; to prevent having the same variable name refer to two different locations, they forced the variable to be fixed in place.
Related
In the following code, I noticed that I can call getWorld() without a reference to the HelloWorld object? But doesn't the implicit 'this' keyword now refer to the inner anonymous class? If so, why I am able to call getWorld()?
public class HelloWorld {
public void getWorld() {
this.setListener(new MyListenerInterface(){
#Override
public void innerMethod() {
getWorld();
}
});
}
}
Ignore the recursion in the code.
The answer is in Section 15.12 of the JLS.
If it is a simple name, that is, just an Identifier, then the name of the method is the Identifier.
If the Identifier appears within the scope of a visible method declaration with that name (§6.3, §6.4.1), then:
If there is an enclosing type declaration of which that method is a member, let T be the innermost such type declaration. The class or interface to search is T.
By using just the simple name of the method, the resolution of which method to call looks up through the enclosing methods until it finds one which has a method with that name, and then attempts to use that method (or methods) to find an exact match.
This is different than the case where you use this.getWorld(), since this refers unambiguously to the inner class instance. That results in a different type of resolution (the Typename . Identifier section of the specification, just below the linked quote), which does not look at the enclosing outer class.
An interesting consequence of this is that you can cause the code to stop compiling by adding a method to the inner class which has the same name, but a different arity. Since it only is searching for the name itself when it tries to determine the class instance to resolve it on, it will try to use the inner class, but not find an exact matching method.
So this:
public class HelloWorld {
public void getWorld() {
this.setListener(new MyListenerInterface(){
#Override
public void innerMethod() {
getWorld();
}
void getWorld(int i){}
});
}
}
would not compile. Method name resolution will discover getWorld in the inner class, and so will stop searching up the hierarchy. But when it tries to do arity resolution, it will see that none of the (one) getWorld methods in the class match, and will fail.
TL;DR - using just the simple name is note quite the same as using this.method(), even though it generally evaluates to the same thing. The language specification has specific rules for handling that case, which can allow it to look in any enclosing instance to find a matching method.
Calling getWorld you get outside the anonymous class and are back at the top level class, so this refers to the object that is creating the anonymous one.
It is like calling a method from other class, this there refers to a different object (not to the caller, but to the callee).
Given this SSCE:
public class AnonymousClassTest {
String param = "initial";
void test() {
Runnable runnalbe = new Runnable() {
#Override
public void run() {
System.out.println(param);
}
};
runnalbe.run();
param = "after";
runnalbe.run();
}
public static void main(String[] args) {
new AnonymousClassTest().test();
}
}
Could anyone point to a part in JLS or any other documentation which explains why the result is
initial
after
Instead of not compiling due to lack of final for param, or just printing:
initial
initial
I remember requiring final when passing parameter this way to an anonymous class, but it seems not to be the case in Java 7. What has changed?
Nothing has changed. Fields of the outer class are always accessible to inner classes. You need final only when accessing a local variable from the inner class.
In Java 8, though, even local variables don't need to be declared final. They must simply be effectively final, i.e. the compiler is smart enough to check that they're never reassigned.
What is printed is completely normal, as the inner class simply has a reference to the outer class instance, and accesses its field the same way as methods from the outer class would do.
It's defined in the section 8.1.3:
Inner classes whose declarations do not occur in a static context may freely refer to the instance variables of their enclosing type declaration.
The way it works is straightforward: compiler makes a constructor for your inner class, and passes a reference of the enclosing instance to that constructor. Any time your inner class refers to a variable that has been resolved to a member of the enclosing class, an access is made through the reference stored at the time the object is constructed.
There is no requirement for member variables of enclosed class to be final. The requirement applies only to local variables, which are "captured" at the time the object of the inner class is created.
This question already has answers here:
why java polymorphism not work in my example
(3 answers)
Closed 6 years ago.
Generally Overriding is the concept of Re-defining the meaning of the member in the sub class.Why variables are not behaving like methods while Overriding in java ?
For instance:
class Base {
int a = 10;
void display() {
System.out.println("Inside Base :");
}
}
class Derived extends Base {
int a = 99;
#Override
// method overriding
void display() {
System.out.println("Inside Derived :");
}
}
public class NewClass {
public static void main(String... a) {
Derived d = new Derived();
Base b = d;
b.display(); // Dynamic method dispatch
System.out.println("a=" + b.a);
}
}
Since data member a is package access specified, it is also available to the Derived class. But generally while calling the overridden method using the base class reference, the method that is redefined in derived class is called (Dynamic method dispatch)..but it is not the same for the variable..why.?
EXPECTED OUTPUT
Inside Derived :
a=99
OBTAINED OUTPUT:
Inside Derived :
a=10
Prints 10 - why the variable does not behave similar to method in the derived class?
Why the variables are not allowed to be overridden in the sub class?
You typed b as an instance of Base. So when the compiler needs to resolve b.a, it looks to the definition of Base for the meaning of b.a. There is no polymorphism for instance fields.
Because the only thing that polymorphism ever applies to in Java is instance method.
Hence, you can neither override static members, nor the instance member fields. By, having these members in a derived class with the same names you're simply hiding them with a new definition.
System.out.println("a="+b.a);
Although, Base b may point to a sub-class object (at runtime) the a above has already been bound to Base class at compile time (static binding). Hence, it prints 10.
Variables behave like that because they lack behavior. In other words, variables are passive.
There is nothing about a variable's definition that a derived class can reasonably change by overriding:
It cannot change its type, because doing so may break methods of the base class;
It cannot reduce its visibility, because that would break the substitution principle.
It cannot make it final without making it useless to the base class.
Therefore, member variables declared in derived classes hide variables from the base class.
There is no way to override a class variable. You do not override class variables in Java you hide them. Overriding is for instance methods.
In this case, it might be a good idea to write a getter method:
public int getA(){
return 99;
}
Now you can override it in a derived class.
First, we don't override any class variable. Methods only.
Second, if you would like to see that the variable value has been updated or replaced, you should rather declare it as "static int" instead of "int". In this way, it will work as everybody is sharing the same variable, and the new value will be put on it.
Third, if you would like to see that the variable value being assigned and used differently, you could design it as passing a parameter in constructor, or something similar, to make it work accordingly as you desire.
The answer to this has to do with variable scoping, not polymorphism. In other words, you're overriding that variable in the class scope. So, d.a will return the variable in Derived's class scope, but b.a will return the variable in Base's class scope.
In OOP (Object Oriented Programming) the idea is to hide the data in the object and let object only communicate with invoking methods. That's why variables cannot be overloaded, in fact they are "scoped"/"attached" to a specific class.
Also the derived class should not define a again, it is already defined in the base class, so simply set a on the object to the desired value, e.g:
class Base {
private int a = 10;
public int getA() { return a; }
public void setA(inta) { this.a = a; }
}
class Derived extends Base {
// adding new variables, override methods, ...
}
// then later:
Derived d = new Derived();
d.setA(99); // override the default value 10
What would happen if variables could override other variables? Suddenly your class has to be aware of what variables the parent class is using, lest you accidentally override one and break whatever was using it in the parent class. The whole point of encapsulation is to avoid having that kind of intimate knowledge of another object's internal state. So instead, variables shadow same-named other variables, and which one you see depends on what type you're trying to reach the variable through.
There's hope, though. If all you want is to override the value, you don't have to redeclare the variable. Just change the value in an init block. If the base class is harmed by you doing that, then it chose the wrong visibility for that variable.
class Base {
int a = 10;
}
class Derived extends Base {
{ a = 99; }
}
Of course, this doesn't work very well for final variables.
we don't override any class variable. Methods only.
If you would like to see that the variable value has been updated or
replaced, you should rather declare it as "static int" instead of
"int". In this way, it will work as everybody is sharing the same
variable, and the new value will be put on it.
If you would like to see that the variable value being assigned and
used differently, you could design it as passing a parameter in
constructor, or something similar, to make it work accordingly as
you desire.
Moreover, if variables are overridden then what is left with a parent class of its own,it breaches the class security if java would give the access to change the value of variable of parent class.
I've read elsewhere that a static anonymous class doesn't make sense - that all anonymous classes should be tied to an instance of the enclosing type. But the compiler let's you do it. Here's an example:
class Test {
/*
* What's the difference at between
* Test.likeThis and Test.likeThat?
*/
// This is obviously okay:
private static final class LikeThat {
#Override
public String toString() { return "hello!"; }
}
public static Object likeThat = new LikeThat();
// What about this - is it really any different?
public static Object likeThis = new Object() {
#Override
public String toString() { return "hello!"; }
};
}
What's going on here?
From the Java Language Specification, section 8.1.3:
An instance of an inner class I whose declaration occurs in a static context has no lexically enclosing instances. However, if I is immediately declared within a static method or static initializer then I does have an enclosing block, which is the innermost block statement lexically enclosing the declaration of I.
Your anonymous class (the one likeThis is an instance of) occurs in a static context, so it is not tied to an enclosing instance. However, it seems that it can refer to final variables of its enclosing block (see the rest of section 8.1.3, they give an example).
Btw, your wording is a bit deceptive, you're actually referring to a static instance of an anonymous class (it's the instance that's static, not the class).
I see nothing wrong with static anonymous classes
Like anything in any language you should just consider why you're doing it. If you've got alot of these instances then I'd question the design decisions, but it doesn't necessarily means it's a pattern that should never be followed.
And of course, always consider the testability of the class and whether you can provide a test double if the need arises
I don't think they have no sense. If you don't need reference to enclosing object then it's better to leave it static. Later it can evolve in separate class with ease.
Wide-spread enum idiom (pre Java 5) used similar approach with anonymous static inheritors of enum class. Probably, now it is better stick to Java 5 enum for this case.
If you are able to find adequate real-world application for anonymous static classes - why not to use them?
I do this all the time. It's especially handy for special-case implementations of utility interfaces, e.g.:
/** A holder for {#link Thing}s. */
public interface ThingsHolder {
/** A {#link ThingsHolder} with nothing in it. */
public static final ThingsHolder EMPTY_HOLDER = new ThingsHolder() {
#Override
public Iterable<Thing> getThings() {
return Collections.emptySet();
}
};
/** Provides some things. */
Iterable<Thing> getThings();
}
You could create a private static inner class called EmptyHolder, and maybe in some cases that would make the code more readable, but there's no reason you have to do it.
According to this answer which references the JLS, anonymous classes are never static, but when created in a "static context" they have no "enclosing instance".
That said,
They give the same error at compile time if you try to reference Test.this (non-static variable this cannot be referenced from a static context)
At runtime, the only obvious difference between the Class objects (apart from name) is that Test$1 is an "anonymous class" and Test$LikeThat is a "member class". Both of them have an enclosing class; neither of them have an enclosing constructor or method. (I only checked the likely-looking methods; there may be other differences.)
EDIT: According to getModifiers(), Test$1 is static and Test$LikeThat is static final! According to the language spec, Test$1 should actually be final. Hmm...
According to javap -c -verbose -s -private -l,
Test$1 specifies an "EnclosingMethod" (probably Test's static initializer?)
Test$LikeThat has an extra entry under "InnerClass" (#12; //class Test$1) and a curious constructor Test$LikeThat(Test$1). This appears to happen because LikeThat is private which makes the constructor private, so the compiler generates a "trampoline" to allow it to be called from Test.
If you remove the private, they appear to compile to roughly the same thing apart from the EnclosingMethod entry.
Test$1 does not have the field final Test this$0; that it would if it was defined in a non-static context.
Seems perfectly legitimate to me. Since the anonymous class is static it won't have a reference to any enclosing class, but there should be no evil consequences from that.
Well, other than being a hidden singleton object, that's pretty evil.
Of course they are not. I always use static nested classes, unless I need the implicit association to the enclosing object.
In java terminology nested class := a class which is declared within another class (or interface). Inner classes are those nested classes which have an associated instance from the enclosing class. (Nonstatic member classes, local classes, anonymous classes).
The implicit association can prevent garbage collection sometimes.
These can be very convenient because of possibility to make circular references:
class A
{
public static final A _1 = new A() {
public A foo()
{
return _2;
}
};
public static final A _2 = new A() {
public A foo()
{
return _1;
}
};
}
Creation of several objects which are holding references to each other can be very awkward without usage of anonymous classes.
GIVEN:
class A
{
String s = "A";
}
class B extends A
{
String s = "B";
}
public class C
{
public static void main(String[] args){ new C().go();}
void go()
{
A a = new B();
System.out.println(a.s);
}
}
Question:
What are the mechanics behind JVM when this code is run? How come a.s prints back as "A".
Field references are not subject to polymorphism, so at compile time the compiler is referencing A's field because your local variable is of type A.
In other words, the field behavior is like the Java overloading behavior on methods, not the Java overriding behavior.
You probably expect fields to be overridden like method, with dynamic dispatch based on the runtime type of the object.
That's not how Java works. Fields are not overridden, they are hidden. That means an object of class B has two fields named "s", but which of them is accessed depends on the context.
As for why this is so: it wouldn't really make sense to override fields, since there is no useful way to make it work when the types are different, and simply no point when the type is the same (as you can just use the superclass field). Personally, I think it should simply be a compiler error.
This isn't polymorphism (as tagged).
Java has virtual methods, not virtual member variables - i.e. you don't override a property - you hide it.
Although member variables are inherited from a base class, they are not invoked polymorphically (i.e dynamic invocation does not apply to member variables).
So, a.s will refer to the member in the base class and not the derived class.
Having said that, the code is not following OO principles. The members of a class need to be private/protected (not public or default) depending on the business use case and you need to provide public methods to get and set the values of the member.