How to generate methods dynamically in Java - java

I was wondering, what if I have the following case:
public class MyObject<T> {
private T myTObject;
public void setMyTObject(T m) {
myTObject = m;
}
public T getMyTObject() {
return myTObject;
}
}
And now I want that class to react something like these:
MyObject<ObjectA> objA = new MyObject<ObjectA>();
ObjectA objAInstance = objA.getObjectA();
or
objA.setObjectA(otherObjectAInstance);
Is there a way to dynamically create methods based on T class name?
Or should I better extend ObjectA to MyObject and create those methods using super.get/seMyObject()?
For clarification:
The idea is to have a getter and setter method generated dynamically
so, if I create an instance of:
MyObject<A> objA = new MyObject<A>();
I would be able to call method:
objA.getA();
getA() will call internally getMyTObject() or just return myTObject
so MyObject may react based on T class and generate the corresponding method.
I have updated member attribute to differentiate from MyObject class, it may lead to confusion. also fixed Method return and parameter Type.

Update Answer is completely changed.
Sounds like you want to use something through reflection. The problem with truly dynamically generating the method names is that, as others have commented, it would have to be done in bytecode which means that other classes trying to use your dynamic classes don't have Java code to refer to. It can be done, but it would be a mess.
Instead, here's a possible solution using generics. Please note that this is something of a quick and dirty hack; I leave it to you to refine it. You define an interface with the getters and setters you want, with whatever you want them named:
package com.example.dcsohl;
public interface IntegerWrapper {
public Integer getInteger();
public void setInteger(Integer i);
}
And then, to use them, you use this class to do the heavy lifting. Note that the error checking isn't very good; for example, it doesn't check that "getFoo" at all corresponds to the name of the class being passed in; nor does it validate that the "foo" in "getFoo" matches the "setFoo" method. This is something you can improve on.
package com.example.dcsohl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyWrapper<T> implements InvocationHandler {
Class<T> clazz = null;
T myvalue = null;
public static <W,T> W getInstance(Class<W> clazz, Class<T> clazz2) {
ProxyWrapper<T> wrapper = new ProxyWrapper<T>();
wrapper.setClass(clazz2);
#SuppressWarnings("unchecked")
W proxy = (W)Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] {clazz}, wrapper);
return proxy;
}
private void setClass(Class<T> clazz) {
this.clazz = clazz;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// getter has no arguments
if (method.getName().startsWith("get") && (args == null || args.length == 0)) {
return myvalue;
} else if (method.getName().startsWith("set") && args.length == 1) {
Object o = args[0];
if (o.getClass().isAssignableFrom(clazz)) {
#SuppressWarnings("unchecked")
T val = (T)o;
myvalue = val;
return null;
}
} else {
throw new Exception();
}
return null;
}
}
Finally, to use it, here's a quick sample:
package com.example.dcsohl;
public class Main {
public static void main(String[] args) {
Integer foo = 5;
IntegerWrapper wrapper = ProxyWrapper.getInstance(IntegerWrapper.class, Integer.class);
wrapper.setInteger(foo);
Integer bar = wrapper.getInteger();
System.out.println(bar);
}
}
It seems like a lot of work just to avoid writing simple wrapper classes, and you'd be right, but reflection has its uses, and this is something of a sampler.

Related

Is there a way we can hide a particular method only for some classes IN the package? [duplicate]

