Following interface and classes are successfully compiled.
Problem is mentioned in the output below :
interface MyInterface{}
class MyClass implements MyInterface{}
class InterDoubt{
static MyInterface mi ;//= new MyClass() ;
public static void main(String[] args){
System.out.println("X") ;
try{
synchronized(mi){
try{
mi.wait(4000) ;
}
catch(InterruptedException ie){
System.out.println("Exception occured at main.") ;
}
}
}
catch(Exception e){
System.out.println("voilla, MyInterface is an interface,\n" +
"then why compiler allows compilation of\n" +
"mi.getClass(), mi.wait().\n" +
"Or how the methods of Object class are available in an interface."
);
}
System.out.println("Y") ;
}
}
output :
X
voilla, MyInterface is an interface,
then why compiler allows compilation of
mi.getClass(), mi.wait().
Or how the methods of Object class are available in an interface.
Y
Edited :-
I am accepting answer from disown, as it's the most explanatory. But after reading the answer, one more issue get's populated :-
"Remember if the interface tries to declare a public instance method declared 'final' in the Object class then it'll result into a compile-time error. For example, 'public final Class getClass()' is a public instance method declared 'final' in the Object class and therefore if an interface tries to declare a method with this signature then the compilation will fail" (Quoted from explanation).
then why the following code is getting successfully compiled :-
interface MyInter{
public void method() ;
}
class MyClass implements MyInter{
public final void method() {
.......
.......
.......
}
}
What you are correctly pointing out as an exception is specified in the Java Language Specification. Interfaces will automatically get all members from the class java.lang.Object added. From here:
The Java Language Specification clearly says that the members of an interface are those which are declared in the interface and those which are inherited from direct super interfaces. If an interface has no direct superinterface then the interface implicitly declares a public abstract member method corresponding to each public instance method declared in the Object class, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by that interface. This is what makes the signatures of the Object methods available to the compiler and the code compiles without any error. Remember if the interface tries to declare a public instance method declared 'final' in the Object class then it'll result into a compile-time error. For example, 'public final Class getClass()' is a public instance method declared 'final' in the Object class and therefore if an interface tries to declare a method with this signature then the compilation will fail.
At run time there should be a real object (or null) behind the reference mi. The real type will implement this interface hence the compiler allows it. At run time any type that implements that interface could be there.
Yes, all Object's methods are available to everything but Primitive value. Interface objects are still objects so they have Object's methods.
The cast (Object)mi will always succeed so why should you be required to provide it?
The Java Language Specification clearly says that the members of an interface are those which are declared in the interface and those which are inherited from direct super interfaces. If an interface has no direct superinterface then the interface implicitly declares a public abstract member method corresponding to each public instance method declared in the Object class, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by that interface.
Related
I'd like to store a class object in a local variable and then call its static methods. Also, the class object should expect descendant types:
class Ancestor {
static void staticMethod() {
}
}
class Descendent extends Ancestor {
}
(...)
Class<? extends Ancestor> fool = Descendent.class;
fool.staticMethod() //compilation error 'cannot resolve symbol'
How would you guys solve this?
There are multiple errors in you question, but I give you that what comes closest to an answer. First of all be aware that your using default visibility which is package. So the method can only be seen by classes in the same package.
The following snippet from you is not valid:
Class<Ancestor> fool = Descendent.class;
A valid version would be:
Class<? extends Ancestor> fool = Descendant.class;
Related to the static method invocation. You cannot invoke static methods of a class with just the class object. It is possible to invoke the method via reflection.
This could look like the following:
fool.getDeclaredMethod("staticMethod").invoke(null);
There are two special behaviors in that case.
static methods will be invoked with null as object argument
It does only work on the class object declaring the static method and not for classes extending the class with the static method.
I am trying to use javassist to programatically create and compile a class (at runtime) that implements an interface.
I get the following Error whenever I invoke an instance of that dynamic class:
java.lang.AbstractMethodError: FooImpl.test()Ljava/lang/Object;
Here's my interface
public class FooBarInterface<T> {
public T getEntity();
}
Here's a sample Entity
public class FooEntity {
#Override
public String toString() {
return "Hello, Foo!";
}
}
Here's how I programatically implement the interface
public void test() {
ClassPool classPool = ClassPool.getDefault();
CtClass testInterface = classPool.get(FooBarInterface.class.getName());
CtClass fooImpl = classPool.makeClass("FooImpl");
fooImpl.addInterface(testInterface);
CtMethod testMethod = CtNewMethod.make(
"public com.test.FooEntity getEntity(){" +
"return new com.test.FooEntity();" +
"}",
canImpl
);
fooImpl.addMethod(testMethod);
fooImpl.writeFile();
TestInterface<FooEntity> test =
(TestInterface<FooEntity>) fooImpl.toClass().newInstance();
System.out.println(test.getEntity());
}
If I changed the return type of the implemented method to Object, then I don't get the Error, like this:
CtMethod testMethod = CtNewMethod.make(
"public Object getEntity(){" +
"return new com.test.FooEntity();" +
"}",
canImpl
);
Then I successfully get the hello, Foo!. I am OK with changing the return type to Object, but I'd like to understand more why returning with type Foo produces AbstractMethodError.
Inside the JVM, methods with different return types are distinct. After type erasure, FooBarEntity.getEntity() has return type Object. Calls via the interface will look specifically for a method with return type Object, hence why your implementation must return Object.
Normally, your Java compiler will create bridge methods that forward the result of the concrete method as the erased type, but apparently Javassist doesn't do this for you (I haven't used Javassist so I'm not sure).
For more on how bridge methods are used to implement type erasure, see the official Java Tutorials topic on bridge methods.
I was having same error. I had a base class in which I declared a new abstract method. I implemented that method on the other classes that were consuming it. Now on debugging I was getting Abstract method error as soon as I was hitting implementation of the method.
Solution-:
I figured that base class been consumed by other artifacts too and I didn't overrode newly created abstract method in those artifacts. Since I never build them as I was not changing them, JVM never throws compile time error but on run time exception occurs.
On implementing method in other artifacts I was able to get rid of the exception.Basically in my case all child classes didn't have implementation of base class's abstract method.
When you have a parameterized parameter or return type, the Java compiler compiles it as though it was Object and synthesizes a bridge method with the parameterized signature that calls the other one. Or possibly the other way around. You've only synthesized one of them, not both.
I have the following setup of classes/interfaces.
Interface IFoobar
Class BaseClass which implements IFoobar and is abstract
Class ConcreteClassA which extends BaseClass
Class ConcreteClassB which extends BaseClass
Class ConcreteClassC which extends BaseClass
I have a method for which I need to pass instances of java.lang.Class for the above concrete classes. I am declaring it like so.
void doSomething(String id, Class<IFoobar> c)
However, when I try to compile, java complains with an error more or less like this:
doSomething(java.lang.String,java.lang.Class<IFoobar>) in javaclass cannot be applied to
(java.lang.String,java.lang.Class<ConcreteClassA>)
register("12345", ConcreteClassA.class);
^
1 error
I've only recently needed to use java.lang.Class to do things, so I am guessing I am missing something simple. I would have expected the typed class declaration to work like normal parameters in that the concrete classes are recognized as instances of the interface, but this apparently isn't the case.
I've tried various methods of casting, etc and either not had the desired results, or had code which isn't valid. So any ideas as to what I need to do would be appreciated.
Thanks in advance.
A variable of type Class<IFoobar> can only hold a reference to a Class<IFoobar> object, not a Class<ConcreteClassA> object.
Change Class<IFoobar> to Class<? extends IFoobar>.
This behaviour is not particularly sensible for Class objects. It is much more logical for collections, where it stops you doing this:
void method1(List<IFoobar> list)
{
list.add(new ConcreteClassA());
}
void method2()
{
List<ConcreteClassB> list = /* something */;
method1(list);
// oops! we put a ConcreteClassA inside a List<ConcreteClassB>
}
the only accepted value for Class<IFoobar> is IFooBar.class. If you want to accept IFooBar.class and all its subclasses, you should use Class<? extends IFooBar>
The error has nothing to do with "Class"
Simply if you use
ArrayList<Object> x = new ArrayList<String>();
You get error: incompatible types
because, though the String class is a subclass of Object, ArrayList<Object> is a different type than ArrayList<String>. That is the nature of Generics.
You can use
void doSomething(String id, Class c)
Consider this case:
public class SomeClass {
public void someMethod() {
new SomeInterface() {
public void someOtherMethod() {
new SomeOtherInterface() {
new someThirdMethod() {
//My question is about code located here.
}
};
}
};
}
}
Is there a syntax to reference the instance of the anonymous inner class represented by SomeInterface at the commented code? For SomeClass you can do SomeClass.this Is there an equivalent to get the implementation of SomeInterface?
If not, of course you can just define a final local variable in the SomeInterface implementation and reference it, but I was just wondering if there is in fact direct language support to reference the instance.
The reason why SomeInterface.this doesn't compile is because the enclosing class is not SomeInterface, but rather some anonymous type.
You can't use qualified this with anonymous type. That's why they're anonymous; you can't refer to them by name, and qualified this works by explicitly naming an enclosing type.
It's tempting to try something like:
SomeClass$1.this
But then you get an error SomeClass$1 cannot be resolved to a type; despite the fact that if you let this code compile without this line, it will (in all likelihood) create a SomeClass$1.class.
You can either use a non-anonymous class and use qualified this, or you can use the final local variable technique you mentioned.
References
JLS 15.8.4 Qualified this
Suppose you have a generic interface and an implementation:
public interface MyInterface<T> {
void foo(T param);
}
public class MyImplementation<T> implements MyInterface<T> {
void foo(T param) {
}
}
These two types are framework types I provide. In the next step I want allow users to extend that interface as well as redeclare foo(T param) to maybe equip it with further annotations.
public interface MyExtendedInterface extends MyInterface<Bar> {
#Override
void foo(Bar param);
// Further declared methods
}
I create an AOP proxy for the extended interface and intercept especially the calls to furtherly declared methods. As foo(…) is now redeclared in MyExtendedInterface I cannot execute it by simply invoking MethodInvocation.proceed() as the instance of MyImplementation only implements MyInterface.foo(…) and not MyExtendedInterface.foo(…).
So is there a way to get access to the method that declared a method initially? Regarding this example is there a way to find out that foo(Bar param) was declared in MyInterface originally and get access to the accoriding Method instance?
I already tried to scan base class methods to match by name and parameter types but that doesn't work out as generics pop in and MyImplementation.getMethod("foo", Bar.class) obviously throws a NoSuchMethodException. I already know that MyExtendedInterface types MyInterface to Bar. So If I could create some kind of "typed view" on MyImplementation my math algorithm could work out actually.
Additional info:
I create the proxy for the MyExtendedInterface as follows:
ProxyFactory factory = new ProxyFactory();
factory.setTarget(new MyImplementation());
factory.setInterfaces(new Class[] { MyExtendedInterface.class });
factory.addInterceptor(new MyInterceptor(MyExtendedInterface.class));
The interceptor pretty much scans the methods and executes JPA queries for all methods declared in MyExtendedInterface but routes all method invocations of methods declared in MyInterface to the proxy target. This works as long as methods from MyInterface are not redeclared as the target then doesn't implement it anymore.
public class MyInterceptor implements MethodInterceptor {
public Object invoke(final MethodInvocation invocation)
throws Throwable {
// handling of query methods
// else
invocation.proceed();
// ^^ works if not redeclared but not if
}
}
So what I would like to do instead of invocation.proceed() is detect the method that originally declared the one being invoked and invoke that on the target manually.
Okay, here's the solution I came up with: As I know the base class and it generics structure (what T means in this case) as well as MyExtendedInterface types MyInterface to Bar I can scan the base implementation for possible matches as follows (pseudocode):
for all methods {
skip those with non matching name and parameters length;
for all generic parametertypes {
if typename = T then concrete type has to be Bar
...
}
}
I don't need a generic solution in this case so that seems to work.
The whole scenario seems strange. You can't apply AOP declared on MyExtendedInterface to MyImplementation, because it does not implement it.
Second, I don't understand why it matters which interface defines a method, since it is the implementation that the method is invoked on.
Apart from that, you can get all the methods declared by a certain class/interface by getDeclaredMethods(). Then you can iterate on them and find something that matches your criteria (name)