I've been examining the Java Language Specification here (instead I should be out having a beer) and I am curious about what a method can contain. The specification states a method body can contain a block
MethodBody:
Block
Where a 'Block' contains 'BlockStatements'. The 'BlockStatement' rule looks like this:
BlockStatement :
LocalVariableDeclarationStatement
ClassOrInterfaceDeclaration
[Identifier :] Statement
I can understand the 'LocalVariableDeclarationStatement' which could be
[final] int x, y, z;
However, I don't get why the 'ClassOrInterfaceDeclaration' rule is there. This rule looks like:
ClassOrInterfaceDeclaration:
ModifiersOpt (ClassDeclaration | InterfaceDeclaration)
ClassDeclaration:
class Identifier [extends Type] [implements TypeList] ClassBody
InterfaceDeclaration:
interface Identifier [extends TypeList] InterfaceBody
What's going on here - You can't declare a class or interface within a block surely?
Can someone help elucidate this confusion please?
Update: I can define a class within a method, but the following won't work:
public class Foo {
public void doFoo() {
interface dooJa {
int bar();
}
}
}
The compiler complains stating "The member interface dooJa can only be defined inside a top-level class or interface"... any explanations?
Oh yes you can declare a class inside a method body. :-)
class A {
public void doIt() {
class B {}
B b = new B();
System.out.println(b.getClass());
}
}
You've made a good observation about interfaces not working anymore. The reason is you that are looking at a very old version of the grammar. It looks to be over 10 year old. Take a look the grammar for Java 6 (what you are probably testing with):
http://www.it.bton.ac.uk/staff/rnb/bosware/javaSyntax/rulesLinked.html#BlockStatement
You will see blockstatement:
BlockStatement:
LocalVariableDeclarationStatement
ClassDeclaration
Statement
An example for a block with an inner class declaration:
public class Test {
static
{
class C {}
C c = new C();
}
}
Although I doubt you'll find a use case...
As others have said, you can declare a class inside a method. One use case of this is to use this as an alternative for an anonymous inner class. Anonymous inner classes have some disadvantages; for example, you can't declare a constructor in an anonymous inner class. With a class declared locally in a method, you can.
Here's a silly example that doesn't really show why you'd want to do this, but at least how you could do it.
public Runnable createTask(int a, int b) {
// Method-local class with a constructor
class Task implements Runnable {
private int x, y;
Task(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public void run() {
System.out.println(x + y);
}
}
return new Task(a, b);
}
These are called local classes. I use it occasionally, but it's not really a necessity.
Edit: a local class can be static, if it appears in a static context, for example, within a static method.
From the wording of the spec, local/inner/anno classe always means class only, not interface.
Related
I show written by me example, it is caused by the fact that I don't understand some thing in java puzzlers:
public class A {
public A foo() {return new A();}
}
package library;
public class C extends A {
static class X extends A {}
#Override
public A foo(){
return new X();
}
}
package library;
public class B extends A {
public static class Y extends A { }
#Override
public A foo(){
return new Y();
}
}
package client;
import library.A;
import library.B;
import library.C;
class Client {
public static void main (String[] args){
A b = new B();
A c = new C();
A bb = b.foo();
A cc = c.foo();
cc.hashCode(); // for me, it should causes compile error
}
}
As you can see, foo method is public.
A cc = c.foo(); - cc is instance of non-public type X
A bb = b.foo(); - bb is instance of public type Y
So, when we invoke cc.hashCode() we invoke public method from non-public type which comes from different package. Why does it is correct?
Why I think so ?
In java puzzlers book I found:
You cannot legally access a member of nonpublic type from another
package.
Moreover,
You can avoid this whole category of problem if you use reflection
only for instantiation and use interfaces to invoke methods from the
class that implements them and provides a high level of type-safety.
Can anyone explain it ? What does it mean in human-language?
Can anyone explain it ? What does it mean in human-language?
Explanation:
The Java Puzzlers book is probably referring to something else. (But who knows: you haven't given us the context.)
The Java Puzzlers book is not designed to be a specification, textbook or tutorial for the Java language. We should therefore not try to use it as such ... and we should not treat its explanations as either complete or definitive.
In fact you can call methods of a non-public class if they implement or override methods declared in a public superclass or interface of the non-public class.
The technical explanation is that
A cc = c.foo();
is accessing a foo() method that is declared in A ... which is a public class. The fact that foo() is overridden in a non-public class does not make the overriding method non-accessible. And if it did, that would violate the principle of substitutability which is principle that makes polymorphism1 work.
Or to put it more simply.
c is an instance of A.
Every A has a foo() method.
Anything to which the declaration of A::foo() is visible must be able to see the method on any instance of A.
If it can see it, it can invoke it.
1 - Strictly speaking, we are talking about subtype polymorphism here. There are other kinds of polymorphism as well to which LSP does not apply.
I have this scenario:
public class A
{
private final Integer index;
public Integer getIndex() { return index; }
public static class B
{
//unimportant
}
}
public class C extends B
{
//how to reference getIndex() here?
}
How can I call getIndex() in class C's body?
Odd scenario... but you'd have to move class C to also be an inner class inside class A. Shrug? Curious why are you extending an inner class in the first place? What are the restrictions of the design that are causing this? Not judging you at all. Having the thinking behind the design could aide in possibly finding an alternative solution.
public class A
{
// make sure final value is set here or in constructor
private final Integer index = 0;
public Integer getIndex() { return index; }
public static class B
{
//unimportant
}
//Doesn't make much sense... but...
public class C extends B
{
//can now call getIndex()
public void callGetIndex() {
getIndex();
}
}
}
Bonus research:
For those that are maybe as curious as me and thought about using this to reference the function from another file. If you compile C in another file, and try accessing getIndex by using the enclosing this:
A.this.getIndex();
Sadly that won't work because even though C extends B, it still needs to be enclosed by A for that methodology to work. You get this compile time error:
C.java:5: error: not an enclosing class: A
A.this.getIndex();
^
1 error
Hey cool! another answer, based off #mzl's answer below:
So interestingly enough, You can keep B static and extend both classes to get what you want to do. This is useful for example if you can not edit file A.java, because A.java is 3rd party functionality. (give #mzl credit here for his answer below)
Here is how you'd do it that way! ( Tested this compiles via javac A.java C.java )
A.java
public class A
{
private final Integer index = 0;
public Integer getIndex() { return index; }
public static class B
{
//unimportant
}
}
C.java
public class C extends A
{
public class D extends A.B {
//can now call getIndex()
public void callGetIndex() {
getIndex();
}
}
}
I've created a static over flow project proving #mzl's theory here:
https://github.com/davethomas11/stackoverflow_Q_39441077
One gothcha. You'll notice I create an instance of C before D to make sure there is access to getIndex(). I haven't tested what happens if you instantiate D directly I will do that later and post the results.
Late update on that instantiate D directly test.
I added C.D testD = new C.D(); in my static main function:
$ sh build.sh
StackOverflowQuestion39441077.java:5: error: an enclosing instance that contains C.D is required
C.D testD = new C.D();
^
1 error
The compiler helps us by not letting us do this.
If you want to extend (non-statically) a inner class you must extend the outer class aswell.
You could do it this way:
public class A
{
private final Integer index;
public Integer getIndex() { return index; }
public static class B {}
}
public class D extends A{
public class C extends B{}
}
You can't. C extends B which does not have a getIndex() method. C must extend A to inherit that method.
(I feel it is an interesting theoretical question but with little meaning in practice.)
You can't event access A.getIndex from B because B is static, and getIndex is not, so to invoke getIndex you need a non-null instance of A.
Assuming you could make B non-static, you couldn't either, because your scheme becomes contradictory:
In one hand, class B is inner, so to instantiate a new object a previous non-null instance of A is required:
A a=new A();
B b=a.new B();
But in the other hand, class C is a top-level (not inner) class, so it may be directly instantiated. However, being a subclass of B, it is subject to the same restrictions as its superclass: It needs an instance of A. Contradictory!
The only way I think to make it work is to declare getIndex static, so no instance of A would be needed (in fact, neither subclassing from B would be a problem).
I was told that inheritance is runtime, but I want to ask that if inheritance is runtime then how does compiler generate error at compile time when we try to access parent class data member via child class object:
class PrivateData {
private int x = 50;
void show() {
System.out.println(x);
}
}
class ChildPrivateData extends PrivateData {
public static void main(String s[]) {
ChildPrivateData c1 = new ChildPrivateData();
System.out.println(c1.x);
}
}
Inheritance is most definitely defined at compile time in Java. I think you're confusing it with polymorphism, which, in a nutshell, states that Java chooses which overridden method to run only at runtime.
You are confused with compile time and runtime . I don't touch your code. But see an example here
String result = returnInt(); // #1
public int returnInt() {
return 1;
}
If you see , at line #1 do you think that compiler execute returnInt() method to give a compile time error ? No right?
And the answer is
All the rules already given to Compiler from Specification. It just checks against them.
Inheritence in java is achieved with the "extends" keyword, which is reserved for compile-time inheritence.
In your case you have defined the Base class variable as private.A private member is not inherited. A private member can only be accessed in the child class through some Base class method.
class PrivateData{
private int x =50;
void show(){
System.out.println(x);
}
}
class ChildPrivateData extends PrivateData {
public static void main(String s[]){
ChildPrivateData c1 = new ChildPrivateData();
System.out.println(c1.show());
}
}
inheritance is always achieched at compile time.the code acquires reusability with
extends keyword even before entering into jvm for verification and thus converting to
bytecode,although we can only use its features at run-time after the creation of the object.
and about private member although it will be inherited by the child class but wont be accessible.
what's the meaning of "this.this$0" in this code?
what does it stands for?
I know why we use "this" but I have no idea about "this.this$0"
class MainActivity$1 implements TextWatcher
{
public void afterTextChanged(Editable paramEditable)
{
}
public void beforeTextChanged(CharSequence paramCharSequence, int paramInt1, int paramInt2, int paramInt3)
{
}
public void onTextChanged(CharSequence paramCharSequence, int paramInt1, int paramInt2, int paramInt3)
{
this.this$0.ChangeToNumber(paramCharSequence.toString());
}
}
-----------------------or ----------------------
class MainActivity$2 implements View.OnClickListener
{
public void onClick(View paramView)
{
this.this$0.startActivity(new Intent(this.this$0, about.class));
}
}
this.this$0 it's same to Main.access$0
These mysterious symbols usually correspond to the anonymous inner classes. The Java VM doesn't know about them, only about top-level classes, so the Java compiler provides several workarounds to make inner classes to work.
Local class has implicit reference to the instance of its enclosing class,'this$0' corresponds to this reference in the decompiled code.
JVM prevents classes from accessing privates methods of other classes so the compiler generates several synthetic package-private methods like access$0 in order to access private methods of enclosing instance.
There are many others features of the Java language that are implemented with synthetic methods like generics and covariant return types.
I suggest you to check those links:
Decoding Decompiled Source Code For Android
and : Performance Tips
this$0 normally is for the parent object of a non-static inner class. E.g.,
public class Outer {
class Inner1 {
int f1 = 1;
}
static class Inner2 {
int f1 = 2;
}
public static void main(String[] args) {
Outer o = new Outer();
Outer.Inner1 i1 = o.new Inner1(); //weird but valid
Outer.Inner2 i2 = new Outer.Inner2(); //normal
//wrong: Outer.Inner1 i3 = new Outer.Inner1();
}
}
Normally we define inner class as static. i2 has only 1 field, but i1 has an extra this$0 which points to o.
There's nothing preventing you (beside decent naming conventions) from having an instance member called this$0 and then referring to it with the this keyword.
For example :
public class SomeClass
{
int this$0;
public SomeClass (int val)
{
this.this$0 = val;
}
}
The Java 1.1 Language Specification specifies that the name of a type which is a class member, when transformed into Java 1.0 code for the purpose of generating Java virtual machine bytecodes, consists of the fully qualified name of the inner class, except that each .' character following a class name is replaced by a$'. In addition, each inner class constructor receives the enclosing instance in a prepended argument. Here is how the transformed source code of the FixedStack example might look:
public class FixedStack {
... (the methods omitted here are unchanged)
public java.util.Enumeration elements() {
return new FixedStack$Enumerator(this);
}
}
class FixedStack$Enumerator implements java.util.Enumeration {
private FixedStack this$0; // saved copy of FixedStack.this
FixedStack$Enumerator(FixedStack this$0) {
this.this$0 = this$0;
this.count = this$0.top;
}
int count;
public boolean hasMoreElements() {
return count > 0;
}
public Object nextElement() {
if (count == 0)
throw new NoSuchElementException("FixedStack");
return this$0.array[--count];
}
}
Anyone who has already programmed with Java or C++ adapter classes has written code similar to this, except that the link variables must be manually defined and explicitly initialized in top-level adapter classes, whereas the Java 1.1 compiler creates them automatically for inner classes.
When the Enumerator needs to refer to the top or array fields of the enclosing instance, it indirects through a private link called this$0. The spelling of this name is a mandatory part of the transformation of inner classes to the Java 1.0 language, so that debuggers and similar tools can recognize such links easily. (Most programmers are happily unaware of such names.)
(Note: There is a limitation in some implementations of Java 1.1, under which the initialization of this$0 is delayed until after any superclass constructor is run. This means that up-level references made by a subclass method may fail if the method happens to be executed by the superclass constructor.)
The topic says the most of it - what is the reason for the fact that static methods can't be declared in an interface?
public interface ITest {
public static String test();
}
The code above gives me the following error (in Eclipse, at least): "Illegal modifier for the interface method ITest.test(); only public & abstract are permitted".
There are a few issues at play here. The first is the issue of declaring a static method without defining it. This is the difference between
public interface Foo {
public static int bar();
}
and
public interface Foo {
public static int bar() {
...
}
}
The first is impossible for the reasons that Espo mentions: you don't know which implementing class is the correct definition.
Java could allow the latter; and in fact, starting in Java 8, it does!
The reason why you can't have a static method in an interface lies in the way Java resolves static references. Java will not bother looking for an instance of a class when attempting to execute a static method. This is because static methods are not instance dependent and hence can be executed straight from the class file. Given that all methods in an interface are abstract, the VM would have to look for a particular implementation of the interface in order to find the code behind the static method so that it could be executed. This then contradicts how static method resolution works and would introduce an inconsistency into the language.
I'll answer your question with an example. Suppose we had a Math class with a static method add. You would call this method like so:
Math.add(2, 3);
If Math were an interface instead of a class, it could not have any defined functions. As such, saying something like Math.add(2, 3) makes no sense.
The reason lies in the design-principle, that java does not allow multiple inheritance. The problem with multiple inheritance can be illustrated by the following example:
public class A {
public method x() {...}
}
public class B {
public method x() {...}
}
public class C extends A, B { ... }
Now what happens if you call C.x()? Will be A.x() or B.x() executed? Every language with multiple inheritance has to solve this problem.
Interfaces allow in Java some sort of restricted multiple inheritance. To avoid the problem above, they are not allowed to have methods. If we look at the same problem with interfaces and static methods:
public interface A {
public static method x() {...}
}
public interface B {
public static method x() {...}
}
public class C implements A, B { ... }
Same problem here, what happen if you call C.x()?
Static methods are not instance methods. There's no instance context, therefore to implement it from the interface makes little sense.
Now Java8 allows us to define even Static Methods in Interface.
interface X {
static void foo() {
System.out.println("foo");
}
}
class Y implements X {
//...
}
public class Z {
public static void main(String[] args) {
X.foo();
// Y.foo(); // won't compile because foo() is a Static Method of X and not Y
}
}
Note: Methods in Interface are still public abstract by default if we don't explicitly use the keywords default/static to make them Default methods and Static methods resp.
There's a very nice and concise answer to your question here. (It struck me as such a nicely straightforward way of explaining it that I want to link it from here.)
It seems the static method in the interface might be supported in Java 8, well, my solution is just define them in the inner class.
interface Foo {
// ...
class fn {
public static void func1(...) {
// ...
}
}
}
The same technique can also be used in annotations:
public #interface Foo {
String value();
class fn {
public static String getValue(Object obj) {
Foo foo = obj.getClass().getAnnotation(Foo.class);
return foo == null ? null : foo.value();
}
}
}
The inner class should always be accessed in the form of Interface.fn... instead of Class.fn..., then, you can get rid of ambiguous problem.
An interface is used for polymorphism, which applies to Objects, not types. Therefore (as already noted) it makes no sense to have an static interface member.
Java 8 Had changed the world you can have static methods in interface but it forces you to provide implementation for that.
public interface StaticMethodInterface {
public static int testStaticMethod() {
return 0;
}
/**
* Illegal combination of modifiers for the interface method
* testStaticMethod; only one of abstract, default, or static permitted
*
* #param i
* #return
*/
// public static abstract int testStaticMethod(float i);
default int testNonStaticMethod() {
return 1;
}
/**
* Without implementation.
*
* #param i
* #return
*/
int testNonStaticMethod(float i);
}
Illegal combination of modifiers : static and abstract
If a member of a class is declared as static, it can be used with its class name which is confined to that class, without creating an object.
If a member of a class is declared as abstract, you need to declare the class as abstract and you need to provide the implementation of the abstract member in its inherited class (Sub-Class).
You need to provide an implementation to the abstract member of a class in sub-class where you are going to change the behaviour of static method, also declared as abstract which is a confined to the base class, which is not correct
Since static methods can not be inherited . So no use placing it in the interface. Interface is basically a contract which all its subscribers have to follow . Placing a static method in interface will force the subscribers to implement it . which now becomes contradictory to the fact that static methods can not be inherited .
With Java 8, interfaces can now have static methods.
For example, Comparator has a static naturalOrder() method.
The requirement that interfaces cannot have implementations has also been relaxed. Interfaces can now declare "default" method implementations, which are like normal implementations with one exception: if you inherit both a default implementation from an interface and a normal implementation from a superclass, the superclass's implementation will always take priority.
Perhaps a code example would help, I'm going to use C#, but you should be able to follow along.
Lets pretend we have an interface called IPayable
public interface IPayable
{
public Pay(double amount);
}
Now, we have two concrete classes that implement this interface:
public class BusinessAccount : IPayable
{
public void Pay(double amount)
{
//Logic
}
}
public class CustomerAccount : IPayable
{
public void Pay(double amount)
{
//Logic
}
}
Now, lets pretend we have a collection of various accounts, to do this we will use a generic list of the type IPayable
List<IPayable> accountsToPay = new List<IPayable>();
accountsToPay.add(new CustomerAccount());
accountsToPay.add(new BusinessAccount());
Now, we want to pay $50.00 to all those accounts:
foreach (IPayable account in accountsToPay)
{
account.Pay(50.00);
}
So now you see how interfaces are incredibly useful.
They are used on instantiated objects only. Not on static classes.
If you had made pay static, when looping through the IPayable's in accountsToPay there would be no way to figure out if it should call pay on BusinessAcount or CustomerAccount.