I am playing around with aop and aspectj and discovered an (for me) unexpected behavior.
In the aspectj-docs I found the following example-pointcut:
execution(public void Middle.*())
for the following class-definitions (I slightly changed the original example):
class Super {
public void m() { ... }
}
class Middle extends Super {
}
class Sub extends Middle {
#Override
public void m() { ... }
}
The description of that exmaple states:
[The pointcut] picks out all method executions for public methods returning void and having no arguments that are either declared in, or inherited by, Middle, even if those methods are overridden in a subclass of Middle.
This example is working fine for me but if class Sub is not overriding m(), the method-calls from outside to m on a Sub-instance are not intercepted. Doesn't this violates the doc?
I had another problem with pointcuts in inhertied classes which is caused by the use of proxies. But in this case the use of a proxy cannot cause this behavior because the proxy should provide methods for all of the proxied class. Or did I missed something?
my aspect-definition:
#Aspect
public class MyAspect {
#Before(value = "execution(* Middle.*(..))", argNames="joinPoint")
public void myAdvice(JoinPoint joinPoint) {
System.out.println("adviced: " + joinPoint.getSignature());
}
}
Related
Which access modifier, in an abstract class, do I have to use for a method,
so the subclasses can decide whether it should be public or not? Is it possible to "override" a modifier in Java or not?
public abstract class A {
??? void method();
}
public class B extends A {
#Override
public void method(){
// TODO
}
}
public class C extends B {
#Override
private void method(){
// TODO
}
}
I know that there will be a problem with static binding, if
someone calls:
// Will work
A foo = new B()
foo.method();
// Compiler ?
A foo = new C();
foo.method();
But maybe there is another way. How I can achieve that?
It is possible to relax the restriction, but not to make it more restrictive:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method(){ // OK
}
}
public class C extends A {
#Override
private void method(){ // not allowed
}
}
Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.
I would recommend using interfaces to selectively expose or hide the method:
public interface WithMethod {
// other methods
void method();
}
public interface WithoutMethod {
// other methods
// no 'method()'
}
public abstract class A {
protected void method();
}
public class B extends A implements WithMethod {
#Override
public void method(){
//TODO
}
}
public class C extends B implements WithoutMethod {
// no 'method()'
}
... then only work with the instances through the interfaces.
When overriding methods, you can only change the modifier to a wider one, not vice versa. For example this code would be valid:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method() { }
}
However, if you try to narrow down the visibility, you'd get a compile-time error:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
private void method() {}
}
For your case, I'd suggest to make C not implementing A, as A's abstraction implies that there's a non-private method():
public class C {
private void method(){
//TODO
}
}
Another option is to make the method() implementation in C throwing a RuntimeException:
public class C extends A {
#Override
public void method(){
throw new UnsupportedOperationException("C doesn't support callbacks to method()");
}
}
What you are asking for is not possible for very good reasons.
The Liskov substitution principle basically says: a class S is a subclass of another class T only then, when you can replace any occurrence of some "T object" with some "S object" - without noticing.
If you would allow that S is reducing a public method to private, then you can't do that any more. Because all of a sudden, that method that could be called while using some T ... isn't available any more to be called on S.
Long story short: inheritance is not something that simply falls out of the sky. It is a property of classes that you as the programmer are responsible for. In other words: inheritance means more than just writing down "class S extends T" in your source code!
This is impossible because of the polymorphism. Consider the following. You have the method in class A with some access modifier which is not private. Why not private? Because if it was private, then no other class could even know of its existence. So it has to be something else, and that something else must be accessible from somewhere.
Now let's suppose that you pass an instance of class C to somewhere. But you upcast it to A beforehand, and so you end up having this code somewhere:
void somewhereMethod(A instance) {
instance.method(); // Ouch! Calling a private method on class C.
}
One nice example how this got broken is QSaveFile in Qt. Unlike Java, C++ actually allows to lower access privileges. So they did just that, forbidding the close() method. What they ended up with is a QIODevice subclass that is not really a QIODevice any more. If you pass a pointer to QSaveFile to some method accepting QIODevice*, they can still call close() because it's public in QIODevice. They “fixed” this by making QSaveFile::close() (which is private) call abort(), so if you do something like that, your program immediately crashes. Not a very nice “solution”, but there is no better one. And it's just an example of bad OO design. That's why Java doesn't allow it.
Edit
Not that I missed that your class is abstract, but I also missed the fact that B extends C, not A. This way what you want to do is completely impossible. If the method is public in B, it will be public in all subclasses too. The only thing you can do is document that it shouldn't be called and maybe override it to throw UnsupportedOperationException. But that would lead to the same problems as with QSaveFile. Remember that users of your class may not even know that it's an instance of C so they won't even have a chance to read its documentation.
Overall it's just a very bad idea OO-wise. Perhaps you should ask another question about the exact problem you're trying to solve with this hierarchy, and maybe you'll get some decent advises on how to do it properly.
Here is a part of the #Override contract.
The answer is : there isn't any possibility to achieve what you have.
The access level cannot be more restrictive than the overridden
method's access level. For example: if the superclass method is
declared public then the overridding method in the sub class cannot be
either private or protected.
This is not a problem concerning abstract classes only but all classes and methods.
THEORY:
You have the determined modifiers order:
public <- protected <- default-access X<- private
When you override the method, you can increase, but not decrease the modifier level. For example,
public -> []
protected -> [public]
default-access -> [public, default-access]
private -> []
PRACTICE:
In your case, you cannot turn ??? into some modifier, because private is the lowest modifier and private class members are not inherited.
This question already has answers here:
Explicitly calling a default method in Java
(6 answers)
Closed 8 years ago.
In java 8 I have something like this:
package test;
public class SimpleFuncInterfaceTest {
public static void carryOutWork(AFunctionalInterface sfi){
sfi.doWork();
}
public static void main(String[] args) {
carryOutWork(() -> System.out.println("Do work in lambda exp impl..."));
AImplementor implementsA = new AImplementor();
//carryOutWork(() -> implementsA.doWork());
BImplementor implementsB = new BImplementor();
carryOutWork(() -> implementsB.doWork());
}
}
#FunctionalInterface
interface AFunctionalInterface {
public void doWork();
default public void doSomeWork(){
System.out.println("FOO");
}
}
#FunctionalInterface
interface BFunctionalInterface extends AFunctionalInterface {
#Override
default public void doSomeWork(){
System.out.println("BAR");//Unreachable in same object?
}
}
class AImplementor implements AFunctionalInterface {
#Override
public void doWork() {
doSomeWork();
}
}
class BImplementor extends AImplementor implements BFunctionalInterface {
public void doSomeWork(){
super.doSomeWork();
new BFunctionalInterface(){
#Override
public void doWork() {
}}.doSomeWork();
System.out.println("WUK WUK");
}
#Override
public void doWork() {
doSomeWork();
}
}
Is there a way to call the default functional interface behavior from implementsB without having to create an anonymous inner class and invoking that?
That has a side effect (calling implementsA's method 2 times), what is desired is a call to the parent's implementation, and then have the childs implementation be able to call the child's default implementation, along with some specialization if needed. As you can see calling the parent's implementation is dead easy, but I don't see a way to avoid re-writing the default implementation unless I add a layer of indirection to the class that implements the child interface, and no way to enforce that.
For instance if A unlocked or provided access to a resource say a database, and B unlocks a second resource (another database), I see no way to make code unlock A and then B enforcing this contract through the use of Functional Interfaces, requiring that A and B be called. One level deep you can do it, but N levels deep looks like it's not possible.
I intended to use lambdas to avoid making expensive calls but to enforce a semantic order of operations on users of my library.
This question is not quite the same as "Explicitly calling a default method in Java", as this question is about interfaces N levels deep, not just calling a parent interfaces default method.
You can invoke an inherited interface default method using InterfaceName.super. The rules are the same as for other super method invocations: You can invoke the inherited method that you have overridden, but you can’t directly invoke the method which the inherited method might have overridden. E.g.
interface A
{
void foo();
default void toOverride() {
System.out.println("A");
}
}
interface B extends A
{
default void toOverride() {
A.super.toOverride();
System.out.println("B");
}
}
interface C extends B
{
default void toOverride() {
A.super.toOverride();// does not work
B.super.toOverride();
System.out.println("B");
}
}
class D implements B
{
public void toOverride() {
}
public void foo() {
D.this.toOverride();
B.super.toOverride();
A.super.toOverride(); // does not work!
}
}
But if each overriding method invokes its super method you have a chain of invocations. However, keep in mind that we are talking about interfaces. An implementation can always override a default method without invoking super at all.
Given this class:
abstract class Foo{
public Foo(){...}
public abstract void checkable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
Is there any code I can put in Foo's constructor to make calledWhenCheckableIsCalled get called when checkable is called?
Note: This is a gross simplification of an actual project I am working on.
Edit: I have already implemented a template pattern workaround. I just wondered if there was another way to do this I am missing. (Perhaps using reflection.)
Looks like a template method pattern.
But then you must implement Foo.checkable() and introduce another abstract method to delegate to.
abstract class Foo{
public Foo(){}
public void checkable(){
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
I would also suggest to make checkable() final in this case so that you can be sure that checkable() can not implemented in another way as you expected.
In addition to Brian Roach's comment
The downside is that the protected can be expanded to public in the subclass, so you can't explicitly enforce it.
That's true, but you can prevent a Foo instance from being instantiated if a subclass increases the visibility of doCheckable. Therefore you have to introduce a verification whenever an object is instantiated. I would recommend to use an initializer code so that the verification is executed on every constructor that exists. Then it can not be forgotten to invoke and therefore be by-passed.
For example:
abstract class Foo {
{ // instance initializer code ensures that enforceDoCheckableVisibility
// is invoked for every constructor
enforceDoCheckableVisibility();
}
public Foo() {...}
public Foo(Object o) {...}
private void enforceDoCheckableVisibility() {
Class<?> currentClass = getClass();
while (currentClass != Foo.class) {
try {
Method doCheckableMethod = currentClass.getDeclaredMethod("doCheckable");
if (Modifier.isPublic(doCheckableMethod.getModifiers())) {
throw new RuntimeException("Visibility of "
+ currentClass.getSimpleName()
+ ".doCheckable() must not be public");
}
} catch (SecurityException | NoSuchMethodException e) {}
currentClass = currentClass.getSuperclass();
}
}
}
Since the check is implemented using reflection the downside is that it is only checked at runtime. So you will not have compiler support of course. But this approach let you enforce that an instance of a Foo can only exist if it fulfills your contract.
No, the constructor will get invoked once during the object initialisation. You can however get your subclass that provides the implementation to call the method in the super class:
class Bar extends Foo {
// implementation of abstract method
public void checkable(){
super.calledWhenCheckableIsCalled(); // call to parent's method
...
}
}
EDIT
You could achieve this with aspects. Using an aspect you can intercept each call to a method by referring to the abstract parent method. This leaves you free from interfering eith the child code. Your calledWhenCheckableIsCalled code would then become part of the intercepting code.
abstract class Foo {
// use pointcut to intercept here
public void checkable();
}
There is no way as you are forcing that method to implement in child.
An awkward suggestion will be know from child implementation. I mean there is no clean way AFAIK
abstract class foo {
public abstract void bar();
public void moo() {
System.out.println("some code");
this.bar();
System.out.println("more code");
}
}
now if moo is called, the underlying implementation of bar will be used, it is just a small paradigm shift from what you want.
so your end user would call moo instead of bar, but he still needs to implement bar
Nope, an abstract method doesn't have a body. You could, however, chain your method like this:
abstract class Foo {
void callMeInstead() {
// do common
callMeImplementation();
}
abstract void callMeImplementation();
}
It looks to me like you're looking for the template pattern:
public abstract class Template {
public final void checkable() {
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
private void calledWhenCheckableIsCalled() {
System.out.println("checkable was called");
}
}
Now, each time checkable() is called, calledWhenCheckableIsCalled() is also called. And the suclass must still provide the actual implementation of checkable(), by implementing the doCheckable() method.
Note that making checkable() final prevents a subclass from overriding it and thus bypassing the call to calledWhenCheckableIsCalled().
I'm using Guice to make an interceptor for all methods in one class except the ones annotated with a specific class I created:
Here's the AbstractModule:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bindInterceptor(
Matchers.subclassesOf(MyFacade.class),
Matchers.not(Matchers.annotatedWith(DAO.class)),
new MyInterceptor());
}
}
Now, is it possible to make my MethodInterceptor ignore all methods in MyFacade when they are called by another method in the same class (MyFacade)?
For example:
public class MyFacade{
#DAO
public void doSomething(){
...
}
public void a(){
...
b();
}
public void b(){
...
}
}
I don't want that the interceptor intercepts the call from method a() to method b().
Thanks!
There's no easy way for the intercepted to know which class is calling it. Also, under most circumstances, you would expect a call to b() to run the intercepted method—such as ensuring a DB transaction is opened and closed appropriately. If you need to ensure that interception only occurs on external calls, you'll have to be a little clever.
Option 1: Rewrite the interceptor to keep state
Consider rewriting your MethodInterceptor to have a guard checking whether it's in the middle of an intercepted method. Remember, bindInterceptor accepts instances, so if it comes to it you can keep call stack state in there. This is unusual—interceptors are typically assumed to be stateless—so document it well.
/**
* Prevents internal interceptor calls from within intercepted methods.
* Not thread safe.
*/
public abstract class GuardedInteceptor implements MethodInterceptor {
private boolean executionInProgress = false;
/** No-op if in the middle of an intercepted method. */
public Object invoke(MethodInvocation invocation) throws Throwable {
if (executionInProgress) {
return invocation.proceed();
}
executionInProgress = true;
Object returnValue = null;
try {
runBefore();
returnValue = invocation.proceed();
runAfter();
} finally {
executionInProgress = false;
}
return returnValue;
}
protected abstract void runBefore();
protected abstract void runAfter();
}
Option 2: Rewrite the intercepted class to delegate to a private method
In your situation I would have b() delegate to private method bInternal() and call that instead of b() from within MyFacade. Guice AOP can't intercept private methods, so you don't need to worry about annotating or configuring anything else. This also allows the individual systems to choose whether to call the possibly-overridden-or-intercepted public methods or the effectively-final, predictable private methods. AOP interception is implemented through inheritance, so the standard rules about designing and documenting for inheritance apply here.
This is my scenario "I have a abstract class. There are many derived classed extending this abstract class with the use of annotations. In addition, I have a method of abstract class, that was reflected all notations in one particular derived class".
// Here's a definition of annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface SampleAnnotation {
int sample();
}
public abstract class A {
// Here's a method to reflect all annotations
// in particular derived class like B or C
#Override
public void foo() {
}}
public class B extends A {
#SampleAnnotation (sample = 1)
public void step1() {}
#SampleAnnotation (sample = 2)
public void step2() {}
}
public class C extends A {
#SampleAnnotation (sample = 1)
public void step1() {}
#Sample (stage = 2)
public void step2() {}
}
How can I use java reflection to reflect all the annotations in specific derived class like B or C ?
Perhaps what you have in mind is this Reflections library.
Using Reflections you can query your metadata such as:
get all subtypes of some type
get all types/methods/fields annotated with some annotation, w/o annotation parameters matching
get all resources matching matching a regular expression
It depends:
Do you want to get all method annotations of a concrete class
Do you want to get all method annotations of all concrete classes
The first one can be achieved with a method implementation of foo like this:
public void foo() {
for (Method method : this.getClass().getDeclaredMethods()) {
for (Annotation a : method.getAnnotations()) {
// do something with a
}
}
}
Then you can invoke foo from your concrete class, for instance:
new B().foo();
For the second case you will need to do class path scanning as Peter Lawrey has pointed out.