How to get class object without an instance or class name - java

I have an abstract class MyClass with a static method to populate given collection with a number of MyClassDescendant objects. This method should call a static getRandom() method of MyClassDescendant to get object instances.
My current code looks like this:
public static void populate(Collection<MyClass> coll, Class<? extends MyClass> cl, int num) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
for (int i = 0; i < num; i++) {
Method m;
m = cl.getMethod("getRandom");
coll.add((MyClass)(m.invoke(null)));
}
}
Then I call it like that:
MyClass.populate((Collection<MyClass>)(Collection<?>)collection, MyClassDescendant.class, 3);
This code works, but it's ugly. What I actually wanted to achieve would look like this:
MyClassDescendant.populate(collection, 3);
If it wasn't a static method, I'd just use this.getClass(). I know that MyClass.class would work for static method, but I don't want class for MyClass, but for specific MyClassDescendant (there are few descendant types).
Is there any way to get class object without having its instance or class name?

Since you are in a static context you'll have to duplicate some code, but you can do delegation.
public class MyClassDescendant extends MyClass {
public static void populate(Collection<MyClass> coll, int count) {
MyClass.populate(coll, MyClassDescendant.class, count);
}
}
Now you can call
MyClassDescendant.populate(collection, 3);

Try restructuring your method in this way:
public static <T extends Base> void populate(Collection<T> coll, int num) throws Exception{
for (T item : coll) {
Method m;
m = item.getClass().getMethod("getRandom");
coll.add((T)(m.invoke(null)));
}
}
With regards to one the comments, you can also use the template method design pattern to utilize inheritance for your getRandom() method by making it abstract and calling it within your populate method.

If get random is a static method couldn't you just call it?
public interface MyClassInterface {
MyClass getRandom();
}
public abstract class MyClass implements MyClassInterface {
public static void populate(Collection<MyClass> coll, int num) {
for (int i = 0; i < num; i++) {
coll.add((MyClass)MyClassDescendant.getRandom());
}
}
}
public class MyClassDescendant extends MyClass {
public MyClass getRandom() {
// implementation of getRandom
}
}

Related

Java invoke static method with Foreign Context / Check method for recursion

I wanted to check if a method uses recursion. So I wrote this mock up:
public class Main {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = Child.class.getMethod("toBeTested", int.class);
Object result = method.invoke(Super.class, 5);
System.out.println((Integer) result);
}
}
public class Super extends Child{
public static int toBeTested(int a){
System.out.println("validating recursion");
return Child.toBeTested(a);
}
}
public class Child {
public static int toBeTested(int a){
if(a==0)return 0;
return toBeTested(a-1)+1;
}
}
So I tried executing the method in Child with the Context of Super.class hoping in the recursion it would call the Super::toBeTested and I could hence validate the method uses recursion.
Is this even possible the way I tried? If no why not? Any other ideas to check foreign code for recursion...
No, you can't do that because that's not how static methods work, they don't have a "context" that decides what they call at runtime, it's decided at compile time (unless you want to call the classloader the context).
If it was a non-static method then you could do this:
public static class Child extends Super {
public int toBeTested(int a){
System.out.println("validating recursion");
return super.toBeTested(a);
}
}
public static class Super {
public int toBeTested(int a){
if(a==0)return 0;
return toBeTested(a-1)+1;
}
}
public static void main(String args[]) throws Exception {
Method method = Super.class.getMethod("toBeTested", int.class);
Object result = method.invoke(new Child(), 5);
System.out.println((Integer) result);
}
and it would print validating recursion 6 times because the method to be called depends on the runtime type of the object.
To check if static methods call themselves you could read the bytecode of the method (if you have access to it).

Instantiate a class inside a function in Java