Here's an example:
class A
{
List l = new List ();
list.insert("x");
}
class List
{
...
public void insert ()
{
/*insertion occurs*/
}
...
}
Is it possible at all to keep the insert() method public, but limit access only to class A so that no other class can access it, only when called from A?
I would pass the object that is calling the method as an argument, i.e.
list.insert("x", this);
And then check if the passed Object is an Instance of Class A
public void insert (String x, Object o)
{
if(o instanceof ClassA){
/*insertion occurs*/
}
}
If the method is public, everyone can access it. The trick to access control like yours is to expose a set of public operations through an interface, add auxiliary operations to a private class implementing the interface, and make your users program to the interface, not to a class.
Here is an example:
public interface MyList {
Object elementAt(int i);
}
public class A {
private static class MyListImpl implements MyList {
public Object elementAt(int i) {
...
}
public void insert(Object element) {
...
}
}
private final MyListImpl list = new MyListImpl();
public MyList getList() { return list; }
public void insert(Object o) { list.insert(o); }
}
Usage scenario:
A a = new A();
a.insert(123);
a.insert("quick brown fox");
MyList lst = a.getList();
System.out.println(lst.elementAt(0));
System.out.println(lst.elementAt(1));
Yes, you can pass calling object as an argument and put a check in insert() method before actual code.
public void insert(Object obj){
if(obj instanceof A){
//your code block
}
}
Please note that this will allow all the classes that extends A as well to call insert. If you want to restrict only for class A, add additional check.
public void insert(Object obj){
if((obj instanceof A) && obj.getClass().getSimpleName().equals("A")){
//your code block
}
}
we can also achieve second case with only condition "obj.getClass().getSimpleName().equals("A")" as well.
The best you can do using access modifiers is to make the method package private (remove the public keyword) and keep only those two classes in the same package.
If all the "inner classes" stuff in the previous answers confuses you, there is another way that may be more intuitive (assuming you've learned about the extends keyword and inheritance). You can simply make the insert() method protected instead of public and make class A extend List. For example:
public class List {
...
protected void insert() {
//insertion occurs
}
...
}
public class A extends List {
...
}
As long as no other classes extend List, only objects of types A and List will ever be able to use the insert() method.
package problems;
public class Problem1 {
public static void main(String[] args) {
B b = new B();
b.methodInB();
C c = new C();
c.methodNotInB();
}
}
class A {
public void onlyB() {
StackTraceElement[] stackTraceElements = Thread.currentThread()
.getStackTrace();
if (!problems.B.class.getCanonicalName().equals(
stackTraceElements[stackTraceElements.length - 2]
.getClassName())) {
System.err.println("You are not authorized to call me!!");
return;
}
System.out.println("You are authorized to call me!!");
}
}
class B {
public void methodInB() {
A a = new A();
a.onlyB();
}
}
class C {
public void methodNotInB() {
A a = new A();
a.onlyB();
}
}
Put it as inner class in A or you can do another thing ...
Let insert takes one parameter with type of Object and in the beginning of it check if the parameter's type is A .... and when you call it send the calling object...
maby its not a good idea but it will do what you want
Put it into the permitted class and make it private.

How to track a method result in Java

Briefly speaking, I am working on developing a system which is able to give you information about the results provided by the execution of a java program. I have considered the following problem, and I do not know if it is possible to solve it in java.
I have the following classes:
public class ClassA {
ClassB classB= new ClassB();
public Integer method1(){
return classB.method2();
}
}
public class ClassB {
ClassC classC = new ClassC();
public Integer method2() {
return this.classC.method3() + this.classC.method4();
}
}
public class ClassC {
public Integer method3() {
return 3;
}
public Integer method4() {
return 4;
}
}
So far I can capture each invocation of the methods by using dynamic proxies. In particular, I am using the Proxy and the InvocationHandler objects from the package java.lang.reflect. Here there is the example I followed (https://www.concretepage.com/java/dynamic-proxy-with-proxy-and-invocationhandler-in-java).
My question is if someone knows how can I give information such as:
"the return of method1() is generated from the return of method2(), and the return of method2() is in turn generated from the return of method3() and the return of method4()".
You need to utilize ThreadLocals. You thread local will have a Map which will be filled by each method. Here is a sample code:
public static void main(String... args){
try{
new ClassA().method1();
TrackingThreadLocal.tracker.get().entrySet().stream().forEach( (e) -> System.out.println(
"the return of " + e.getKey() + " is generated from the return of " + e.getValue().stream().collect( Collectors.joining(", ") ) ) );
}finally{
//make sut to clean up to avoid ThreadLocal memoty leak
TrackingThreadLocal.tracker.remove();
}
}
public class TrackingThreadLocal{
public static ThreadLocal< Map<String, List<String> > > tracker = new ThreadLocal< Map< String, List<String> > >(){
#Override
public Map< String, List<String> > initialValue() {
return new HashMap<>();
}
};
}
public class ClassA {
ClassB classB= new ClassB();
public Integer method1(){
TrackingThreadLocal.tracker.get().put("method1", Arrays.asList("method2") );
return classB.method2();
}
}
public class ClassB {
ClassC classC = new ClassC();
public Integer method2() {
TrackingThreadLocal.tracker.get().put( "method2", Arrays.asList("method3", "method4") );
return this.classC.method3() + this.classC.method4();
}
}
public class ClassC {
public Integer method3() {
return 3;
}
public Integer method4() {
return 4;
}
}
I have used instrumentation to solve a similar problem before.
Disclaimer: You can only do the following if you have control over the JVM and you can specify it to run with a javaagent.
An agent is fairly simple to implement, all you need is a class which implements a method with the premain(String, java.lang.Instrumentation) signature. An example follows:
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.lang.instrumentation.ClassFileTransformer;
import java.lang.instrumentation.IllegalClassFormatException;
import java.lang.instrumentation.Instrumentation;
import java.security.ProtectionDomain;
public class MyAgent {
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new ClassTransformer() {
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
// if you want to target specific classes or packages you can filter
// on the class name, just remember that it is the JVM class format string
if(className.startWith("com/my/package/SomeThing")) {
// javassist provides methods to access classes and generate bytecode
ClassPool cp = ClassPool.getDefault();
// you can access the class with the following
CtClass cc = cp.get("com.my.package.MyClass$InnerClass");
// access specific methods with
CtMethod m = cc.getDeclaredMethod("someMethod");
m.setBody("{MyCallTree tree = com.my.package.TreeSingleton.getTree();\ntree.addCall(" + m.getLongName + ");\n}");
return cc.toByteCode();
}
else {
// return null so that you don't break methods or classes you
// don't want to
return null;
}
});
}
}
In the snippet above, I replaced the entire method body with the code passed as a string to CtMethod.setBody. However, you can really do almost anything with javassist, prepend code, append code, etc. A detailed tutorial on using javassist can be found here. It is a very powerful library.
The details of how you implement the code to build up the call information is really just Java code, maybe write the code as part of your project first and then just use the bits that does the footwork in the premain method. You can even let it write the code suggested by tsolakp in his answer.
The next step is to package the above code in a jar file and then inject it into your JVM when you start it up, as done in this answer.
One thing that comes to my mind is to retrieve a stacktrace of a thread and see what you can do with.
You can do it with eg. Thread.currentThread().getStackTrace() method and receive an array of StackTraceElement, finally use them to receive a method name with a getMethodName() method.
It is just an idea, I am not sure if you can get the information you want to.

