Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Final Classes

Ron,

	In first place, thanks for you answer. Now, to answer your question:

		- I have been reading the book "The Java Programming Language - 4th 
Edition", in which the authors appeal to the programmers not to use public, 
protected or packaged methods inside the classes constructores, except in the 
cases in which the class is final. To illustrate why this is adviced, there 
is an example, similar to the following:

public class Test {
        private int first;

        public Test(){
               changeValue();
        }

        public void changeValue(){
                first = 1;
        }

        public int getFirst(){
                return first;
        }

        public static void main(final String[] args) {
                final ExtTest test = new ExtTest();
                System.out.println("first: " + test.getFirst());
                System.out.println("extended: " + test.getExtended());
        }
}

class ExtTest extends Test {
        private int extended;

        public void changeValue(){
                extended = 2;
        }

        public int getExtended(){
                return extended;
        }
}

When one runs the previous code, the result is 0 instead of the expected 1. 
The book authors also tell that is important to document such things because 
they are dangerous. So, what I was trying to do was to create an Aspect that 
would prevent this from happening. What I did was the following (which seems 
to work but only using Annotations):

My BaseClass class which is not final and so, it shouldn't be allowed to call 
public, protected and packaged methods in the constructor:

public class BaseClass {

	private int variable;

	public BaseClass() {
		// it results in a compile error
		// changeVariable();
	}

	public void changeVariable() {
		variable = 1;
	}

	public int getVariable() {
		return variable;
	}
}

My ExtendedClass class which is final and so, there isn't the same problem as 
the previous one:

public class ExtendedClass extends BaseClass {

	private int extendedVariable;

	@FinalClass
	public ExtendedClass() {
		// it's not a compile error because ot the Annotation
		changeVariable();
	}

	@Override
	public void changeVariable() {
		extendedVariable = 2;
	}
}

Here's the Aspect:

public aspect ConstructorsPolicyAspect {

	pointcut privateMethods() : call(private * 
pt.zenida.paulo.constructores..*.*(..));

	pointcut protectedMethods() : call(protected * 
pt.zenida.paulo.constructores..*.*(..));

	pointcut publicMethods() : call(public * 
pt.zenida.paulo.constructores..*.*(..));

	pointcut packagedMethods() : !privateMethods() && !protectedMethods() 
&& !publicMethods();

	pointcut markedFinalClasses() : execution(@FinalClass 
pt.zenida.paulo.constructores.policy.ExtendedClass.new(..));

	pointcut forbiddenCalls() :
		withincode(pt.zenida.paulo.constructores..*.new(..)) &&
		!withincode(@FinalClass *.new(..)) &&
		(publicMethods() || protectedMethods());

	declare error : forbiddenCalls() :
		"You should't call protected, packaged ou public methods inside a 
constructor for a non final class";
}

Following, there is the testing code:

public class Test {

	public static void main(String args[]) {
		BaseClass bc = new ExtendedClass();
		System.out.println(bc.getVariable());
	}
}

Best regards,

	Paulo Zenida

Em Sexta, 23 de Dezembro de 2005 15:12, o Ronald R. DiFrango escreveu:
> Paulo,
>
> I do not think there is a way to capture the fact that a class itself is
> final directly.  The only way I can think that you MAY be able to do this
> capture the constructor as you have it now and use reflection to determine
> if the class is final or not.  May I ask why you would want to do such a
> thing?
>
> I will defer final answer to aspectj guys because obviously they know
> better than I.
>
> Ron
>
> On 12/23/05, Paulo Alexandre Corigo Zenida <paulo.zenida@xxxxxxxx> wrote:
> > Ron,
> >
> >        I suppose I didn't explain myself quite well. You are absolutely
> > right about
> > what you've just said. Actually, what I was trying to do is something
> > else:
> > I'm trying to capture the class itself being final, not its constructor
> > being
> > final. The source code I have put here was just to simplify but I guess
> > it wasn't well chosen. I would like to do something like the following:
> >
> > // The following does not compile
> > pointcut finalClasses() : call(* (final *.*)(..))
> > && !within(DetectFinalClassesAspect);
> >
> > Is there a way to see if a class is declared as final?
> >
> > Best regards,
> >
> >        Paulo Zenida
> >
> > Em Sexta, 23 de Dezembro de 2005 14:30, o Ronald R. DiFrango escreveu:
> > > Paulo,
> > >
> > > Just remove the final from your advice and you should be good to go. 
> > > At least I was.  Here is what it should look like:
> > >
> > >   pointcut finalClasses() : execution(*.new(..)) &&
> > > !within(DetectFinalClassesAspect);
> > >
> > > The reason this fails is that final as a modifier is not allowed on a
> > > constructor, therefore aspectj can not pick it up.
> > >
> > > Ron
> > >
> > > On 12/23/05, Paulo Alexandre Corigo Zenida <paulo.zenida@xxxxxxxx>
> >
> > wrote:
> > > > Good morning,
> > > >
> > > >        I was trying to capture calls to the constructores of a final
> > > > class with the
> > > > following example but I couldn't do so. Am I doing something wrong or
> > > > isn't
> > > > possible to capture final classes? In the case of not being possible
> >
> > to
> >
> > > > capture final classes, could someone tell me why, please?
> > > >
> > > > Here's my final class:
> > > >
> > > > final public class FinalClass {
> > > >
> > > >        public void foo() {
> > > >                System.out.println("FinalClass.foo()");
> > > >        }
> > > > }
> > > >
> > > > The testing class, which simply creates an instance of my FinalClass
> > > > class and
> > > > executes its foo method:
> > > >
> > > > public class Test {
> > > >
> > > >        public static void main(String args[]) {
> > > >                FinalClass fc = new FinalClass();
> > > >                fc.foo();
> > > >        }
> > > > }
> > > >
> > > > And here's the Aspect I have created in order to capture calls for
> > > > the constructors of final classes:
> > > >
> > > > public aspect DetectFinalClassesAspect {
> > > >
> > > >        pointcut finalClasses() : execution(final *.new(..))
> > > > && !within(DetectFinalClassesAspect);
> > > >
> > > >        // This is not being applied to anything!!!
> > > >        before() : finalClasses() {
> > > >                System.out.println("Before final class: " +
> > > > thisJoinPointStaticPart);
> > > >        }
> > > > }
> > > >
> > > > Thanks in advance. Best regards,
> > > >
> > > >        Paulo Zenida
> > > > _______________________________________________
> > > > aspectj-users mailing list
> > > > aspectj-users@xxxxxxxxxxx
> > > > https://dev.eclipse.org/mailman/listinfo/aspectj-users


Back to the top