I'm trying to delegate a private method in bytebuddy - but how do I call the 'overriden' version? If I have
TypePool typepool = TypePool.Default.ofClassPath();
new ByteBuddy()
.rebase(typepool.describe("Foo").resolve(), ClassFileLocator.ForClassLoader.ofClassPath())
.method(named("getNum"))
.intercept(MethodDelegation.to(typepool.describe("FooInterceptor").resolve()))
.make()
.load(typepool.describe("Foo").resolve().getClass().getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
Foo foo1 = new Foo();
System.out.println("Foo says " + foo1.getMessage());
and
public class Foo
{
private int num = 0;
public String getMessage()
{
return "Message is Foo " + getNum();
}
private int getNum()
{
return num++;
}
}
and
import net.bytebuddy.implementation.bind.annotation.Super;
public class FooInterceptor
{
public static int getNum(#Super Foo foo)
{
// This won't work!
return foo.getNum() + 100;
}
}
As far as the compiler is concerned, even if #Super Foo foo is going to become something else at runtime, I'm not allowed to call a private method on Foo. I don't seem to be able to reflect/invoke getNum() either - whatever #Super Foo becomes, it doesn't seem to have a getNum() method (although it does have a getMessage() method).
Can someone perhaps point me in the right direction here?
Update:
#Rafael's answer is technically a very good solution to the question I asked; unfortunately I guess my example was bad. Mea culpa. What I was really hoping for was a solution that would let me manipulate the arguments to getNum() before passing them. But it turns out that for my application I might be able to get by without doing that, so if that changes then perhaps I'll post that exact example.
Update 2:
Question completely answered! Hurray!
You probably want to use #SuperCall Callable. This would allow you to do invoke the overridden method from the method itself. It does however not allow you to invoke any method from within a proxied class.
public class FooInterceptor
{
public static int getNum(#SuperCall Callable<Integer> c) throws Exception
{
// This will work!
return c.call() + 100;
}
}
If you need to manipulate the arguments, this is possible by using the Morph annotation. It allows you to invoke a method whilst supplying explicit arguments:
public interface Morphing<T> {
T invoke(Object[] args);
}
public class FooInterceptor
{
public static int getNum(#Morph Morphing<Integer> m, #AllArguments Object[] args)
{
// This will work!
return m.invoke(args) + 100;
}
}
Note that you need to install the interface explicitly:
MethodDelegation.to(FooInterceptor.class)
.appendParameterBinder(Morph.Binder.install(Morphing.class));
Related
I have a class which contains a public static method in Java. Is there any annotation in java to warn the subclasses not to use same method signature(and thereby hide the superclass method). Any other workarounds would also be fine.
Just make the superclass method final:
class Foo {
public static final void go() {}
}
class Bar extends Foo {
public static void go() {}; // Error
}
Ideone Example
you dont need such annotations because what you a trying to do in not going to compile...
in java you just can not override static method
as #thomas suggested(+1 dafuer), you can play with the visibility of the static method
example:
public class Calculator {
static int add(int a, int b) {
System.out.println("a+b= " + (a + b));
return a + b;
}
public static void main(String[] args) {
}
}
and then
public class ScientificCalculator extends Calculator {
public int add(int a, int b) {
System.out.println("11111");
return a + b;
}
}
I don't know of any such annotation to flag the declaration of the method. You could, however, approach this from the opposite direction. Instead of focusing on the method declaration, you could look at uses of it. The -Xlint:all will warn if any uses could be a problem. A static method with an identical signature to a static method in its superclass will only cause problems when that method is referenced from an instance instead of statically. Consider this example:
public class Foo {
public static String getFoo(){
return "foo";
}
}
public class Bar extends Foo {
public static void main(String[] args){
Bar bar = new Bar();
String s = bar.getFoo(); // Actually calls Foo.getFoo()
System.out.println(s); // Prints "foo"
}
}
In the code above, we reference the static getFoo() method from Foo through an instance of Bar. The bar.getFoo() line actually calls the static method from Foo. Now suppose we add a static method with an identical signature to Bar:
public class Bar extends Foo {
public static String getFoo(){
return "bar";
}
public static void main(String[] args){
Bar bar = new Bar();
String s = bar.getFoo(); // Actually calls Bar.getFoo()
System.out.println(s); // Prints "bar"
}
}
This hides the Foo.getFoo() method from Bar and now the Bar.getFoo() method is invoked instead. In a real context, this would almost certainly break Bar. If you compile with the -Xlint:all option, then you'd get this message:
warning: [static] static method should be qualified by type name, Foo, instead of by an expression
You'd notice this when you compile the first version of Bar and you could fix it to String s = Foo.getFoo() right away. Later when getFoo is also added to Bar, the original code will still work because it explicitly references the method in Foo. If you always explicitly call static methods by referencing the class in which they are declared, then the only problem with having an identical method in a subclass is that it's not exactly a best practice. Maybe there is a way to flag the declaration, too, but I'd focus on making sure that the static method is used properly.
When i use below code, the stackoverflow exception is seen. It looks like line 16 (i.e public my m1 = new my()) is repeatedly called. Can someone please explain on the reason for calling it continuously.
abstract class my {
static int i = 0;
my(){
System.out.println("my constructor " + i++);
}
public void mymethod() {
System.out.println("Abstract");
}
public my m1 = new my() {
public void mymethod() {
System.out.println("Inside Abstract");
}
};
You have an instance field, m1, which you initialize with a call to new my. Instance field initialization is done during construction.1 So you construct an instance, and constructing that instance requires constructing another instance to assign to m1; constructing that instance requires constructing an instance to assign to its m1; constructing it requires constructing another instance, which...
You get the idea.
As Peter said, by far the best way to understand how and why something is working the way it is is to use a debugger to step through the code. Using a debugger is not an advanced technique, it's a fundamental tool to learn early in the process of learning the language.
1 In fact, the compiler takes instance initializer code and inserts it at the beginning of every constructor in the class. So
class Foo {
private int bar = 42;
Foo() {
System.out.println("no args");
}
Foo(int arg) {
System.out.println("one arg: " + arg);
}
}
is actually compiled to
class Foo {
private int bar;
Foo() {
bar = 42
System.out.println("no args");
}
Foo(int arg) {
bar = 42
System.out.println("one arg: " + arg);
}
}
Okay, so I'm not sure if this question already exists because I don't know how to format it, but here's the problem: can a same method produce different result depending on a constructor? (I apologize if I'm repeating the question or if it's a stupid question.)
For example, let's say that I have an interface MyInterface with function public void foo();. Let's say we have class:
public class MyClass implements MyInterface {
public MyClass() {
// I want foo() to print "Empty constructor" with sysout.
}
public MyClass(int x) {
// I want foo() to print "Constructor with int" with sysout.
}
}
So now, if create two references MyClass mc1 = new MyClass(); and MyClass mc2 = new MyClass(5); and then call mc1.foo(); and mc2.foo();, the result should be:
Empty constructor.
Constructor with int.
I tried with new MyInterface { #Override public void foo() { ... } } inside constructors but doesn't seem to work.
Yes. Store the variable and check it in the foo method.
public class MyClass implements MyInterface {
private int x;
public MyClass() {
// I want foo() to print "Empty constructor" with sysout.
}
public MyClass(int x) {
// I want foo() to print "Constructor with int" with sysout.
this.x = x;
}
public void foo(){
if(x > 0)
System.out.println("Constructor with int");
else
System.out.println("Empty constructor");
}
}
To answer the question: Not to my knowledge. Or at least not directly, you could start to read byte code and change it during run time, make it adapt-- so again, the answer is no.
Now the weird parts are the override and depending on constructor. It is not in the scope of overriding.
A method doing different things depending on the state of the Class is not too odd. However, making the method unique of how the class was instantiated I've never heard of. That being said, here is a fairly ugly solution to it.
public class Test
{
private final boolean intConstructorUsed;
public Test () {
intConstructorUsed = false;
}
public Test (int x) {
intConstructorUsed = true;
}
public void foo () {
if (intConstructorUsed == true) {
// do this
} else {
// do that
}
}
}
The foo method isn't that weird. The weird part is that you basically have to different implementations of foo depending on which constructor, you are sure you do not want an abstract class behind, with all shared methods except for one abstract void foo () that you override? Sure the classes will almost look identical, however they are not, as they do not share their foo ().
Yes, it's what's multiple constructors are designed to allow for - variation via object creation.
public class MyClass implements MyInterface {
private final String message;
public MyClass() {
message = "Empty constructor";
}
public MyClass(int x) {
message = "Constructor with int";
}
#Override
public void foo() {
System.out.println(message);
}
}
It's even threadsafe.
The thing to note here is that the implementation of the method is exactly the same, the variation is in the constructor. And it's the constructor which is called differently depending on what the caller wants to happen.
This may seem a basic question, but I'd like to get this right.
I have a Class 'AWorld'. Within that class, I have a method that draws a border, depending on the map size set by the user.
If the variable 'mapSize' is private, but I want to access it's value from within the same class, is it more appropriate to reference it directly, or use a getter method.
The code below should explain what I'm wanting to know.
package javaFX;
public class AWorld {
//initialized later
AWorld newWorld;
private int mapSize = 20;
public int getMapSize()
{
return mapSize;
}
public void someMethod()
{
int var = newWorld.mapSize; //Do I reference 'mapSize' using this...
}
// Or...
public void someOtherMethod()
{
int var = newWorld.getMapSize(); //Or this?
}
public static void main(String[] args) {}
}
Either of those is ok since you're getting a primitive field. If the get method does another operation before returning the data e.g. performing a math operation on the value, then it would be better to use it rather than calling the field directly. This is specially meant when using proxy/decorator pattern on your classes.
Here's an example of the second statement from above:
//base class to be decorated
abstract class Foo {
private int x;
protected Foo foo;
public int getX() { return this.x; }
public void setX(int x) { this.x = x; }
public Foo getFoo() { return this.foo; }
//method to prove the difference between using getter and simple value
public final void printInternalX() {
if (foo != null) {
System.out.println(foo.x);
System.out.println(foo.getX());
}
}
}
//specific class implementation to be decorated
class Bar extends Foo {
#Override
public int getX() {
return super.getX() * 10;
}
}
//decorator
class Baz extends Foo {
public Baz(Foo foo) {
this.foo = foo;
}
}
public class Main {
public static void main(String[] args) {
Foo foo1 = new Bar();
foo1.setX(10);
Foo foo2 = new Bar(foo1);
//here you see the difference
foo2.printInternalX();
}
}
Output:
10
100
You better dereference it directly.
The point of the private modifier is not to expose internal implementation to other classes. These other classes will use the getter method to get the value of the private property.
In your own class, there is no point on using the getter. Worse, someone may have overridden that method in a class that extends your class, and the getter may perform something that you do not expect
IMHO, if you are referencing a field of the current instance the general rule is to access the field directly with mapSize or this.mapSize.
If you are referencing a value from a different instance (be it of the same class or a different class, I would use the getter method). I believe this would lead to simpler refactoring. It also maintains the contract that any other instance gets the field value via the getter which allows for additional functionality in the getter.
Please have a look at this code :
class Foo {
public int a;
public Foo() {
a = 3;
}
public void addFive() {
a += 5;
}
public int getA() {
System.out.println("we are here in base class!");
return a;
}
}
public class Polymorphism extends Foo{
public int a;
public Poylmorphism() {
a = 5;
}
public void addFive() {
System.out.println("we are here !" + a);
a += 5;
}
public int getA() {
System.out.println("we are here in sub class!");
return a;
}
public static void main(String [] main) {
Foo f = new Polymorphism();
f.addFive();
System.out.println(f.getA());
System.out.println(f.a);
}
}
Here we assign reference of object of class Polymorphism to variable of type Foo, classic polmorphism. Now we call method addFive which has been overridden in class Polymorphism. Then we print the variable value from a getter method which also has been overridden in class Polymorphism. So we get answer as 10. But when public variable a is SOP'ed we get answer 3!!
How did this happen? Even though reference variable type was Foo but it was referring to object of Polymorphism class. So why did accessing f.a not result into value of a in the class Polymorphism getting printed? Please help
You're hiding the a of Polymorphism - you should actually get a compiler warning for that. Therefore those are two distinct a fields. In contrast to methods fields cannot be virtual. Good practice is not to have public fields at all, but only methods for mutating private state (encapsulation).
If you want to make it virtual, you need to make it as a property with accessor methods (e.g. what you have: getA).
This is due to the fact that you can't override class varibles. When accessing a class variable, type of the reference, rather than the type of the object, is what decides what you will get.
If you remove the redeclaration of a in the subclass, then I assume that behaviour will be more as expected.