Can an instance complete its arguments later?

I wonder if there is any way that I can declare a new instance with parameters, do not fill them, and just set them later.
Here is an example:
private Example example = new Example() // Need 1 parameter.
public void foo(Object arg1)
{
example = new Example(arg1);
}
It is clear that this is not possible, but is there a way to do something similar to that?
You can always use a parameter-less constructor, and then set the properties of the created instance later.
....
public Example ()
{
this.s = null;
}
public Example (String s)
{
this.s = s;
}
....
public void setS (String s)
{
this.s = s;
}
....
Example ex = new Example ("something");
Example ex2 = new Example ();
ex2.setS("Something Else");
public class Example{
private Object object1;
public Example(){
}
public void setObject1(Object o){
this.object1 = o;
}
}
Now you can use this as follows:
Example example = new Example();
example.setObject1(someObject);
As noted by others and yourself already, there is no easy / official way of object construction when you can't provide the parameters needed.
You may want to look at the Objenesis project. They provide clever ways of instantiation of objects in non-standard ways. To my knowledge sometimes being able to instantiate objects without providing the usually mandatory arguments declared by the constructors.

Creating mock object without framework

I am currently using EasyMock and creating mock objects like this
mockedObject = createMock(myInterface.class);
Easy mock is an unnecessary overhead(because the method that i mock is really simple) and i would like to create a mock without it.
But the problem is myInterface is an interface so how do i instantiate it.Please suggest.
Thanks,
Sriram
The easiest way would be to create an inner class that implements the interface, implement the methods to return the data that you want, then use it in the test case.
For example:
public void testMethod ( )
{
MyInterface mockObject = new MyInterface ( ) {
public void myMethod ( )
{
// NOOP
}
public int myFunction ( )
{
return -1 ;
}
}
// Proceed with the test case using mockObject
}
You can create and Anoymous class e.g.
MyInterface myMock = new MyInterface() {
... methods implemented here
};
If you need to verify the number of times a method is called you can add a simple counter member for each method.
e.g.
public void testMethod ( )
{
MyInterface mockObject = new MyInterface ( ) {
public int MyMethodCount = 0;
public int MyFunctionCount = 0;
public void myMethod ( )
{
MyMethodCount++;
// NOOP
}
public int myFunction ( )
{
MyFunctionCount++;
return -1 ;
}
}
// Proceed with the test case using mockObject
}
In the absence of a mock framework, java.lang.reflect.Proxy is your best bet. If you've never used it before, you can create a dynamic object which implements a set of interfaces, and you use the InvocationHandler to check each method call and decide what to do. This is a very powerful technique (and not limited to testing), as you can delegate method calls to other objects, etc.... It also insulates you from certain interface changes when you do this sort of delegation, as you don't declare each method. It adapts to the interface at runtine.
public static interface MyIntf {
String foo(String arg1);
}
InvocationHandler invocationHandler = new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("foo") &&
method.getParameterTypes().length == 1 &&
method.getParameterTypes()[0] == String.class) {
// do your mocking here. For now i'll just return the input
return args[0];
}
else {
return null;
}
}
};
MyIntf myintf = (MyIntf) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class[] { MyIntf.class },
invocationHandler);
System.out.println(myintf.foo("abc"));
You cannot instantiate an interface, you need to work with one of its implementation. Since you have decided to forgo EasyMock (not sure why), then you need to either instantiate one of the existing interfaces implementations, or create a new one just for testing.

