I want to add an advice that runs for each object created from a set of classes (in my case, from a specific package) after initialization is complete. Consider this code:
public class Test {
public static void main(String[] args) {
new A();
new A(0);
new B();
new B(0);
new B(false);
}
}
class A {
public A() {
}
public A(int i) {
this();
}
}
class B extends A {
public B() {
}
public B(int i) {
this();
}
public B(boolean b) {
super(0);
}
}
for example, for new B(false), the advise should run after public B(boolean), but not after public A(int) of after public A(). Also note that I don't want to advise the constructor calls in main(); if objects are constructed from a 3rd party application that's not compiled with my aspect, the advise should still be there, i.e. the constructors themselves should be advised.
I thought this should work using some !cflowbelow() expression, but I had no luck. The closest I got is this:
after() : initialization(pkg.*.new(..))
&& !cflowbelow(withincode(pkg.*.new(..)))
&& !within(MyAspect) {
System.out.println(thisJoinPointStaticPart);
}
which gives this output:
initialization(test.A())
initialization(test.A(int))
initialization(test.A())
initialization(test.B())
initialization(test.A())
initialization(test.B(int))
initialization(test.A(int))
initialization(test.B(boolean))
i.e. this() executions are ignored correctly, but super() executions are not. Also, I fear this will ignore things like public B() {new A();} or similar, because new A(); is in a pkg.*.new(..) cflowbelow...
I can't imagine this isn't a use case that's useful over and over, but I didn't find any resources on it. An example where full initialization is necessary would be when logging newly created objects, but the toString() method uses the object's state. Advising anything else but the "subclass-most" constructor will yield in a log containing uninitialized values, and advising constructor calls will, as I said, not work with third party code (or code from a different package in my example).
For extra internet-cookies, how would I select the bottom-most (non-Object or other non-unadvised-superclass) constructor for injectting pre-initialization code?
Related
I've got the following code example:
class p {
public void druckauftrag() {
// ...
drucke();
}
public void drucke() {
System.out.println("B/W-Printer");
}
}
class cp extends p {
public void drucke() {
System.out.println("Color-Printer");
}
}
Calling the following lines:
cp colorprinter = new cp();
cp.druckauftrag();
There is no problem understanding why "cp.druckauftrag();" results in console output "Color-Printer".
But when I call:
p drucker = (p)colorprinter;
drucker.druckauftrag();
I get the same output - why?
Does the typecast overwrite the object "drucker" 's method "drucke" with "drucke" from colorprinter?
Thanks in advance for every explanation.
colorprinter does not stop being an instance of cp when you use the cast operator on it, so its implementation of public void drucke() does not change
What you are expressing with your (p)colorprinter casting is the kind of contract (interface) you expect the object colorprinter to satisfy, which includes a public method with the signature public void drucke(), but not any specific implementation.
And, by the way, this casting is already performed implicitly when you declare drucker of the type p, so (p) is redundant in p drucker = (p)colorprinter;. p drucker = colorprinter; will suffice.
Here you can learn more about typecasting.
Keep in mind that it's best practice to extend from abstract classes or interfaces and only #Override (implement) abstract methods. A better design of your code would be:
abstract class BasePrinter {
public void druckauftrag() {
// ...
drucke();
}
public void drucke();
}
class p extends BasePrinter {
public void drucke() {
System.out.println("B/W-Printer");
}
}
class cp extends BasePrinter {
public void drucke() {
System.out.println("Color-Printer");
}
}
But of course constraints don't always allow for that kind of redesign. Passing the base requirements as parameters to the constructor (dependency injection) instead of extending a base class can also be a good alternative:
interface Druckable {
void drucke();
}
class Druckauftrager {
Druckable dk;
Druckauftrager(Drukable dk){
this.dk = dk;
}
public void druckauftrag() {
// ...
dk.drucke();
}
}
class p implements Druckable {
public void drucke() {
System.out.println("B/W-Printer");
}
}
class cp implements Druckable {
public void drucke() {
System.out.println("Color-Printer");
}
}
Now, if you want to express that a printer requires or can have multiple printing capabilities (like both color and b/w), you just write the class with as much extra Drukable properties and constructor parameters as you want, for example:
class BlackAndWhiteOrColorPrinter {
p blackAndWhitePrintService;
cp colorPrintService;
Druckable selectedPrintService;
BlackAndWhiteOrColorPrinter (p blackAndWhitePrintService, cp colorPrintService){
this.blackAndWhitePrintService = blackAndWhitePrintService;
this.colorPrintService = colorPrintService;
this.selectedPrintService = blackAndWhitePrintService;
}
public void druckauftrag() {
// ...
selectedPrintService.drucke();
}
}
This way, you can even write a class MultiPrinter with a MultiPrinter(List<Druckable> printServices) constructor and add any number of printing modes to its list of printing services: p, cp, and whatever other implementation of Druckable with its public void drucke() comes in the future. It is also extra practical if you want to introduce unit testing, so you can provide mockup objects that force the particular conditions you want to test, like druke() throwing a PaperJamException, for example.
For more information on how interfaces, overriding and inheritance work, see https://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.html
BTW, acording to the latest revision of the official java code conventions guide and also by de facto standard, classes in Java should use CamelCase naming convention. You can also benefit greatly from using semanting naming on all your definitions, like BlackAndWhitePrinter blackAndWhitePrinter and ColorPrinter colorPrinter.
colorprinter is an instance of cp. Even when you upcast it to p, it's drucke() method will be still the one from cp.
The difference is that after you upcast colorprinter, you will not be able to invoke the methods that cp defines on its own.
When you create an object using new operator, memory is allocated in heap. Methods and fields are actually there depending upon the concrete actual class of the object.
Alter a sub class overrides and modifies a behavior from its super class, invoking the overridden method will always result in the modified behavior. Casting will only mean that the object of sub class is now represented by the super type as the object has a modified behavior for a method will always result in the modified behavior.
Suppose you have below classes
public class Fruit{
public void taste(){
System.out.println("depends upon the actual fruit");
}
}
public class Mango extends Fruit{
#Override
public void taste(){
System.out.println("sweet");
}
public void wayToExposeSuperMethod(){
super.taste();
}
}
In other words its like calling mango as a fruit but still mango remains mango.
For above code
Fruit fruit = new Mango();
fruit.taste(); // <-- this will output : sweet
((Mango)fruit).taste();// <-- this will output : sweet
fruit.wayToExposeSuperMethod(); // <-- this will not compile
((Mango)fruit).wayToExposeSuperMethod(); // <-- this will output : depends upon the actual fruit
This is a question from this book: https://www.cl.cam.ac.uk/teaching/0506/ConcSys/cs_a-2005.pdf page 28
Can you write an additional Java class which creates an
object that, when passed to the test method causes it to
print “Here!”? As I say in the code, editing the class A
itself, or using library features like reflection, serialization,
or native methods are considered cheating! I’ll provide
some hints in lectures if nobody can spot it in a week or
so. None of the PhD students has got it yet.
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof A) {
System.out.println("Here!");
}
}
}
I know the question is a lot unclear. I can think of many different 'hack-ish' solutions but not sure if they will be counted as 'cheating' or not :)
I can't find the official answer so asking you for what would be a good answer.
If we consider that nesting class A does not "modify it" (as, technically, all lines of code are intact) then this solution is probably the only valid option:
class B
{
static
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof A) {
System.out.println("Here!");
}
}
}
public static void main (String[] args) throws java.lang.Exception
{
A.test(new A());
}
}
What I mean is, technically it follows all the rules:
Can you write an additional Java class which creates an object that, when passed to the test method causes it to print “Here!”? - Done
As I say in the code, editing the class A itself ... considered cheating! - Technically, the class is unedited. I copy pasted it into my code.
... or using library features like reflection, serialization, or native methods are considered cheating! - Done
If, however, you decide that nesting class A should not be allowed, then I believe there is no proper solution to the problem given the current definition. Also, given the section of the book this task is given in, I bet that the author wanted to make the constructor protected but not private.
Somehow, I don't like this sort of questions. It's from a lecture back in 2005, and according to websearches, it seems that nobody has found "the" solution until now, and no solution has been published.
The constraints are clear, but the question of what is allowed or not is somewhat fuzzy. Every solution could be considered as "cheating", in one or the other way, because a class with a private constructor is not meant to be subclassed. That's a critical security mechanism, and the responsible engineers are working hard to make sure that this security mechanism cannot be trivially circumvented.
So of course, you have to cheat in order to solve this.
Nevertheless, I spent quite a while with this, and here's how I eventually cheated it:
1.) Download the Apache Bytecode Engineering Library, and place the bcel-6.0.jar in one directory.
2.) Create a file CreateB.java in the same directory, with the following contents:
import java.io.FileOutputStream;
import org.apache.bcel.Const;
import org.apache.bcel.generic.*;
public class CreateB
{
public static void main(String[] args) throws Exception
{
ClassGen cg = new ClassGen("B", "A", "B.java",
Const.ACC_PUBLIC | Const.ACC_SUPER, new String[] {});
ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.VOID,
Type.NO_ARGS, new String[] {}, "<init>", "B", il, cp);
il.append(InstructionFactory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
cg.addMethod(method.getMethod());
il.dispose();
cg.getJavaClass().dump(new FileOutputStream("B.class"));
}
}
3.) Compile and execute this class:
javac -cp .;bcel-6.0.jar CreateB.java
java -cp .;bcel-6.0.jar CreateB
(note: On linux, the ; must be a :). The result will be a file B.class.
4.) Copy the class that was given in the question (verbatim - without any modification) into the same directory and compile it.
5.) Create the following class in the same directory, and compile it:
public class TestA
{
public static void main(String[] args)
{
A.test(new B());
}
}
6.) The crucial step: Call
java -Xverify:none TestA
The output will be Here!.
The key point is that the CreateB class creates a class B that extends A, but does not invoke the super constructor. (Note that an implicit super constructor invocation would normally be added by the compiler. But there's no compiler involved here. The bytecode is created manually). All this would usually fail with a VerifyError when the class is loaded, but this verification can be switched off with -Xverify:none.
So in summary:
The class A itself is not edited (and also its byte code is not edited, I hope this is clear!)
No reflection
No serialization
No custom native methods
There are a few options here:
Create a class:
public class Y extends A {
public static void main(String[] args) throws Exception {
X.test(new Y());
}
}
And then edit the bytecode and remove the call to X.. Of course this violates the JVM specification and has to be run with -Xverify:none as said above. This is essentially the same as the one #Marco13.
Option 2:
import sun.misc.Unsafe;
public class Y extends A {
public static void main(String[] args) throws Exception {
Unsafe uf = Unsafe.getUnsafe();
X.test((X) uf.allocateInstance(X.class));
}
}
Compile the code and run it by putting your classpath in the sysloader (otherwise it won't work):
$ java -Xbootclasspath/p:. Y
Both work for me :) Of course, they are both cheating. The first option isn't Java. The second is, well, evil :)
If I find out another way, I'll post it :)
In any case this can't be done without low-level tricks. The JVM Specification explicitly prohibits the creation of an object without calling the constructor as the object in the stack is uninitialized. And the JVM Specification explicitly prohibits not calling the super constructor. And the JVM Specification explicitly requires verification of access protection.
Still funny, though :)
Java can support unicode class name:)
The A in "if (o instanceof A)" could be different from the A in "public class A"
For example, the code below will print "Here!" instead of "bad".
A.java
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
// A: U+0041
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof А) {
System.out.println("Here!");
}
}
}
А.java
public class А {
// A: U+0410, not A: U+0041
}
Main.java
public class Main {
public static void main(String[] args) {
A.test(new А());
}
}
I'm trying to write an expression or series of statements of Java source code that when written inside a static method evaluates to null, but if the method is non-static evaluates to this.
My initial idea was to 'overload' on static vs non-static, as below:
public class test {
public void method1() {
System.out.println(getThisOrNull());
}
public static void method2() {
System.out.println(getThisOrNull());
}
private static Object getThisOrNull() {
return null;
}
private Object getThisOrNull() {
return this;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
Unfortunately this isn't actually legal Java, you can't 'overload' like that and it just gives a compiler error:
test.java:14: error: method getThisOrNull() is already defined in class test
private Object getThisOrNull() {
^
1 error
Clearly in an ideal world I wouldn't write it like that to begin with, but the problem is this code will be generated automatically by a tool that is not really semantically or syntactically enough to distinguish between the static vs non-static case.
So, how can I write some source code that, although byte for byte identical compiles and behaves differently in depending on the presence of the static modifier for the method?
This can be achieved with a trick and a bit of help from Java's reflection facilities. It's ugly, but it works:
import java.lang.reflect.Field;
public class test {
public void method1() {
System.out.println(getThisOrNull(new Object(){}));
}
public static void method2() {
System.out.println(getThisOrNull(new Object(){}));
}
private static Object getThisOrNull(final Object o) {
for (Field f: o.getClass().getDeclaredFields()) {
if (f.getType().equals(test.class)) {
try {
return f.get(o);
}
catch (IllegalAccessException e) {
// Omm nom nom...
}
}
}
return null;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
This compiles and runs as hoped for:
test#183f74d
test#183f74d
null
The trick that makes this possible is the use of new Object(){}, which creates a new, anonymous class within the existing method that we're trying to figure out if it's static or not. The behaviour of this is subtly different between the two cases.
If the goal were just to figure out if the method is static or not we could write:
java.lang.reflect.Modifiers.isStatic(new Object(){}.getClass().getEnclosingMethod().getModifiers())
Since we want to get this (when available) we need to do something slightly different. Fortunately for us classes defined within the context of an instance of an object in Java get an implicit reference to the class that contains them. (Normally you'd access it with test.this syntax). We needed a way to access test.this if it existed, except we can't actually write test.this anywhere because it too would be syntactically invalid in the static case. It does however exist within the object, as a private member variable. This means that we can find it with reflection, which is what the getThisOrNull static method does with the local anonymous type.
The downside is that we create an anonymous class in every method we use this trick and it probably adds overheads, but if you're backed into a corner and looking for a way of doing this it does at least work.
Suppose we have some Base class with a method with Object parameter, and in a newer vesion developers decide to change Ojbect to int.
for example:
public class Base {
public void foo(Object i)
{
System.out.println("ahahaa");
}
}
public class Child extends Base
{
public void foo(Object i)
{
System.out.println("tru-la-la");
}
}
Then new version of Base:
public class Base
{
public void foo(int i)
{
Console.WriteLine("ahahaa");
}
}
Then if we call something like:
Child child = new Child();
child.foo(5);
We'll get "ahaha" instead of expected "tru-la-la"
So how can we deal with it, and what architecture solution should we use?
It seems you are not looking for an explanation regarding why you get "ahaha" and not "tru-la-la" (which you used to get before the change in the Base class).
If you are releasing libraries to be used by other developers, you are expected to maintain backward comptibility. The chnage you describe in the Base class clearly doesn't respect backward comptibility, so any code that relies on it would break.
There's nothing you can do other than change your code or stop using that library.
You can change your code, for example, by calling child.foo(new Integer(5)), which would invoke the sub-class method.
Another thing that can help is to mark the method in the Child class with #Override annotation. This would stop your code from compiling after the change in the Base class.
If you are using an int -child.foo(5); then the JVM will naturaly take the method in the child object that is most specific. In this case it is
a choice between
public void foo (Object i) {
&
public void foo (int i) {
the more specific is --
public void foo(int i) {
which writes "ahahaa"
I'm trying to write a unit test that needs to confirm if a method is called or not. I'm using JUnit, Mockito and PowerMock.
public class Invoice
{
protected void createInvoice()
{
// random stuff here
markInvoiceAsBilled("57");
}
protected void markInvoiceAsBilled(String code)
{
// marked as billed
}
}
So, here my system under test is Invoice. I'm running this test:
public class InvoiceTest
{
#Test
public void testInvoiceMarkedAsBilled()
{
Invoice sut = new Invoice();
Invoice sutSpy = spy(sut);
sut.createInvoice();
// I want to verify that markInvoiceAsBilled() was called
}
}
This example is just an example of what the actual code looks like....
My problem is that mockito says you can only verify if a method is called on a mocked object... but I don't want to mock this object, as it's my object under test. I know that you can spy on the object you're testing, so here's what I tried:
verify(sutSpy).markInvoiceAsBilled("57");
Is what I'm trying to do not possible? Or am I just going about it the wrong way?
Thanks everyone :)
I'm not sure if what you are attempting to do is the best way to go about things.
I wouldn't concern myself with verifying that Invoice.createInvoice() calls an internal, private method markInvoiceAsBilled() - instead test that calling createInvoice() changes the state of the Invoice object in the way you expect - i.e., that status is now BILLED or something similar.
In other words - don't test what methods are called by createInvoice() - test that after calling this method, the state of the object is what you expect.
I agree with matt-b's answer. That being said, depending on the use case and the complexity of the method, you can redesign your unit so that it can be tested.
Say for example your object gets much more complicated, e.g.
public A {
public a() {
b();
c();
}
public b() { /** hairy code, many branches to test */ }
public c() { /** hairy code, many branches to test */ }
}
Covering b with tests and c with tests is straight-forward, but covering a would seem like a hassle since you depend on methods b and c.
Consider instead this design
public A {
private final Dep mDep;
public a() {
mDep.b();
mDep.c();
}
public b() {
mDep.b();
}
public c() {
mDep.c();
}
// dependency abstraction we create to help test
static class Dep {
public b() { /** hairy code, many branches to test */ }
public c() { /** hairy code, many branches to test */ }
}
}
Now, testing A.a, A.b and A.c just requires you to verify your mDep is called (among whatever else the method does). Separately, you test A.Dep.b and A.Dep.c methods.