I'm having a casting issue in this code but have no idea how to correct it.
public void showFrame(String className, Object controller) throws Exception{
try {
Class c = Class.forName("com." + className);
// "(Object.class)" I want this to be of type held in className var
// this type will be same as one passed into "controller" at runtime
Constructor ctr = c.getConstructor(Object.class);
ctr.newInstance(controller);
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "Error" );
}
}
getConstructor selects from the possible existing constructors for the class in question.
If your class name looks like:
com.mycorp.SomeClass
and it doesn't have a
public SomeClass(Object object) {
...
}
constructor, then ctr will be null. If it does have such a constructor, then asking for a new instance without providing a value for the Object parameter is just asking for trouble.
In addition, you are only catching if the class doesn't exist, not of the constructor can't be found, or if the security manager denies new class creation, or if the constructor is getting called with the wrong number of parameters, etc.
Related
I am currently trying to develop a method for invoking a specific class. The problem I am having is that I need to get the fully-qualified name or full class name when I invoke the class.
public static void testAlgorithm(String className, String methodName, long n) throws Exception
{
Class<?> myClass = null;
Object myObject = null;
try {
myClass = Class.forName(className);
myObject = myClass.newInstance();
Class<?>[] params = new Class[1];
params[0]=Long.TYPE;
Method m = myClass.getMethod(methodName, params);
m.invoke(myObject, n);
}catch(Throwable e) {
System.err.println(e);
}
}
I call it from main
try {
testAlgorithm("Algorithms", "linear", 50);
} catch (Exception e) {
e.printStackTrace();
}
I tried passing different arguments for className and I also directly modified the method inside to try to get the full class name but I didn't get anything to work. I have the class in the same project file Session01 and in the same package as well lab01.
I also checked out a similar question here.
And it leed me to also trying out:
Class currentClass = new Object() {}.getClass().getEnclosingClass();
inside the Algorithms class but I don't get the java.lang.String that I need to use for the method I am working on.
If you just want to invoke method on given class - you can always refer to it using .class so you could change parameter of your method from String className to Class<?> myClass and simply remove Class<?> myClass = null; from your method's body.
However, if you want to keep your method's signature as it is and find a class by its simple name instead of fully-qualified name - you can also do this. I could suggest usage of https://github.com/ronmamo/reflections which makes things a lot easier.
Then you can find your class using code like this:
Set<Class<? extends Object>> classes = new Reflections("packageName").getSubTypesOf(Object.class);
Class<?> myClass = classes.stream().filter(clazz -> clazz.getSimpleName().equals(className))
.findAny()
.orElseThrow(() -> new IllegalArgumentException("No class with name: " + className));
Keep in mind that you need to replace "packageName" with root package where you want to scan classes so only classes inside this package or its subpackages will be found. The less classes in a package - the faster will be the scan but you need to make sure that you class will be in the package.
Also keep in mind that you can have multiple classes with same name in different packages - this method will any of them. You can change this behaviour if you need.
You can also restrict classes to subtype of more concrete class than Object.class.
I want to intercept every setter method called on all instances of one class, and then call a method on another class object, with arguments corresponding to some fields values of each instance of the first class.
For that purpose, I want to use the ByteBuddy API, but I also want to create only one subclass for all instances of a specified class
For example, I wrote the following code :
public final class AttributesIntercepted<T> {
private static EnumMap<ResourceType, Class> attributesClasses = new EnumMap<>(ResourceType.class);
private Target target;
private T attributes;
private Resource resource;
private AttributesIntercepted(T attributes, Target target, Resource resource) {
this.attributes = attributes;
this.target = target;
this.resource = resource;
}
private T makeInstance() {
T instance = null;
try {
Class subClass;
if (!attributesClasses.containsKey(resource.getType())) {
subClass = new ByteBuddy()
.subclass(attributes.getClass())
.method(ElementMatchers.isSetter())
.intercept(SuperMethodCall.INSTANCE.andThen(
MethodCall.invoke(target.getClass().getMethod("updateResource", Resource.class))
.on(target)
.with(resource)
)).make()
.load(attributes.getClass().getClassLoader())
.getLoaded();
attributesClasses.put(resource.getType(), subClass);
} else {
subClass = attributesClasses.get(resource.getType());
}
// create the new instance of this subclass
instance = (T) (subClass.getDeclaredConstructor(attributes.getClass()).newInstance(attributes));
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
System.out.println(e.toString());
}
return instance;
}
public static<T> T create(T attributes, Target target, Resource resource) {
return (T) (new AttributesIntercepted(attributes, target, resource).makeInstance());
}
}
I save each subclass created for each resource type in a map, in order to create only one subclass for each resource type.
The problem here, is that for all instances of the subclass created, the value of the argument 'resource' passed to the method 'updateResource' called on the target object will always be the same.
It seems that the argument passed to the target object is evaluated when creating the subclass and not when calling the setters
If I just put in comments the code that save the subclasses in the map, it works, but, as i said, i only want to create one subclass for each resource type ....
Thanks for your help
You should use Byte Buddy's TypeCache and avoid your own solution, it will help you avoid some common problems.
As for your interception: define fields for these values using defineField in your DSL. Then instead of on(target), you do onField(...) and withField(...). After creating the class you now need to set those fields for any particular instance you create, this way you can reuse the class for all occasions.
I've been looking into Java reflections. This is an example from Wikipedia http://en.wikipedia.org/wiki/Reflection_(computer_programming):
// Without reflection
new Foo().hello();
// With reflection
Class<?> cls = Class.forName("Foo");
cls.getMethod("hello").invoke(cls.newInstance());
I find this a bit counter-intuitive because the method is called before creating an instance.
Reflections of course could be useful to call game leves, especially if there are hundreds of them.
EDIT - SOME SOLUTIONS:
Here is a simple example of reflection which works on Android:
try {
Class<?> clazz = Class.forName("com.test.Foo");
clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
and the class file
public class Foo {
Foo(){
hello();
}
private void hello() {
Log.e("FOO", "Hello!");
}
}
Suppose one wants to call an Activity by reflection:
Activity activity;
try {
Class<?> clazz = Class.forName("com.test.MyLevelActivity");
activity = (Activity) clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
startActivity(new Intent(this,activity.getClass()));
Suppose a level which contains data and methods should be 'loaded' by reflection:
Level currentLevel;
try {
Class<?> clazz = Class.forName("com.test.Level_1_1");
currentLevel = (Level) clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
String levelName = currentLevel.getLevelName();
String result = Integer.toString(currentLevel.processData(3, 7));
Toast.makeText(this, levelName + " result= " + result, Toast.LENGTH_LONG).show();
Here are the classes:
public abstract class Level {
public abstract String getLevelName();
public abstract int processData(int a, int b);
}
public class Level_1_1 extends Level{
private String levelName = "level 1.1";
public String getLevelName(){
return levelName;
}
public int processData(int a, int b) {
return a * b;
}
}
I find this a bit counter-intuitive because the method is called before creating an instance
Sorry, don't think so. The method arguments are first evaluated before being passed to "invoke" and hence you end up passing a "new" instance of the Foo class to the "invoke" method of the Method class. Also, in case you are wondering why call "invoke" on method object, it's because for a given class, you'd create the Method objects only once and all subsequent invocations would rather depend on the "state" of the object rather than the "method" being invoked.
here
foo.hello();
can't work, foo is just an object that does not have a method hello().
Things that are unfamiliar may seem counter-intuitive, but eventually new idioms become natural. Just go with the standard approach.
To understand it, consider that the method definition is not part of the object, you write the method once for the class, it "lives" independently of any given object. Hence it's quite reasonable for the class to say "hey method, apply yourself in the context of this object, he's one of us"
It's not really clear what you mean, but does this help?
Class<?> cls = Class.forName("Foo");
Method method = cls.getMethod("hello");
Object instance = cls.newInstance();
method.invoke(instance);
you are not calling the method first. you are just definig the method and then invoking it. also, the instance of cls is created before we actually enter invoke. I find the reflections to be a very useful API in java and it is used by almost all the framworks that work on java like struts, log4j, etc. In reflection you always define the method you wanna call and only then work on the actual object you wanna operate on.
Hope this helps!
Is it possible to get the class type from inside the static initialization block?
This is a simplified version of what I currently have::
class Person extends SuperClass {
String firstName;
static{
// This function is on the "SuperClass":
// I'd for this function to be able to get "Person.class" without me
// having to explicitly type it in but "this.class" does not work in
// a static context.
doSomeReflectionStuff(Person.class); // IN "SuperClass"
}
}
This is closer to what I am doing, which is to initialize a data structure that holds information about the object and its annotations, etc... Perhaps I am using the wrong pattern?
public abstract SuperClass{
static void doSomeReflectionStuff( Class<?> classType, List<FieldData> fieldDataList ){
Field[] fields = classType.getDeclaredFields();
for( Field field : fields ){
// Initialize fieldDataList
}
}
}
public abstract class Person {
#SomeAnnotation
String firstName;
// Holds information on each of the fields, I used a Map<String, FieldData>
// in my actual implementation to map strings to the field information, but that
// seemed a little wordy for this example
static List<FieldData> fieldDataList = new List<FieldData>();
static{
// Again, it seems dangerous to have to type in the "Person.class"
// (or Address.class, PhoneNumber.class, etc...) every time.
// Ideally, I'd liken to eliminate all this code from the Sub class
// since now I have to copy and paste it into each Sub class.
doSomeReflectionStuff(Person.class, fieldDataList);
}
}
Edit
I picked the accepted answer based on what applied best to my problem, however it seems to me that all three of the current answers have their merits.
No, it's not possible without grabbing the stacktrace (which is imo nastier than your initial approach and for which I would in any way prefer Thread#getStackTrace() above new Exception()).
Rather do that job in a non-static initializer (or the default constructor) of the abstract class where you check the initialized status.
public abstract class SuperClass {
{
if (!isInitialized(getClass())) {
initialize(getClass());
}
}
}
The called methods in turn can be safely static.
yes, I use this often to initialize a static Log variable :
e.g. :
public class Project implements Serializable, Cloneable, Comparable<Project> {
private static final Logger LOG = LoggerFactory.getLogger(Project.class);
...
To get a class at runtime, you could do something along the lines of
public class Test {
public static void main(String[] args) {
try{
throw new Exception();
}
catch(Exception e){
StackTraceElement[] sTrace = e.getStackTrace();
// sTrace[0] will be always there
String className = sTrace[0].getClassName();
System.out.println(className);
}
}
}
Not pretty but will do the job (ripped from http://www.artima.com/forums/flat.jsp?forum=1&thread=155230).
This means you still make a call from the subclass (so is in the stack trace), but you don't need to include the XXX.class as an argument.
I'd like to access the classname of the underlying class which is an instance of java.lang.reflect.Proxy.
Is this possible?
You can get the InvocationHandler with which the proxy was created, by calling Proxy.getInvocationHandler(proxy)
Note that in the case of java.lang.reflect.Proxy there is no underlying class per se. The proxy is defined by:
interface(s)
invocation handler
And the wrapped class is usually passed to the concrete invocation handler.
I found a good solution on this site (now archived):
#SuppressWarnings({"unchecked"})
protected <T> T getTargetObject(Object proxy, Class<T> targetClass) throws Exception {
if (AopUtils.isJdkDynamicProxy(proxy)) {
return (T) ((Advised)proxy).getTargetSource().getTarget();
} else {
return (T) proxy; // expected to be cglib proxy then, which is simply a specialized class
}
}
Usage
#Override
protected void onSetUp() throws Exception {
getTargetObject(fooBean, FooBeanImpl.class).setBarRepository(new MyStubBarRepository());
}
Well a Proxy instance won't be an instance of java.lang.reflect.Proxy per se. Rather, it will be an instance of a subclass of java.lang.reflect.Proxy.
Anyway, the way to get the actual proxy classes name is:
Proxy proxy = ...
System.err.println("Proxy class name is " + proxy.getClass().getCanonicalName());
However, you cannot get the name of the class that the Proxy is a proxy for, because:
you proxy interfaces not classes, and
a Proxy can be a proxy for multiple interfaces
However, from looking at the source code of the ProxyGenerator class, it seems that the interfaces are recorded in the generated proxy class as the interfaces of the class. So you should be able to get them at runtime via the proxy classes Class object; e.g.
Class<?>[] classes = proxy.getClass().getInterfaces();
(Note: I've not tried this ...)
Simple and robust:
AopUtils.getTargetClass(object).getName();
Will also work for CGLIB proxies and non-proxy objects.
Here was the solution we used with my team (we need the name of the class behind the proxy) :
if (getTargetName(yourBean) ... ) {
}
With this little helper :
private String getTargetName(final Object target) {
if (target == null) {
return "";
}
if (targetClassIsProxied(target)) {
Advised advised = (Advised) target;
try {
return advised.getTargetSource().getTarget().getClass().getCanonicalName();
} catch (Exception e) {
return "";
}
}
return target.getClass().getCanonicalName();
}
private boolean targetClassIsProxied(final Object target) {
return target.getClass().getCanonicalName().contains("$Proxy");
}
Hope it helps!
You can use the following code for retrieve the info (ArrayUtils is from Apache commons lang) about invocation handler and the interfaces of the current proxy:
String.format("[ProxyInvocationHandler: %s, Interfaces: %s]",
Proxy.getInvocationHandler(proxy).getClass().getSimpleName(),
ArrayUtils.toString(proxy.getClass().getInterfaces()));
Example result:
[ProxyInvocationHandler: ExecuteProxyChain, Interfaces: {interface com.example.api.CustomerApi}]}
I found the perfect solution for me in org.springframework.aop.framework.AopProxyUtils:
AopProxyUtils.ultimateTargetClass(object).getCanonicalName()
First of all, java.lang.reflect.Proxy works only on interfaces. The framework creates a descendant class that implements the interface(s) but extends java.lang.reflect.Proxy rather than an application class that may be of interest to you. There is no inheritance of multiple classes in modern (2016) Java.
In my case, the debugger shows that the object of interest is in the obj field in the invocation handler of the proxy object.
Object handler = Proxy.getInvocationHandler(somethingProxied);
Class handlerClass = handler.getClass();
Field objField = handlerClass.getDeclaredField("obj");
objField.setAccessible(true);
Object behindProxy = objField.get(handler);
You will have to catch() two exceptions: NoSuchFieldException and IllegalAccessException.
I found it useful to print the list of fields of declared fields from the catch() clause:
...
} catch (NoSuchFieldException nsfe) {
nsfe.printStackTrace();
Object handler = Proxy.getInvocationHandler(somethingProxied);
Class handlerClass = handler.getClass();
for (Field f : handlerClass.getDeclaredFields()) {
f.setAccessible(true);
String classAndValue = null;
try {
Object v = f.get(handler);
classAndValue= "" + (v == null ? "" : v.getClass()) + " : " + v;
} catch (IllegalAccessException iae) {
iae.printStackTrace();
}
System.out.println(" field: " + f.getName() + " = " + classAndValue+ ";");
}
...
}
Note that different frameworks use different proxies and even different techniques of proxying. The solution that worked for me may be not applicable in your case. (It definitely will not work for Javassist or Hibernate proxies.)
Static Hibernate.getClass() might be useful in this scenario.
Get the true, underlying class of a proxied persistent class
public static Class getClass(Object proxy) {
if ( proxy instanceof HibernateProxy ) {
return ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer()
.getImplementation()
.getClass();
}
else {
return proxy.getClass();
}
}