generics calling constructor

I am trying to do something I would not normally do, it is a bit odd, but I'd like to make it work. Essentially I have a factory that has to create objects by calling the constructor with different types of data (A and B take different types in the code below). I seem to have gotten my self stuck going down the generics route (I do need the code to be as compile time typesafe as possible). I am not opposed to writing the code differently (I'd like to keep the idea of the factory if possible, and I do not want to have to add in casts - so the "data" parameter cannot be an "Object").
Any thoughts on how to fix the code with generics or an alternative way of doing it that meets my requirements?
(Technically this is homework, but I am the instructor trying out something new... so it isn't really homework :-)
public class Main2
{
public static void main(String[] args)
{
X<?> x;
x = XFactory.makeX(0, "Hello");
x.foo();
x = XFactory.makeX(1, Integer.valueOf(42));
x.foo();
}
}
class XFactory
{
public static <T> X<T> makeX(final int i,
final T data)
{
final X<T> x;
if(i == 0)
{
// compiler error: cannot find symbol constructor A(T)
x = new A(data);
}
else
{
// compiler error: cannot find symbol constructor B(T)
x = new B(data);
}
return (x);
}
}
interface X<T>
{
void foo();
}
class A
implements X<String>
{
A(final String s)
{
}
public void foo()
{
System.out.println("A.foo");
}
}
class B
implements X<Integer>
{
B(final Integer i)
{
}
public void foo()
{
System.out.println("B.foo");
}
}
I don't see a way to make it work. I don't really think it should work either. When calling your makeX() function the calling code needs to know what integer parameter corresponds to what type of data to pass in. IOW, your abstraction is very leaky in the first place, and what you're really implementing is a rudimentary form of polymorphism, which you might as well use method overloading for, i.e.:
X makeX(String data) {
return new A(data);
}
X makeX(Integer data) {
return new B(data);
}
Of course it's a toy problem and all that. One way to make it work would be to make the client aware of implementation classes and add a Class<T> argument that you instantiate through reflection. But I suppose that would be kind of defeating the purpose.
I don't think what you're trying to do is possible without casting.
With casting, you have two options
if(i == 0)
{
x = new A((Integer)data);
}
else
{
x = new B((String)data);
}
}
or
class A
implements X<String>
{
A(final Object s)
{
}
}
...
class B
implements X<Integer>
{
B(final Object i)
{
}
}
Probably the closest thing you could get whilst retaining static type safety and having lazy construction is:
public static void main(String[] args) {
X<?> x;
x = aFactory("Hello").makeX();
x.foo();
x = bFactory(42).makeX();
x.foo();
}
private static XFactory aFactory(final String value) {
return new XFactory() { public X<?> makeX() {
return new A(value);
}};
}
public static XFactory bFactory(final Integer value) {
return new XFactory() { public X<?> makeX() {
return new B(value);
}};
}
interface XFactory() {
X<?> makeX();
}
So we create an instance of an abstract factory that creates the appropriate instance with the appropriate argument. As a factory, the product is only constructed on demand.
Clearly something had to give. What would you expect XFactory.makeX(1, "Hello") to do?
This is not possible without casting. As I have said elsewhere - generics don't remove the need for casting, but they mean that you can do all the casting in one place.
In the setup you describe, the factory method is exactly where all the under-the-hood work takes place. It's the spot where your code tells the compiler "I know you don't know what these types are, but I do, so relax.
It's entirely legit for your factory method to know that if i==1, then the data must be be of type Integer, and to check/enforce this with casting.

Categories