I'm trying to create a function which fills a 2d array with some objects. My function looks like this:
void funcName(Element el){
container[0][0] = new el(args);
}
The only issue here is that Element is an abstract class, and so Java gives me an error when I try to instantiate an object. What I am trying to do is instantiate objects of classes which are built as extension to Element (i.e Class B extends Element). Is there a way to pass those classes as an argument, and have my function create them accordingly?
The abstract class:
public abstract class Element {
public abstract void myMethod();
}
The concrete class:
public class ArrayElement extends Element{
#Override
public void myMethod() {
System.out.println("Hello!");
}
}
The calling must be done in this way:
public class Main {
public static void main(String[] args) {
Element element = new ArrayElement();
calculate(element);
}
// This syntax will let you use any class that extends from the Element class, since it guarantees that is convertible to the type that you need. Are called generics.
public static <T extends Element> void calculate(T element){
element.myMethod();
}
}
Try this.
static abstract class Element {}
static class B extends Element {}
static void funcName(Class<? extends Element> cls)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException,
NoSuchMethodException, SecurityException {
Element[][] container = new Element[1][1];
container[0][0] = cls.getConstructor().newInstance();
and
funcName(B.class);
Or
static void funcName(Supplier<Element> s) {
Element[][] container = new Element[1][1];
container[0][0] = s.get(); // is equivalent to `new B()`
}
and
funcName(B::new);

Java Proxy invoke for nested calls

I'm having problems implementing a Proxy for a class that has to print the stacktrace for every call on a function of a class, because the functions are nested one with the other.
The problem is very similar if not the same to one another user had, the answers helped me to understand how to approach it but still I can't manage to solve it ( Dynamic Proxy: how to handle nested method calls ).
I've a class :
public class NestedCalls implements INestedCalls{
private int i = 0;
public int a() {
return b(i++);
}
public int b(int a) {
return (i<42)?c(b(a())):1;
}
public int c(int a) {
return --a;
}
}
and its interface:
public interface INestedCalls {
public int a() ;
public int b(int a) ;
public int c(int a) ;
}
The handler I implemented looks like this:
public class NestHandler implements InvocationHandler {
Object base;
public NestHandler(Object base) {
this.base=base;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(base, args);
printNest();
return result;
}
private void printNest() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
StackTraceElement[] stack = new Throwable().getStackTrace();
System.out.println("num of elem " + stack.length);
for(int i=0; i<stack.length; i++) {
System.out.println("elem "+i+": "+stack[i]);
}
}
}
What I aim to do is to initialize the object and the proxy from my main and after invoking a method I expect to print the stacktrace every time a method of the class is invoked.
INestedCalls nestedcalls = new ENestedCalls();
INestedCalls nestproxy = (INestedCalls) Proxy.newProxyInstance(nestedcalls.getClass().getClassLoader(), nestedcalls.getClass().getInterfaces(), new NestHandler(nestedcalls));
nestproxy.a();
To my understanding this doesn't work because the proxy handles everything with a intra-object and so the nested methods are not called with the proxy interface.
How can I get the effect I want without touching the code of the class?

Storing values from an abstract int on start-up

so I have an abstract class and i'm willing to store all the values from the sub-classes in an ImmutableList. Here is an example on what I mean
public abstract class Test {
...
public abstract int getValue();
}
then the sub-class
public final class Example extends Test {
#Override
public int getValue() {
return 5;
}
}
Is there a way to store the Test#getValue() in an ImmutableList on start-up?
I tried doing something like
public abstract class Test {
public static final ImmutableList<Integer> VALUES = ImmutableList.of();
public Test() {
VALUES.add(getValue());
}
public abstract int getValue();
}
then print out the values in the VALUES list.
public static void main(String[] args) {
Test.LIST.forEach(System.out::println);
}
but it didnt work.
use an initializer block. It's possible to create a static block which will execute upon class load:
package foo.bar.baz;
import java.util.*;
public class Test {
static {
int MY_INT = 5;
List<Object> mylist = new ArrayList<Object>();
mylist.add(new Integer(MY_INT));
}
public Test() {
// ...
}
}
You can write in the main method like this :
Reflections reflections = new Reflections("com.TestClassExample");
Set<Class<? extends >> classes = reflections.getSubTypesOf(TestExampleClass.class);
Get all the names of the classes and then loop through all the classes, and then cast it in the your test class and , then using and storing the values dynamically in a variable like this.
private static List<Integer> immutableList = new ArrayList<Integer>();
Does this sound feasible for your problem ?

get caller class name from inherited static method

I have following classes (note that methods are static):
class Base
{
public static void whosYourDaddy()
{
Class callerClass = // what should I write here to get caller class?
System.out.print(callerClass.getName());
}
}
Class A extends Base
{
public static void foo()
{
A.whosYourDaddy();
}
}
Class B extends Base
{
public static void bar()
{
B.whosYourDaddy();
}
}
And when I call:
A.foo();
B.bar();
I'd like to get output:
AB instead of BaseBase. Is it even possible with static methods (in Java 7)?
What you can do, but shouldn't :) is use the Throwable getStackTrace method. Aside from the smell, this is pretty slow, because getting the stack trace isn't that fast. But you will get an array of StackTraceElement, and each one will contain the class of teh class that is calling it (and you can also get the file and line, and if you separate the two with a : you can get a clickable link in eclipse, not that I'd ever do such a thing...).
Something like
String className = new Throwable().getStackTrace()[1].getClassName();
Hope that helps :)
private static class Reflection {
private static final SecurityManager INSTANCE = new SecurityManager();
static Class getCallClass() {
return INSTANCE.getCallClass(2);
}
private Reflection() {
}
private static class SecurityManager extends java.lang.SecurityManager {
public Class getCallClass(int i) {
Class[] classContext = getClassContext();
if (i >= 0 && i + 1 < classContext.length) {
return classContext[i + 1];
}
return null;
}
};
}
Is it even possible with static methods (in Java 7)?
No, Static methods aren't inherited. Only non-static methods are inherited.
In your case change Base (and subclasses) as follows:
class Base
{
public void whosYourDaddy()
{
Class<?> callerClass = getClass();
System.out.print(callerClass.getName());
}
}

Categories